lib/prawn/text/formatted/box.rb in prawn-0.12.0 vs lib/prawn/text/formatted/box.rb in prawn-0.13.0

- old
+ new

@@ -43,14 +43,23 @@ # a URL to which to create a link. A clickable link will be created # to that URL. Note that you must explicitly underline and color using # the appropriate tags if you which to draw attention to the link # <tt>:anchor</tt>:: # a destination that has already been or will be registered using - # Prawn::Core::Destinations#add_dest. A clickable link will be + # PDF::Core::Destinations#add_dest. A clickable link will be # created to that destination. Note that you must explicitly underline # and color using the appropriate tags if you which to draw attention # to the link + # <tt>:local</tt>:: + # a file or application to be opened locally. A clickable link will be + # created to the provided local file or application. If the file is + # another PDF, it will be opened in a new window. Note that you must + # explicitly underline and color using the appropriate tags if you which + # to draw attention to the link + # <tt>:draw_text_callback</tt>: + # if provided, this Proc will be called instead of #draw_text! once + # per fragment for every low-level addition of text to the page. # <tt>:callback</tt>:: # an object (or array of such objects) with two methods: # #render_behind and #render_in_front, which are called immediately # prior to and immediately after rendring the text fragment and which # are passed the fragment as an argument @@ -87,23 +96,24 @@ # conjunction with #render(:dry_run => true) enables one to do look-ahead # calculations prior to placing text on the page, or to determine how much # vertical space was consumed by the printed text # class Box - include Prawn::Core::Text::Formatted::Wrap + include Prawn::Text::Formatted::Wrap def valid_options - Prawn::Core::Text::VALID_OPTIONS + [:at, :height, :width, + PDF::Core::Text::VALID_OPTIONS + [:at, :height, :width, :align, :valign, :rotate, :rotate_around, :overflow, :min_font_size, :leading, :character_spacing, :mode, :single_line, :skip_encoding, :document, :direction, - :fallback_fonts] + :fallback_fonts, + :draw_text_callback] end # The text that was successfully printed (or, if <tt>dry_run</tt> was # used, the text that would have been successfully printed) attr_reader :text @@ -137,12 +147,12 @@ # # Example (see Prawn::Text::Core::Formatted::Wrap for what is required # of the wrap method if you want to override the default wrapping # algorithm): - # # + # # module MyWrap # # def wrap(array) # initialize_wrap([{ :text => 'all your base are belong to us' }]) # @line_wrap.wrap_line(:document => @document, @@ -203,11 +213,17 @@ @mode = options[:mode] || @document.text_rendering_mode @rotate = options[:rotate] || 0 @rotate_around = options[:rotate_around] || :upper_left @single_line = options[:single_line] @skip_encoding = options[:skip_encoding] || @document.skip_encoding + @draw_text_callback = options[:draw_text_callback] + # if the text rendering mode is :unknown, force it back to :fill + if @mode == :unknown + @mode = :fill + end + if @overflow == :expand # if set to expand, then we simply set the bottom # as the bottom of the document bounds, since that # is the maximum we should expand to @height = default_height @@ -271,11 +287,11 @@ def available_width @width end # The height actually used during the previous <tt>render</tt> - # + # def height return 0 if @baseline_y.nil? || @descender.nil? (@baseline_y - @descender).abs end @@ -308,12 +324,17 @@ if @inked draw_fragment_underlays(fragment) @document.word_spacing(word_spacing) { - @document.draw_text!(fragment.text, :at => [x, y], - :kerning => @kerning) + if @draw_text_callback + @draw_text_callback.call(fragment.text, :at => [x, y], + :kerning => @kerning) + else + @document.draw_text!(fragment.text, :at => [x, y], + :kerning => @kerning) + end } draw_fragment_overlays(fragment) end end @@ -369,12 +390,11 @@ fallback_fonts = @fallback_fonts.dup # always default back to the current font if the glyph is missing from # all fonts fallback_fonts << fragment_font - hash[:text].unpack("U*").each do |char_int| - char = [char_int].pack("U") + hash[:text].unicode_characters do |char| @document.font(fragment_font) font_glyph_pairs << [find_font_for_this_glyph(char, @document.font.family, fallback_fonts.dup), char] @@ -435,18 +455,25 @@ @at[1] + @document.bounds.absolute_bottom - frame.absolute_bottom end def process_vertical_alignment(text) + # The vertical alignment must only be done once per text box, but + # we need to wait until render() is called so that the fonts are set + # up properly for wrapping. So guard with a boolean to ensure this is + # only run once. + return if defined?(@vertical_alignment_processed) && @vertical_alignment_processed + @vertical_alignment_processed = true + return if @vertical_align == :top wrap(text) case @vertical_align when :center @at[1] = @at[1] - (@height - height) * 0.5 when :bottom - @at[1] = @at[1] - (@height - height) + @at[1] = @at[1] - (@height - height) + @descender end @height = height end # Decrease the font size until the text fits or the min font @@ -503,10 +530,11 @@ def draw_fragment_overlays(fragment) draw_fragment_overlay_styles(fragment) draw_fragment_overlay_link(fragment) draw_fragment_overlay_anchor(fragment) + draw_fragment_overlay_local(fragment) fragment.callback_objects.each do |obj| obj.render_in_front(fragment) if obj.respond_to?(:render_in_front) end end @@ -515,26 +543,37 @@ box = fragment.absolute_bounding_box @document.link_annotation(box, :Border => [0, 0, 0], :A => { :Type => :Action, :S => :URI, - :URI => Prawn::Core::LiteralString.new(fragment.link) }) + :URI => PDF::Core::LiteralString.new(fragment.link) }) end def draw_fragment_overlay_anchor(fragment) return unless fragment.anchor box = fragment.absolute_bounding_box @document.link_annotation(box, :Border => [0, 0, 0], :Dest => fragment.anchor) end + def draw_fragment_overlay_local(fragment) + return unless fragment.local + box = fragment.absolute_bounding_box + @document.link_annotation(box, + :Border => [0, 0, 0], + :A => { :Type => :Action, + :S => :Launch, + :F => PDF::Core::LiteralString.new(fragment.local), + :NewWindow => true }) + end + def draw_fragment_overlay_styles(fragment) underline = fragment.styles.include?(:underline) if underline @document.stroke_line(fragment.underline_points) end - + strikethrough = fragment.styles.include?(:strikethrough) if strikethrough @document.stroke_line(fragment.strikethrough_points) end end