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 all commits
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
73 changes: 66 additions & 7 deletions lib/prawn/font.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,15 @@ 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

new_font = find_font(name.to_s, options)
options ||= DEFAULT_OPTS
new_font = find_font(name, options)

if block_given?
save_font do
Expand All @@ -68,6 +69,54 @@ def font(name = nil, options = DEFAULT_OPTS)
@font
end

# Returns the family name of the current font, if the font was selected using
# a font family name, or nil, if the font was specified as a specific built-in
# font or a TTF file.
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.
#
# Font style can only be applied, if the current font is specified using a
# font family name, not a specific built-in font or TTF file.
#
def font_style(style = nil, &block)
return @font ? @font.style : :normal if style.nil?

font(nil, style: style, &block)
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 All @@ -91,9 +140,6 @@ def font(name = nil, options = DEFAULT_OPTS)
# text "At size 16"
# end
#
# When called without an argument, this method returns the current font
# size.
#
def font_size(points = nil)
return @font_size unless points

Expand Down Expand Up @@ -237,13 +283,22 @@ def save_font
#
# @private
def find_font(name, options = {}) #:nodoc:
name ||= font_family || font.name
style = options[:style] || :normal
if font_families.key?(name)
family = name
name = font_families[name][options[:style] || :normal]
if !font_families[family].key?(style)
raise Prawn::Errors::UnknownFont,
"Font family `#{family}` has no `:#{style}` style."
end
name = font_families[family][style]
if name.is_a?(::Hash)
options = options.merge(name)
name = options[:file]
end
elsif style != :normal
options[:style] = :normal
warn "Style not supported for `#{name}`."
end
key = "#{name}:#{options[:font] || 0}"

Expand Down Expand Up @@ -299,6 +354,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 +392,7 @@ def initialize(document, name, options = {}) #:nodoc:
@options = options

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

@identifier = generate_unique_id

Expand Down
2 changes: 1 addition & 1 deletion lib/prawn/font_metric_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def width_of(string, options)
f =
if options[:style]
# override style with :style => :bold
@document.find_font(@document.font.family, style: options[:style])
@document.find_font(nil, style: options[:style])
else
@document.font
end
Expand Down
2 changes: 1 addition & 1 deletion lib/prawn/fonts/afm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def initialize(document, name, options = {}) #:nodoc:
name ||= options[:family]
unless BUILT_INS.include?(name)
raise Prawn::Errors::UnknownFont,
"#{name} (#{options[:style] || 'normal'}) is not a known font."
"`#{name}` is not a known font."
end

super
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
50 changes: 38 additions & 12 deletions manual/text/font_style.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,51 @@
# 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'

filename = File.basename(__FILE__).gsub('.rb', '.pdf')
Prawn::ManualBuilder::Example.generate(filename) do
fonts = %w[Courier Helvetica Times-Roman]
styles = %i[bold bold_italic italic normal]
text "The default style is normal"

move_down 10
font_style :bold
text 'This is bold'

fonts.each do |example_font|
move_down 20
move_down 10
font_style :italic
text 'This is italic (not bold, i.e. existing style is overwritten)'

styles.each do |style|
font example_font, style: style
text "I'm writing in #{example_font} (#{style})"
end
move_down 10
font_style :bold_italic
text 'This is bold italic'

move_down 10
font_style :normal
text 'Back to normal'

move_down 10
text 'A single line of italic', style: :italic

move_down 10
font_style :bold do
text 'A single line of bold'
end

move_down 10
font 'Courier', style: :bold_italic
text 'This is Courier bold italic'

font 'Courier'
text 'This is Courier normal (style is reset when changing font)'
end
Loading