Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Document#font_style and Document#font_family #1225

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/prawn/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ def initialize(options = {}, &block)

@background = options[:background]
@background_scale = options[:background_scale] || 1
@font = nil
@font_size = 12

@bounding_box = nil
Expand Down
56 changes: 54 additions & 2 deletions lib/prawn/font.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,16 @@ class Document
# font files.
# See font_families for more information.
#
def font(name = nil, options = DEFAULT_OPTS)
return((defined?(@font) && @font) || font('Helvetica')) if name.nil?
def font(name = nil, options = nil)
return @font || font('Helvetica') if name.nil? && options.nil?

if state.pages.empty? && !state.page.in_stamp_stream?
raise Prawn::Errors::NotOnPage
end

name ||= font_family
options ||= DEFAULT_OPTS

new_font = find_font(name.to_s, options)

if block_given?
Expand All @@ -68,6 +71,51 @@ def font(name = nil, options = DEFAULT_OPTS)
@font
end

def font_family
@font ? @font.family : 'Helvetica'
end

# @method font_style(points=nil)
#
# When called with no argument, returns the current font style.
#
# When called with a single argument but no block, sets the current font
# style. When a block is used, the font style is applied transactionally and
# is rolled back when the block exits. You may still change the font style
# within a transactional block for individual text segments, or nested calls
# to font_style.
#
# Prawn::Document.generate("font_style.pdf") do
# font_style :bold
# text "Bold text"
#
# font_style(:italic) do
# text "Italic text"
# text "Bold text", :style => :bold
# text "Italic text"
# end
#
# text "Bold text"
# end
#
# Font styles are not additive, i.e. if the current style is :bold, setting
# the style to :italic results in italic, not bold-italic text. Use
# :bold_italic instead.
#
# When called without an argument, this method returns the current font
c960657 marked this conversation as resolved.
Show resolved Hide resolved
# style.
#
def font_style(style = nil, &block)
return @font ? @font.style : :normal if style.nil?

font(font.name, style: style, &block)
c960657 marked this conversation as resolved.
Show resolved Hide resolved
end

# Sets the font style
def font_style=(style = nil)
font_style(style)
end

# @method font_size(points=nil)
#
# When called with no argument, returns the current font size.
Expand Down Expand Up @@ -299,6 +347,9 @@ class Font
# The current font family
attr_reader :family

# The current font style
attr_reader :style

# The options hash used to initialize the font
attr_reader :options

Expand Down Expand Up @@ -334,6 +385,7 @@ def initialize(document, name, options = {}) #:nodoc:
@options = options

@family = options[:family]
@style = options[:style] || :normal

@identifier = generate_unique_id

Expand Down
1 change: 1 addition & 0 deletions lib/prawn/fonts/afm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def initialize(document, name, options = {}) #:nodoc:
@kern_pair_table = font_data[:kern_pair_table]
@attributes = font_data[:attributes]

@family ||= @attributes['familyname']
@ascender = @attributes['ascender'].to_i
@descender = @attributes['descender'].to_i
@line_gap = Float(bbox[3] - bbox[1]) - (@ascender - @descender)
Expand Down
1 change: 1 addition & 0 deletions lib/prawn/fonts/ttf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def initialize(document, name, options = {})
super

@ttf = read_ttf_file
@family ||= @ttf.name.font_family.first
@subsets = TTFunk::SubsetCollection.new(@ttf)
@italic_angle = nil

Expand Down
15 changes: 11 additions & 4 deletions manual/text/font.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
# If we don't pass it any arguments it will return the current font being used
# to render text.
#
# If we just pass it a font name it will use that font for rendering text
# through the rest of the document.
# If we just pass it a font name and an options hash, it will use that font for
# rendering text through the rest of the document. Both the font name and
# the options can be omitted. Valid option keys are :style and :size.
#
# It can also be used by passing a font name and a block. In this case the
# specified font will only be used to render text inside the block.
# It can also be used by passing a font name, an options hash and a block. In this
# case the specified font will only be used to render text inside the block.
#
# The default font is Helvetica.

Expand All @@ -18,6 +19,7 @@
filename = File.basename(__FILE__).gsub('.rb', '.pdf')
Prawn::ManualBuilder::Example.generate(filename) do
text "Let's see which font we are using: #{font.inspect}"
text "Family is #{font_family}, style is #{font_style}, and size is #{font_size}"

move_down 20
font 'Times-Roman'
Expand All @@ -31,6 +33,11 @@
move_down 20
text 'Written in Times again as we left the previous block.'

move_down 20
font nil, size: 16, style: :bold do
text 'Written in 16pt bold, still Times.'
end

move_down 20
text "Let's see which font we are using again: #{font.inspect}"

Expand Down
18 changes: 14 additions & 4 deletions manual/text/font_style.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# frozen_string_literal: true

# The <code>font_style</code> method works just like the <code>font</code>
# method.
#
# In fact we can even use <code>font</code> with the <code>:style</code> option
# to declare which size we want.
#
# Another way to change the font size is by supplying the <code>:style</code>
# option to the text methods.
#
# Most font families come with some styles other than normal. Most common are
# <code>bold</code>, <code>italic</code> and <code>bold_italic</code>.
#
# The style can be set the using the <code>:style</code> option, with either the
# <code>font</code> method which will set the font and style for rest of the
# document, or with the inline text methods.

require_relative '../example_helper'

Expand All @@ -20,6 +25,11 @@
styles.each do |style|
font example_font, style: style
text "I'm writing in #{example_font} (#{style})"

font_style style
text "This is also #{style}"

text "And this is also #{style}", style: style
c960657 marked this conversation as resolved.
Show resolved Hide resolved
end
end
end
133 changes: 102 additions & 31 deletions spec/prawn/font_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,109 @@
end
end

describe '#font' do
it 'allows setting of size directly when font is created' do
pdf.font 'Courier', size: 16
expect(pdf.font_size).to eq(16)
end

it 'allows temporary setting of a new font using a transaction' do
pdf.font 'Helvetica', size: 12

pdf.font 'Courier', size: 16, style: :bold do
expect(pdf.font_family).to eq('Courier')
expect(pdf.font_size).to eq(16)
expect(pdf.font_style).to eq(:bold)
end

expect(pdf.font.name).to eq('Helvetica')
expect(pdf.font_size).to eq(12)
expect(pdf.font_style).to eq(:normal)
end

it 'masks font size when using a transacation' do
pdf.font 'Courier', size: 16 do
expect(pdf.font_size).to eq(16)
end

pdf.font 'Times-Roman'
pdf.font 'Courier'

expect(pdf.font_size).to eq(12)
end
end

describe '#font_size' do
it 'returns default font size' do
expect(pdf.font_size).to eq(12)
end

it 'allows setting font size in DSL style' do
pdf.font_size 20
expect(pdf.font_size).to eq(20)
end

it 'allows setting font size in DSL style using a transaction' do
pdf.font_size 20 do
expect(pdf.font_size).to eq(20)
end

expect(pdf.font_size).to eq(12)
end

it 'allows setting font size as assignment' do
pdf.font_size = 20
expect(pdf.font_size).to eq(20)
end
end

describe '#font_style' do
it 'returns default font style' do
expect(pdf.font_style).to eq(:normal)
end

it 'allows setting font style in DSL style' do
expect(pdf.font_style).to eq(:normal)
c960657 marked this conversation as resolved.
Show resolved Hide resolved
pdf.font_style :bold
expect(pdf.font_style).to eq(:bold)
expect(pdf.font.name).to eq('Helvetica-Bold')
end

it 'allows setting font style in DSL style using a transaction' do
pdf.font_style :bold do
expect(pdf.font_style).to eq(:bold)
expect(pdf.font.name).to eq('Helvetica-Bold')
end

expect(pdf.font_style).to eq(:normal)
expect(pdf.font.name).to eq('Helvetica')
end

it 'allows setting font style as assignment' do
pdf.font_style = :bold
expect(pdf.font_style).to eq(:bold)
end
end

describe '#font_family' do
it 'returns default font family' do
expect(pdf.font_family).to eq('Helvetica')
end

it 'returns font family' do
pdf.font 'Courier', style: :bold
expect(pdf.font_family).to eq('Courier')
end

it 'returns font family for AFM font' do
pdf.font 'ZapfDingbats'
expect(pdf.font_family).to eq('ZapfDingbats')
end

it 'returns font family for TTF font' do
pdf.font "#{Prawn::DATADIR}/fonts/DejaVuSans-Bold.ttf"
expect(pdf.font_family).to eq('DejaVu Sans')
end
end

describe 'font style support' do
Expand All @@ -142,11 +240,14 @@
pdf.font 'Helvetica'
pdf.text 'In Normal Helvetica'

pdf.font nil, style: :bold
pdf.text 'In Bold Helvetica'

text = PDF::Inspector::Text.analyze(pdf.render)
expect(text.font_settings.map { |e| e[:name] }).to eq(
%i[
Courier-Bold Courier-BoldOblique Courier-Oblique
Courier Helvetica
Courier Helvetica Helvetica-Bold
]
)
end
Expand Down Expand Up @@ -233,36 +334,6 @@
end
end

describe 'Transactional font handling' do
it 'allows setting of size directly when font is created' do
pdf.font 'Courier', size: 16
expect(pdf.font_size).to eq(16)
end

it 'allows temporary setting of a new font using a transaction' do
pdf.font 'Helvetica', size: 12

pdf.font 'Courier', size: 16 do
expect(pdf.font.name).to eq('Courier')
expect(pdf.font_size).to eq(16)
end

expect(pdf.font.name).to eq('Helvetica')
expect(pdf.font_size).to eq(12)
end

it 'masks font size when using a transacation' do
pdf.font 'Courier', size: 16 do
expect(pdf.font_size).to eq(16)
end

pdf.font 'Times-Roman'
pdf.font 'Courier'

expect(pdf.font_size).to eq(12)
end
end

describe 'Document#page_fonts' do
it 'registers fonts properly by page' do
pdf.font 'Courier'
Expand Down