Skip to content

Commit

Permalink
Add support for modifying the text rendering mode
Browse files Browse the repository at this point in the history
* Block form is available via the Prawn::Document#text_rendering_mode()
  method
* Inline for is available as the :mode option to the
  Prawn::Document#text() method
  • Loading branch information
yob committed Nov 1, 2010
1 parent 0e9df5c commit e6177bb
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 18 deletions.
21 changes: 21 additions & 0 deletions examples/text/rendering_mode.rb
@@ -0,0 +1,21 @@
# encoding: utf-8
#
# Example of character spacing
#
#
require File.expand_path(File.join(File.dirname(__FILE__),
%w[.. example_helper]))

Prawn::Document.generate "rendering_mode.pdf" do |pdf|
pdf.fill_color "00ff00"
pdf.stroke_color "0000ff"

# inline rendering mode
pdf.text("Inline mode", :mode => 1, :size => 40)

# block rendering mode
pdf.text_rendering_mode(1) do
pdf.text("Block", :size => 30)
pdf.text("Mode", :size => 30)
end
end
37 changes: 37 additions & 0 deletions lib/prawn/core/text.rb
Expand Up @@ -73,6 +73,43 @@ def default_leading(number)

alias_method :default_leading=, :default_leading

# Call with no argument to retrieve the current text rendering mode.
#
# Call with an integer and block to temporarily change the current
# text rendering mode.
#
# pdf.text_rendering_mode(1) do
# pdf.text("Outlined Text")
# end
#
# Valid modes are:
#
# * 0 - fill text (default)
# * 1 - stroke text
# * 2 - fill, then stroke text
# * 3 - invisible text
# * 4 - fill text then add to path for clipping
# * 5 - stroke text then add to path for clipping
# * 6 - fill then stroke text, then add to path for clipping
# * 7 - add text to path for clipping
#
def text_rendering_mode(mode=nil)
return @text_rendering_mode || 0 if mode.nil?
if mode.to_i < 0 || mode.to_i > 7
raise ArgumentError, "mode must be between 0 and 7"
end
original_mode = text_rendering_mode
if original_mode == mode
yield
else
@text_rendering_mode = mode
add_content "\n#{mode} Tr"
yield
add_content "\n#{original_mode} Tr"
@text_rendering_mode = original_mode
end
end

# Increases or decreases the space between characters.
# For horizontal text, a positive value will increase the space.
# For veritical text, a positive value will decrease the space.
Expand Down
41 changes: 23 additions & 18 deletions lib/prawn/text/box.rb
Expand Up @@ -109,7 +109,7 @@ def valid_options
:rotate, :rotate_around,
:overflow, :min_font_size,
:leading, :character_spacing,
:single_line,
:mode, :single_line,
:skip_encoding,
:document]
end
Expand Down Expand Up @@ -189,6 +189,7 @@ def initialize(text, options={})
@leading = options[:leading] || @document.default_leading?
@character_spacing = options[:character_spacing] ||
@document.character_spacing
@mode = options[:mode] || @document.text_rendering_mode
@rotate = options[:rotate] || 0
@rotate_around = options[:rotate_around] || :upper_left
@single_line = options[:single_line]
Expand Down Expand Up @@ -226,24 +227,26 @@ def render(flags={})
unprinted_text = ''
@document.save_font do
@document.character_spacing(@character_spacing) do
process_options
@document.text_rendering_mode(@mode) do
process_options

if @skip_encoding
text = original_text
else
text = normalize_encoding
end

@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]
if @rotate != 0 && @inked
unprinted_text = render_rotated(text)
if @skip_encoding
text = original_text
else
unprinted_text = wrap(text)
text = normalize_encoding
end

@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]
if @rotate != 0 && @inked
unprinted_text = render_rotated(text)
else
unprinted_text = wrap(text)
end
@inked = false
end
@inked = false
end
end
end
Expand Down Expand Up @@ -285,8 +288,10 @@ def draw_line(line_to_print, line_width=0, word_spacing=0, include_ellipses=fals
if @inked
@document.word_spacing(word_spacing) {
@document.character_spacing(@character_spacing) {
@document.draw_text!(line_to_print, :at => [x, y],
:kerning => @kerning)
@document.text_rendering_mode(@mode) {
@document.draw_text!(line_to_print, :at => [x, y],
:kerning => @kerning)
}
}
}
end
Expand Down
12 changes: 12 additions & 0 deletions spec/text_box_spec.rb
Expand Up @@ -760,6 +760,18 @@

end

describe "Text::Box#render with :mode option" do
it "should alter the text rendering mode of the document" do
create_pdf
string = "hello world"
options = { :document => @pdf, :mode => 2 }
text_box = Prawn::Text::Box.new(string, options)
text_box.render
contents = PDF::Inspector::Text.analyze(@pdf.render)
contents.text_rendering_mode.should == [2,0]
end
end

def reduce_precision(float)
("%.5f" % float).to_f
end
Expand Down
44 changes: 44 additions & 0 deletions spec/text_rendering_mode_spec.rb
@@ -0,0 +1,44 @@
# encoding: utf-8

require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")

describe "#text_rendering_mode" do
it "should draw the text rendering mode to the document" do
create_pdf
@pdf.text_rendering_mode(1) do
@pdf.text("hello world")
end
contents = PDF::Inspector::Text.analyze(@pdf.render)
contents.text_rendering_mode.first.should == 1
end
it "should not draw the text rendering mode to the document" +
" when the new mode matches the old" do
create_pdf
@pdf.text_rendering_mode(0) do
@pdf.text("hello world")
end
contents = PDF::Inspector::Text.analyze(@pdf.render)
contents.text_rendering_mode.should.be.empty
end
it "should restore character spacing to 0" do
create_pdf
@pdf.text_rendering_mode(1) do
@pdf.text("hello world")
end
contents = PDF::Inspector::Text.analyze(@pdf.render)
contents.text_rendering_mode.should == [1,0]
end
it "should function as an accessor when no parameter given" do
create_pdf
@pdf.text_rendering_mode(2) do
@pdf.text("hello world")
@pdf.text_rendering_mode.should == 2
end
@pdf.text_rendering_mode.should == 0
end
it "should raise an exception when passed a value < 0 or > 7" do
create_pdf
lambda { @pdf.text_rendering_mode(-1) }.should raise_error(ArgumentError)
lambda { @pdf.text_rendering_mode(8) }.should raise_error(ArgumentError)
end
end

0 comments on commit e6177bb

Please sign in to comment.