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