diff --git a/examples/text/rendering_mode.rb b/examples/text/rendering_mode.rb new file mode 100644 index 000000000..97905fe1d --- /dev/null +++ b/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 diff --git a/lib/prawn/core/text.rb b/lib/prawn/core/text.rb index 8bf3cedc6..c6997d122 100644 --- a/lib/prawn/core/text.rb +++ b/lib/prawn/core/text.rb @@ -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. diff --git a/lib/prawn/text/box.rb b/lib/prawn/text/box.rb index 9fc181dff..bcd0248fc 100644 --- a/lib/prawn/text/box.rb +++ b/lib/prawn/text/box.rb @@ -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 @@ -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] @@ -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 @@ -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 diff --git a/spec/text_box_spec.rb b/spec/text_box_spec.rb index 2e4230e94..1523115bd 100644 --- a/spec/text_box_spec.rb +++ b/spec/text_box_spec.rb @@ -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 diff --git a/spec/text_rendering_mode_spec.rb b/spec/text_rendering_mode_spec.rb new file mode 100644 index 000000000..6fdd80e56 --- /dev/null +++ b/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