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

Horizontal text scaling #1107

Open
wants to merge 3 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
5 changes: 3 additions & 2 deletions lib/prawn/font_metric_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ def width_of(string, options)

length = @cache[key]

length +
(length +
(@document.character_spacing *
@document.font.character_count(encoded_string))
@document.font.character_count(encoded_string))) *
(@document.horizontal_text_scaling / 100.0)
end
end
end
3 changes: 3 additions & 0 deletions lib/prawn/text/box.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ module Text
# <tt>:character_spacing</tt>:: <tt>number</tt>. The amount of space to add
# to or remove from the default character
# spacing. [0]
# <tt>:horizontal_text_scaling</tt>:: <tt>number</tt>. The amount as a
# percentage by which to scale the text
# horizontally. [100]
# <tt>:disable_wrap_by_char</tt>:: <tt>boolean</tt> Whether
# or not to prevent mid-word breaks when text does not fit in box. [false]
# <tt>:mode</tt>:: <tt>symbol</tt>. The text rendering mode. See
Expand Down
20 changes: 13 additions & 7 deletions lib/prawn/text/formatted/arranger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,25 +156,31 @@ def apply_font_settings(fragment = nil, &block)
size = current_format_state[:size]
character_spacing = current_format_state[:character_spacing] ||
@document.character_spacing
horizontal_text_scaling =
current_format_state[:horizontal_text_scaling] ||
@document.horizontal_text_scaling
styles = current_format_state[:styles]
else
font = fragment.font
size = fragment.size
character_spacing = fragment.character_spacing
horizontal_text_scaling = fragment.horizontal_text_scaling
styles = fragment.styles
end
font_style = font_style(styles)

@document.character_spacing(character_spacing) do
if font || font_style != :normal
raise 'Bad font family' unless @document.font.family
@document.font(
font || @document.font.family, style: font_style
) do
@document.horizontal_text_scaling(horizontal_text_scaling) do
if font || font_style != :normal
raise 'Bad font family' unless @document.font.family
@document.font(
font || @document.font.family, style: font_style
) do
apply_font_size(size, styles, &block)
end
else
apply_font_size(size, styles, &block)
end
else
apply_font_size(size, styles, &block)
end
end
end
Expand Down
39 changes: 23 additions & 16 deletions lib/prawn/text/formatted/box.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ module Formatted
# <tt>:character_spacing</tt>::
# a number denoting how much to increase or decrease the default
# spacing between characters
# <tt>:horizontal_text_scaling</tt>::
# The amount as a percentage by which to scale the text
# horizontally. [100]
# <tt>:font</tt>::
# the name of a font. The name must be an AFM font with the desired
# faces or must be a font that is already registered using
Expand Down Expand Up @@ -166,6 +169,8 @@ def initialize(formatted_text, options = {})
@leading = options[:leading] || @document.default_leading
@character_spacing = options[:character_spacing] ||
@document.character_spacing
@horizontal_text_scaling = options[:horizontal_text_scaling] ||
@document.horizontal_text_scaling
@mode = options[:mode] || @document.text_rendering_mode
@rotate = options[:rotate] || 0
@rotate_around = options[:rotate_around] || :upper_left
Expand Down Expand Up @@ -213,21 +218,23 @@ def render(flags = {})

@document.save_font do
@document.character_spacing(@character_spacing) do
@document.text_rendering_mode(@mode) do
process_options

text = normalized_text(flags)

@document.font_size(@font_size) do
shrink_to_fit(text) if @overflow == :shrink_to_fit
process_vertical_alignment(text)
@inked = true unless flags[:dry_run]
unprinted_text = if @rotate != 0 && @inked
render_rotated(text)
else
wrap(text)
end
@inked = false
@document.horizontal_text_scaling(@horizontal_text_scaling) do
@document.text_rendering_mode(@mode) do
process_options

text = normalized_text(flags)

@document.font_size(@font_size) do
shrink_to_fit(text) if @overflow == :shrink_to_fit
process_vertical_alignment(text)
@inked = true unless flags[:dry_run]
unprinted_text = if @rotate != 0 && @inked
render_rotated(text)
else
wrap(text)
end
@inked = false
end
end
end
end
Expand Down Expand Up @@ -350,7 +357,7 @@ def valid_options
:rotate, :rotate_around,
:overflow, :min_font_size,
:disable_wrap_by_char,
:leading, :character_spacing,
:leading, :character_spacing, :horizontal_text_scaling,
:mode, :single_line,
:document,
:direction,
Expand Down
5 changes: 5 additions & 0 deletions lib/prawn/text/formatted/fragment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ def character_spacing
@document.character_spacing
end

def horizontal_text_scaling
@format_state[:horizontal_text_scaling] ||
@document.horizontal_text_scaling
end

def direction
@format_state[:direction]
end
Expand Down
20 changes: 17 additions & 3 deletions lib/prawn/text/formatted/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,15 @@ def self.to_string(array)
else
character_spacing = nil
end
if font || size || character_spacing
prefix += "<font#{font}#{size}#{character_spacing}>"
if hash[:horizontal_text_scaling]
horizontal_text_scaling =
" horizontal_text_scaling='#{hash[:horizontal_text_scaling]}'"
else
horizontal_text_scaling = nil
end
if font || size || character_spacing || horizontal_text_scaling
prefix += "<font#{font}#{size}#{character_spacing}"\
"#{horizontal_text_scaling}>"
suffix = '</font>'
end

Expand Down Expand Up @@ -133,6 +140,7 @@ def self.array_from_tokens(tokens)
fonts = []
sizes = []
character_spacings = []
horizontal_text_scalings = []

tokens.each do |token|
case token
Expand Down Expand Up @@ -170,6 +178,7 @@ def self.array_from_tokens(tokens)
fonts.pop
sizes.pop
character_spacings.pop
horizontal_text_scalings.pop
when /^<link[^>]*>$/, /^<a[^>]*>$/
matches = /href="([^"]*)"/.match(token) ||
/href='([^']*)'/.match(token)
Expand Down Expand Up @@ -220,6 +229,10 @@ def self.array_from_tokens(tokens)
matches = /character_spacing="([^"]*)"/.match(token) ||
/character_spacing='([^']*)'/.match(token)
character_spacings << matches[1].to_f unless matches.nil?

matches = /horizontal_text_scaling="([^"]*)"/.match(token) ||
/horizontal_text_scaling='([^']*)'/.match(token)
horizontal_text_scalings << matches[1].to_f unless matches.nil?
else
string = token.gsub('&lt;', '<').gsub('&gt;', '>')
.gsub('&amp;', '&')
Expand All @@ -232,7 +245,8 @@ def self.array_from_tokens(tokens)
anchor: anchor,
font: fonts.last,
size: sizes.last,
character_spacing: character_spacings.last
character_spacing: character_spacings.last,
horizontal_text_scaling: horizontal_text_scalings.last
}
end
end
Expand Down
2 changes: 1 addition & 1 deletion prawn.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Gem::Specification.new do |spec|
spec.add_dependency('ttfunk', '~> 1.5')
spec.add_dependency('pdf-core', '~> 0.8.1')

spec.add_development_dependency('pdf-inspector', '>= 1.2.1', '< 2.0.a')
spec.add_development_dependency('pdf-inspector', '>= 1.3.0', '< 2.0.a')
spec.add_development_dependency('yard')
spec.add_development_dependency('rspec', '~> 3.0')
spec.add_development_dependency('rake', '~> 12.0')
Expand Down
35 changes: 34 additions & 1 deletion spec/prawn/document_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ def self.format(string)
local: nil,
font: nil,
size: nil,
character_spacing: nil
character_spacing: nil,
horizontal_text_scaling: nil
}
]
end
Expand Down Expand Up @@ -798,4 +799,36 @@ def self.format(string)
.to eq([1, 3, 6, 9])
end
end

describe '#horizontal_text_scaling' do
it 'draws the horizontal text scaling to the document' do
pdf.horizontal_text_scaling(110) do
pdf.text('hello world')
end
contents = PDF::Inspector::Text.analyze(pdf.render)
expect(contents.horizontal_text_scaling.first).to eq(110)
end
it 'should not draw the horizontal text scaling to the document' \
' when the new horizontal text scaling matches the old' do
pdf.horizontal_text_scaling(100) do
pdf.text('hello world')
end
contents = PDF::Inspector::Text.analyze(pdf.render)
expect(contents.horizontal_text_scaling).to be_empty
end
it 'restores horizontal text scaling to 100' do
pdf.horizontal_text_scaling(110) do
pdf.text('hello world')
end
contents = PDF::Inspector::Text.analyze(pdf.render)
expect(contents.horizontal_text_scaling.last).to eq(100)
end
it 'functions as an accessor when no parameter given' do
pdf.horizontal_text_scaling(110) do
pdf.text('hello world')
expect(pdf.horizontal_text_scaling).to eq(110)
end
expect(pdf.horizontal_text_scaling).to eq(100)
end
end
end
7 changes: 7 additions & 0 deletions spec/prawn/font_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@
end
end

it 'takes horizontal text scaling into account' do
original_width = pdf.width_of('hello world')
pdf.horizontal_text_scaling(110) do
expect(pdf.width_of('hello world')).to eq(original_width * 1.1)
end
end

it 'excludes newlines' do
# Use a TTF font that has a non-zero width for \n
pdf.font("#{Prawn::DATADIR}/fonts/gkai00mp.ttf")
Expand Down
23 changes: 23 additions & 0 deletions spec/prawn/text/box_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,29 @@
end
end

describe '#render with :horizontal_text_scaling option' do
it 'draws the horizontal text scaling to the document' do
string = 'hello world'
options = { document: pdf, horizontal_text_scaling: 110 }
text_box = described_class.new(string, options)
text_box.render
contents = PDF::Inspector::Text.analyze(pdf.render)
expect(contents.horizontal_text_scaling[0]).to eq(110)
end
it 'takes horizontal text scaling into account when wrapping' do
pdf.font 'Courier'
text_box = described_class.new(
'hello world',
width: 100,
overflow: :expand,
horizontal_text_scaling: 150,
document: pdf
)
text_box.render
expect(text_box.text).to eq("hello\nworld")
end
end

describe 'wrapping' do
it 'wraps text' do
text = 'Please wrap this text about HERE. ' \
Expand Down
57 changes: 57 additions & 0 deletions spec/prawn/text/formatted/arranger_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,63 @@
end
end

describe '#line_width with horizontal_text_scaling > 100' do
it 'returns a width greater than a line without a '\
'horizontal_text_scaling' do
array = [
{ text: 'hello ' },
{ text: 'world', styles: [:bold] }
]
arranger.format_array = array
while arranger.next_string
end
arranger.finalize_line

base_line_width = arranger.line_width

array = [
{ text: 'hello ' },
{
text: 'world', styles: [:bold],
horizontal_text_scaling: 110
}
]
arranger.format_array = array
while arranger.next_string
end
arranger.finalize_line
expect(arranger.line_width).to be > base_line_width
end
end

describe '#line_width with horizontal_text_scaling < 100' do
it 'returns a width less than a line without a horizontal_text_scaling' do
array = [
{ text: 'hello ' },
{ text: 'world', styles: [:bold] }
]
arranger.format_array = array
while arranger.next_string
end
arranger.finalize_line

base_line_width = arranger.line_width

array = [
{ text: 'hello ' },
{
text: 'world', styles: [:bold],
horizontal_text_scaling: 90
}
]
arranger.format_array = array
while arranger.next_string
end
arranger.finalize_line
expect(arranger.line_width).to be < base_line_width
end
end

describe '#line' do
before do
array = [
Expand Down
31 changes: 31 additions & 0 deletions spec/prawn/text/formatted/box_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,37 @@
end
end

describe 'Text::Formatted::Box#render with fragment level '\
':horizontal_text_scaling option' do
it 'draws the horizontal text scaling to the document' do
array = [{
text: 'hello world',
horizontal_text_scaling: 110
}]
options = { document: pdf }
text_box = described_class.new(array, options)
text_box.render
contents = PDF::Inspector::Text.analyze(pdf.render)
expect(contents.horizontal_text_scaling[0]).to eq(110)
end

it 'lays out text properly' do
array = [{
text: 'hello world',
font: 'Courier',
horizontal_text_scaling: 150
}]
options = {
document: pdf,
width: 100,
overflow: :expand
}
text_box = described_class.new(array, options)
text_box.render
expect(text_box.text).to eq("hello\nworld")
end
end

describe 'Text::Formatted::Box#render with :align => :justify' do
it 'does not justify the last line of a paragraph' do
array = [
Expand Down
Loading