Permalink
Browse files

Merge branch 'master' of git://github.com/alexdowad/prawn

  • Loading branch information...
bradediger committed Aug 17, 2012
2 parents f30d859 + 4113335 commit 56c39962a2add184642f3b69cef09bd6d1d2b8bf
Showing with 192 additions and 39 deletions.
  1. +9 −6 bench/table_bench.rb
  2. +2 −2 lib/prawn/core/text.rb
  3. +142 −17 lib/prawn/graphics.rb
  4. +33 −11 lib/prawn/table/cell/text.rb
  5. +5 −2 lib/prawn/text/formatted/parser.rb
  6. +1 −1 prawn.gemspec
View
@@ -24,22 +24,25 @@ def data_for_table(columns,rows,string_size)
rows.times.collect { columns.times.collect { String.random(string_size) }}
end
-def benchmark_table_generation(columns,rows,string_size)
+def benchmark_table_generation(columns,rows,string_size,options={})
data = data_for_table(columns,rows,string_size)
Benchmark.bm do |x|
- x.report("#{columns}x#{rows} table (#{columns*rows} cells, with #{string_size} char string contents)") do
- Prawn::Document.new { table(data) }.render
+ x.report("#{columns}x#{rows} table (#{columns*rows} cells, with #{string_size} char string contents#{", options = #{options.inspect}" unless options.empty?})") do
+ Prawn::Document.new { table(data,options) }.render
end
end
end
+# Try building and rendering tables of different sizes
benchmark_table_generation(10,450,5)
benchmark_table_generation(10,300,5)
benchmark_table_generation(10,200,5)
-benchmark_table_generation(10,150,5)
benchmark_table_generation(10,100,5)
-benchmark_table_generation(10,50,5)
-benchmark_table_generation(10,25,5)
+# Try different optional arguments to Prawn::Document#table
+benchmark_table_generation(10,450,5, :cell_style => {:inline_format=>true})
+benchmark_table_generation(10,450,5, :row_colors => ['FFFFFF','F0F0FF'], :header => true, :cell_style => {:inline_format=>true})
+
+# Try different "aspect ratios", with same total number of cells
benchmark_table_generation(20,100,5)
benchmark_table_generation(25,80,5)
View
@@ -186,10 +186,10 @@ def fallback_fonts(fallback_fonts=nil)
#
def text_rendering_mode(mode=nil)
return @text_rendering_mode || :fill if mode.nil?
- unless MODES.keys.include?(mode)
+ unless MODES.key?(mode)
raise ArgumentError, "mode must be between one of #{MODES.keys.join(', ')} (#{mode})"
end
- original_mode = text_rendering_mode
+ original_mode = @text_rendering_mode || :fill
if original_mode == mode
yield
else
View
@@ -337,23 +337,148 @@ def close_path
add_content "h"
end
- # Provides the following shortcuts:
- #
- # stroke_some_method(*args) #=> some_method(*args); stroke
- # fill_some_method(*args) #=> some_method(*args); fill
- # fill_and_stroke_some_method(*args) #=> some_method(*args); fill_and_stroke
- #
- def method_missing(id,*args,&block)
- case(id.to_s)
- when /^fill_and_stroke_(.*)/
- send($1,*args,&block); fill_and_stroke
- when /^stroke_(.*)/
- send($1,*args,&block); stroke
- when /^fill_(.*)/
- send($1,*args,&block); fill
- else
- super
- end
+ ##
+ # :method: stroke_rectangle
+ # Draws and strokes a rectangle given +point+, +width+ and +height+. The rectangle is bounded by its upper-left corner.
+ # :call-seq:
+ # stroke_rectangle(point,width,height)
+
+ ##
+ # :method: fill_rectangle
+ # Draws and fills ills a rectangle given +point+, +width+ and +height+. The rectangle is bounded by its upper-left corner.
+ # :call-seq:
+ # fill_rectangle(point,width,height)
+
+ ##
+ # :method: fill_and_stroke_rectangle
+ # Draws, fills, and strokes a rectangle given +point+, +width+ and +height+. The rectangle is bounded by its upper-left corner.
+ # :call-seq:
+ # fill_and_stroke_rectangle(point,width,height)
+
+ ##
+ # :method: stroke_rounded_rectangle
+ # Draws and strokes a rounded rectangle given +point+, +width+ and +height+ and +radius+ for the rounded corner. The rectangle is bounded by its upper-left corner.
+ # :call-seq:
+ # stroke_rounded_rectangle(point,width,height,radius)
+
+ ##
+ # :method: fill_rounded_rectangle
+ # Draws and fills a rounded rectangle given +point+, +width+ and +height+ and +radius+ for the rounded corner. The rectangle is bounded by its upper-left corner.
+ # :call-seq:
+ # fill_rounded_rectangle(point,width,height,radius)
+
+ ##
+ # :method: stroke_and_fill_rounded_rectangle
+ # Draws, fills, and strokes a rounded rectangle given +point+, +width+ and +height+ and +radius+ for the rounded corner. The rectangle is bounded by its upper-left corner.
+ # :call-seq:
+ # stroke_and_fill_rounded_rectangle(point,width,height,radius)
+
+ ##
+ # :method: stroke_line
+ # Strokes a line from one point to another. Points may be specified as tuples or flattened argument list.
+ # :call-seq:
+ # stroke_line(*points)
+
+ ##
+ # :method: stroke_horizontal_line
+ # Strokes a horizontal line from +x1+ to +x2+ at the current y position, or the position specified by the :at option.
+ # :call-seq:
+ # stroke_horizontal_line(x1,x2,options={})
+
+ ##
+ # :method: stroke_horizontal_rule
+ # Strokes a horizontal line from the left border to the right border of the bounding box at the current y position.
+
+ ##
+ # :method: stroke_vertical_line
+ # Strokes a vertical line at the x coordinate given by :at from y1 to y2.
+ # :call-seq:
+ # stroke_vertical_line(y1,y2,params)
+
+ ##
+ # :method: stroke_curve
+ # Strokes a Bezier curve between two points, bounded by two additional points.
+ # :call-seq:
+ # stroke_curve(origin,dest,options={})
+
+ ##
+ # :method: stroke_circle
+ # Draws and strokes a circle of radius +radius+ with the centre-point at +point+.
+ # :call-seq:
+ # stroke_circle(center,radius)
+
+ ##
+ # :method: fill_circle
+ # Draws and fills a circle of radius +radius+ with the centre-point at +point+.
+ # :call-seq:
+ # fill_circle(center,radius)
+
+ ##
+ # :method: fill_and_stroke_circle
+ # Draws, strokes, and fills a circle of radius +radius+ with the centre-point at +point+.
+ # :call-seq:
+ # fill_and_stroke_circle(center,radius)
+
+ ##
+ # :method: stroke_ellipse
+ # Draws and strokes an ellipse of x radius +r1+ and y radius +r2+ with the centre-point at +point+.
+ # :call-seq:
+ # stroke_ellipse(point, r1, r2 = r1)
+
+ ##
+ # :method: fill_ellipse
+ # Draws and fills an ellipse of x radius +r1+ and y radius +r2+ with the centre-point at +point+.
+ # :call-seq:
+ # fill_ellipse(point, r1, r2 = r1)
+
+ ##
+ # :method: fill_and_stroke_ellipse
+ # Draws, strokes, and fills an ellipse of x radius +r1+ and y radius +r2+ with the centre-point at +point+.
+ # :call-seq:
+ # fill_and_stroke_ellipse(point, r1, r2 = r1)
+
+ ##
+ # :method: stroke_polygon
+ # Draws and strokes a polygon from the specified points.
+ # :call-seq:
+ # stroke_polygon(*points)
+
+ ##
+ # :method: fill_polygon
+ # Draws and fills a polygon from the specified points.
+ # :call-seq:
+ # fill_polygon(*points)
+
+ ##
+ # :method: fill_and_stroke_polygon
+ # Draws, strokes, and fills a polygon from the specified points.
+ # :call-seq:
+ # fill_and_stroke_polygon(*points)
+
+ ##
+ # :method: stroke_rounded_polygon
+ # Draws and strokes a rounded polygon from specified points, using +radius+ to define Bezier curves.
+ # :call-seq:
+ # stroke_rounded_polygon(radius, *points)
+
+ ##
+ # :method: fill_rounded_polygon
+ # Draws and fills a rounded polygon from specified points, using +radius+ to define Bezier curves.
+ # :call-seq:
+ # fill_rounded_polygon(radius, *points)
+
+ ##
+ # :method: fill_and_stroke_rounded_polygon
+ # Draws, strokes, and fills a rounded polygon from specified points, using +radius+ to define Bezier curves.
+ # :call-seq:
+ # fill_and_stroke_rounded_polygon(radius, *points)
+
+ ops = %w{fill stroke fill_and_stroke}
+ shapes = %w{line_to curve_to rectangle rounded_rectangle line horizontal_line horizontal_rule vertical_line
+ curve circle_at circle ellipse_at ellipse polygon rounded_polygon rounded_vertex}
+
+ ops.product(shapes).each do |operation,shape|
+ class_eval "def #{operation}_#{shape}(*args); #{shape}(*args); #{operation}; end"
end
private
@@ -47,7 +47,7 @@ def font_style=(style)
# from the final width if the text is long.
#
def natural_content_width
- [styled_width_of(@content), @pdf.bounds.width].min
+ @natural_content_width ||= [styled_width_of(@content), @pdf.bounds.width].min
end
# Returns the natural height of this block of text, wrapped to the
@@ -78,9 +78,11 @@ def set_width_constraints
# Sets a reasonable minimum width. If the cell has any content, make
# sure we have enough width to be at least one character wide. This is
# a bit of a hack, but it should work well enough.
- min_content_width = [natural_content_width, styled_width_of("M")].min
- @min_width ||= padding_left + padding_right + min_content_width
- super
+ unless @min_width
+ min_content_width = [natural_content_width, styled_width_of_single_character].min
+ @min_width = padding_left + padding_right + min_content_width
+ super
+ end
end
protected
@@ -97,21 +99,28 @@ def with_font
end
def with_text_color
- old_color = @pdf.fill_color || '000000'
- @pdf.fill_color(@text_color) if @text_color
- yield
- ensure
- @pdf.fill_color(old_color)
+ if @text_color
+ begin
+ old_color = @pdf.fill_color || '000000'
+ @pdf.fill_color(@text_color)
+ yield
+ ensure
+ @pdf.fill_color(old_color)
+ end
+ else
+ yield
+ end
end
def text_box(extra_options={})
if @text_options[:inline_format]
options = @text_options.dup
options.delete(:inline_format)
+ options.merge!(extra_options)
+ options[:document] = @pdf
array = ::Prawn::Text::Formatted::Parser.to_array(@content)
- ::Prawn::Text::Formatted::Box.new(array,
- options.merge(extra_options).merge(:document => @pdf))
+ ::Prawn::Text::Formatted::Box.new(array, options)
else
::Prawn::Text::Box.new(@content, @text_options.merge(extra_options).
merge(:document => @pdf))
@@ -124,6 +133,19 @@ def styled_width_of(text)
@pdf.width_of(text, @text_options)
end
+ private
+
+ # Returns the greatest possible width of any single character
+ # under the given text options.
+ # (We use this to determine the minimum width of a table cell)
+ # (Although we currently determine this by measuring "M", it should really
+ # use whichever character is widest under the current font)
+ #
+ def styled_width_of_single_character
+ key = (@text_options[:style] == :bold) ? :bold_char_width : :plain_char_width
+ cache = Thread.current[key] ||= {}
+ cache[@pdf.font] ||= styled_width_of("M")
+ end
end
end
end
@@ -14,7 +14,7 @@ module Formatted
class Parser
- def self.to_array(string)
+ PARSER_REGEX = begin
regex_string = "\n|" +
"<b>|</b>|" +
"<i>|</i>|" +
@@ -30,7 +30,10 @@ def self.to_array(string)
"<a[^>]*>|</a>|" +
"[^<\n]+"
regex = Regexp.new(regex_string, Regexp::MULTILINE)
- tokens = string.gsub(/<br\s*\/?>/, "\n").scan(regex)
+ end
+
+ def self.to_array(string)
+ tokens = string.gsub(/<br\s*\/?>/, "\n").scan(PARSER_REGEX)
self.array_from_tokens(tokens)
end
View
@@ -34,7 +34,7 @@ END_DESC
Please read the changelog for details:
- https://github.com/sandal/prawn/wiki/CHANGELOG
+ https://github.com/prawnpdf/prawn/wiki/CHANGELOG
********************************************

0 comments on commit 56c3996

Please sign in to comment.