lib/prawn/document/text.rb in prawn-0.2.3 vs lib/prawn/document/text.rb in prawn-0.3.0

- old
+ new

@@ -4,14 +4,16 @@ # # Copyright May 2008, Gregory Brown. All Rights Reserved. # # This is free software. Please see the LICENSE and COPYING files for details. require "zlib" +require "prawn/document/text/box" module Prawn class Document module Text + # Draws text on the page. If a point is specified via the +:at+ # option the text will begin exactly at that point, and the string is # assumed to be pre-formatted to properly fit the page. # # pdf.text "Hello World", :at => [100,100] @@ -35,19 +37,49 @@ # # If your font contains kerning pairs data that Prawn can parse, the # text will be kerned by default. You can disable this feature by passing # <tt>:kerning => false</tt>. # - # === Character Encoding Details: + # === Text Positioning Details: # + # When using the :at parameter, Prawn will position your text by its + # baseline, and flow along a single line. + # + # When using automatic text flow, Prawn currently does a bunch of nasty + # hacks to get things to position nicely in bounding boxes, table cells, + # etc. + # + # For AFM fonts, the first line of text is positioned font.height below + # the baseline. + # + # For TTF fonts, the first line is possitioned font.ascender below the + # baseline. + # + # The issue here is that there are complex issues with determining the + # size of the glyphs above and below the baseline in TTF that we haven't + # figured out yet, and that AFM and TTF appear to handle things very + # differently. + # + # The moral of the story is that if you want reliable font positioning + # for your advanced needs, use :at, otherwise, just let Prawn do its + # positioning magic for you, or investigate and help us get rid of this + # ugly issue. + # + # == Rotation + # + # Text can be rotated before it is placed on the canvas by specifying the + # :rotate option. Rotation occurs counter-clockwise. + # + # == Encoding + # # Note that strings passed to this function should be encoded as UTF-8. # If you get unexpected characters appearing in your rendered document, # check this. # # If the current font is a built-in one, although the string must be - # encoded as UTF-8, only characters that are available in ISO-8859-1 - # are allowed (transliteration will be attempted). + # encoded as UTF-8, only characters that are available in WinAnsi + # are allowed. # # If an empty box is rendered to your PDF instead of the character you # wanted it usually means the current font doesn't include that character. # def text(text,options={}) @@ -65,10 +97,13 @@ if options[:at] x,y = translate(options[:at]) font.size(options[:size]) { add_text_content(text,x,y,options) } else + if options[:rotate] + raise ArgumentError, "Rotated text may only be used with :at" + end wrapped_text(text,options) end font(original_font) end @@ -84,11 +119,11 @@ private def process_text_options(options) Prawn.verify_options [:style, :kerning, :size, :at, :wrap, - :spacing, :align ], options + :spacing, :align, :rotate ], options if options[:style] raise "Bad font family" unless font.family font(font.family,:style => options[:style]) end @@ -113,14 +148,18 @@ font.size(options[:size]) do text = font.metrics.naive_wrap(text, bounds.right, font.size, :kerning => options[:kerning], :mode => options[:wrap]) - lines = text.lines + lines = text.lines.to_a - lines.each do |e| - move_text_position( font.height + font.descender ) + lines.each_with_index do |e,i| + if font.metrics.type0? + move_text_position(font.ascender) + else + move_text_position(font.height) + end line_width = font.width_of(e) case(options[:align]) when :left x = @bounding_box.absolute_left @@ -130,29 +169,35 @@ when :right x = @bounding_box.absolute_right - line_width end add_text_content(e,x,y,options) - move_text_position(options[:spacing] || -font.descender ) + + if font.metrics.type0? && i < lines.length - 1 + move_text_position(font.height - font.ascender) + end + + move_text_position(options[:spacing]) if options[:spacing] end end end - + def add_text_content(text, x, y, options) text = font.metrics.convert_text(text,options) - add_content %Q{ - BT - /#{font.identifier} #{font.size} Tf - #{x} #{y} Td - } - + add_content "\nBT" + add_content "/#{font.identifier} #{font.size} Tf" + if options[:rotate] + rad = options[:rotate].to_i * Math::PI / 180 + arr = [ Math.cos(rad), Math.sin(rad), -Math.sin(rad), Math.cos(rad), x, y ] + add_content "%.3f %.3f %.3f %.3f %.3f %.3f Tm" % arr + else + add_content "#{x} #{y} Td" + end + rad = 1.570796 add_content Prawn::PdfObject(text, true) << - " #{options[:kerning] ? 'TJ' : 'Tj'}\n" - - add_content %Q{ - ET - } - end + " #{options[:kerning] ? 'TJ' : 'Tj'}" + add_content "ET\n" + end end end end