prawn 1.0.0.rc1 → 1.0.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +18 -0
- data/README.md +5 -3
- data/Rakefile +8 -14
- data/data/pdfs/nested_pages.pdf +13 -13
- data/lib/prawn.rb +3 -1
- data/lib/prawn/compatibility.rb +46 -10
- data/lib/prawn/core.rb +3 -1
- data/lib/prawn/core/document_state.rb +2 -1
- data/lib/prawn/core/object_store.rb +61 -5
- data/lib/prawn/core/page.rb +3 -6
- data/lib/prawn/core/pdf_object.rb +21 -4
- data/lib/prawn/core/reference.rb +6 -2
- data/lib/prawn/core/text.rb +4 -4
- data/lib/prawn/core/text/formatted/line_wrap.rb +23 -8
- data/lib/prawn/document.rb +21 -15
- data/lib/prawn/document/bounding_box.rb +3 -3
- data/lib/prawn/document/column_box.rb +22 -4
- data/lib/prawn/document/snapshot.rb +1 -1
- data/lib/prawn/encoding.rb +1 -1
- data/lib/prawn/errors.rb +4 -0
- data/lib/prawn/font.rb +1 -1
- data/lib/prawn/font/afm.rb +30 -72
- data/lib/prawn/font/ttf.rb +6 -33
- data/lib/prawn/graphics.rb +148 -23
- data/lib/prawn/graphics/color.rb +8 -1
- data/lib/prawn/graphics/patterns.rb +137 -0
- data/lib/prawn/images.rb +25 -19
- data/lib/prawn/images/jpg.rb +4 -4
- data/lib/prawn/images/png.rb +18 -12
- data/lib/prawn/security.rb +6 -4
- data/lib/prawn/soft_mask.rb +94 -0
- data/lib/prawn/table.rb +136 -31
- data/lib/prawn/table/cell.rb +260 -29
- data/lib/prawn/table/cell/span_dummy.rb +88 -0
- data/lib/prawn/table/cell/text.rb +36 -14
- data/lib/prawn/table/cells.rb +91 -41
- data/lib/prawn/text.rb +3 -2
- data/lib/prawn/text/formatted/box.rb +14 -5
- data/lib/prawn/text/formatted/fragment.rb +33 -22
- data/lib/prawn/text/formatted/parser.rb +5 -2
- data/lib/prawn/utilities.rb +44 -0
- data/manual/basic_concepts/adding_pages.rb +27 -0
- data/manual/basic_concepts/basic_concepts.rb +34 -0
- data/manual/basic_concepts/creation.rb +39 -0
- data/manual/basic_concepts/cursor.rb +33 -0
- data/manual/basic_concepts/measurement.rb +25 -0
- data/manual/basic_concepts/origin.rb +38 -0
- data/manual/basic_concepts/other_cursor_helpers.rb +40 -0
- data/manual/bounding_box/bounding_box.rb +39 -0
- data/manual/bounding_box/bounds.rb +49 -0
- data/manual/bounding_box/canvas.rb +24 -0
- data/manual/bounding_box/creation.rb +23 -0
- data/manual/bounding_box/indentation.rb +46 -0
- data/manual/bounding_box/nesting.rb +45 -0
- data/manual/bounding_box/russian_boxes.rb +40 -0
- data/manual/bounding_box/stretchy.rb +31 -0
- data/manual/document_and_page_options/background.rb +27 -0
- data/manual/document_and_page_options/document_and_page_options.rb +31 -0
- data/manual/document_and_page_options/metadata.rb +23 -0
- data/manual/document_and_page_options/page_margins.rb +38 -0
- data/manual/document_and_page_options/page_size.rb +34 -0
- data/manual/example_file.rb +116 -0
- data/manual/example_helper.rb +430 -0
- data/manual/example_package.rb +53 -0
- data/manual/example_section.rb +46 -0
- data/manual/graphics/circle_and_ellipse.rb +22 -0
- data/manual/graphics/color.rb +24 -0
- data/manual/graphics/common_lines.rb +28 -0
- data/manual/graphics/fill_and_stroke.rb +42 -0
- data/manual/graphics/fill_rules.rb +37 -0
- data/manual/graphics/gradients.rb +37 -0
- data/manual/graphics/graphics.rb +58 -0
- data/manual/graphics/helper.rb +17 -0
- data/manual/graphics/line_width.rb +35 -0
- data/manual/graphics/lines_and_curves.rb +41 -0
- data/manual/graphics/polygon.rb +29 -0
- data/manual/graphics/rectangle.rb +21 -0
- data/manual/graphics/rotate.rb +28 -0
- data/manual/graphics/scale.rb +41 -0
- data/manual/graphics/soft_masks.rb +46 -0
- data/manual/graphics/stroke_cap.rb +31 -0
- data/manual/graphics/stroke_dash.rb +43 -0
- data/manual/graphics/stroke_join.rb +30 -0
- data/manual/graphics/translate.rb +29 -0
- data/manual/graphics/transparency.rb +35 -0
- data/manual/images/absolute_position.rb +23 -0
- data/manual/images/fit.rb +21 -0
- data/manual/images/horizontal.rb +25 -0
- data/manual/images/images.rb +40 -0
- data/manual/images/plain_image.rb +18 -0
- data/manual/images/scale.rb +22 -0
- data/manual/images/vertical.rb +28 -0
- data/manual/images/width_and_height.rb +25 -0
- data/manual/layout/boxes.rb +27 -0
- data/manual/layout/content.rb +25 -0
- data/manual/layout/layout.rb +28 -0
- data/manual/layout/simple_grid.rb +23 -0
- data/manual/manual/cover.rb +26 -0
- data/manual/manual/foreword.rb +13 -0
- data/manual/manual/how_to_read_this_manual.rb +41 -0
- data/manual/manual/manual.rb +36 -0
- data/manual/outline/add_subsection_to.rb +61 -0
- data/manual/outline/insert_section_after.rb +47 -0
- data/manual/outline/outline.rb +32 -0
- data/manual/outline/sections_and_pages.rb +67 -0
- data/manual/repeatable_content/page_numbering.rb +54 -0
- data/manual/repeatable_content/repeatable_content.rb +31 -0
- data/manual/repeatable_content/repeater.rb +55 -0
- data/manual/repeatable_content/stamp.rb +41 -0
- data/manual/security/encryption.rb +31 -0
- data/manual/security/permissions.rb +38 -0
- data/manual/security/security.rb +28 -0
- data/manual/syntax_highlight.rb +52 -0
- data/manual/table/basic_block.rb +53 -0
- data/manual/table/before_rendering_page.rb +26 -0
- data/manual/table/cell_border_lines.rb +24 -0
- data/manual/table/cell_borders_and_bg.rb +31 -0
- data/manual/table/cell_dimensions.rb +30 -0
- data/manual/table/cell_text.rb +38 -0
- data/manual/table/column_widths.rb +30 -0
- data/manual/table/content_and_subtables.rb +39 -0
- data/manual/table/creation.rb +27 -0
- data/manual/table/filtering.rb +36 -0
- data/manual/table/flow_and_header.rb +17 -0
- data/manual/table/image_cells.rb +33 -0
- data/manual/table/position.rb +29 -0
- data/manual/table/row_colors.rb +20 -0
- data/manual/table/span.rb +30 -0
- data/manual/table/style.rb +22 -0
- data/manual/table/table.rb +52 -0
- data/manual/table/width.rb +27 -0
- data/manual/templates/full_template.rb +23 -0
- data/manual/templates/page_template.rb +47 -0
- data/manual/templates/templates.rb +26 -0
- data/manual/text/alignment.rb +44 -0
- data/manual/text/color.rb +24 -0
- data/manual/text/column_box.rb +32 -0
- data/manual/text/fallback_fonts.rb +37 -0
- data/manual/text/font.rb +41 -0
- data/manual/text/font_size.rb +45 -0
- data/manual/text/font_style.rb +23 -0
- data/manual/text/formatted_callbacks.rb +60 -0
- data/manual/text/formatted_text.rb +50 -0
- data/manual/text/free_flowing_text.rb +51 -0
- data/manual/text/group.rb +29 -0
- data/manual/text/inline.rb +43 -0
- data/manual/text/kerning_and_character_spacing.rb +39 -0
- data/manual/text/leading.rb +25 -0
- data/manual/text/line_wrapping.rb +41 -0
- data/manual/text/paragraph_indentation.rb +26 -0
- data/manual/text/positioned_text.rb +38 -0
- data/manual/text/registering_families.rb +48 -0
- data/manual/text/rendering_and_color.rb +37 -0
- data/manual/text/right_to_left_text.rb +43 -0
- data/manual/text/rotation.rb +43 -0
- data/manual/text/single_usage.rb +37 -0
- data/manual/text/text.rb +75 -0
- data/manual/text/text_box_excess.rb +32 -0
- data/manual/text/text_box_extensions.rb +45 -0
- data/manual/text/text_box_overflow.rb +44 -0
- data/manual/text/utf8.rb +28 -0
- data/manual/text/win_ansi_charset.rb +59 -0
- data/prawn.gemspec +10 -7
- data/spec/bounding_box_spec.rb +107 -17
- data/spec/cell_spec.rb +66 -40
- data/spec/column_box_spec.rb +33 -0
- data/spec/document_spec.rb +45 -24
- data/spec/extensions/encoding_helpers.rb +6 -0
- data/spec/extensions/mocha.rb +1 -0
- data/spec/font_spec.rb +71 -53
- data/spec/formatted_text_arranger_spec.rb +19 -19
- data/spec/formatted_text_box_spec.rb +16 -16
- data/spec/formatted_text_fragment_spec.rb +6 -6
- data/spec/graphics_spec.rb +96 -31
- data/spec/grid_spec.rb +2 -2
- data/spec/images_spec.rb +18 -10
- data/spec/jpg_spec.rb +1 -1
- data/spec/line_wrap_spec.rb +14 -14
- data/spec/measurement_units_spec.rb +2 -2
- data/spec/name_tree_spec.rb +6 -6
- data/spec/object_store_spec.rb +17 -17
- data/spec/outline_spec.rb +35 -17
- data/spec/pdf_object_spec.rb +3 -1
- data/spec/png_spec.rb +22 -19
- data/spec/reference_spec.rb +24 -1
- data/spec/repeater_spec.rb +9 -9
- data/spec/security_spec.rb +3 -3
- data/spec/snapshot_spec.rb +3 -3
- data/spec/soft_mask_spec.rb +117 -0
- data/spec/span_spec.rb +4 -4
- data/spec/spec_helper.rb +12 -6
- data/spec/stamp_spec.rb +12 -12
- data/spec/stroke_styles_spec.rb +5 -5
- data/spec/table_spec.rb +458 -88
- data/spec/template_spec.rb +108 -54
- data/spec/text_at_spec.rb +17 -17
- data/spec/text_box_spec.rb +76 -45
- data/spec/text_rendering_mode_spec.rb +5 -5
- data/spec/text_spacing_spec.rb +4 -4
- data/spec/text_spec.rb +44 -40
- metadata +419 -250
- data/lib/prawn/graphics/gradient.rb +0 -84
- data/lib/prawn/security/arcfour.rb +0 -51
@@ -0,0 +1,88 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# span_dummy.rb: Placeholder for non-master spanned cells.
|
4
|
+
#
|
5
|
+
# Copyright December 2011, Brad Ediger. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
module Prawn
|
9
|
+
class Table
|
10
|
+
class Cell
|
11
|
+
|
12
|
+
# A Cell object used to represent all but the topmost cell in a span
|
13
|
+
# group.
|
14
|
+
#
|
15
|
+
class SpanDummy < Cell
|
16
|
+
def initialize(pdf, master_cell)
|
17
|
+
super(pdf, [0, pdf.cursor])
|
18
|
+
@master_cell = master_cell
|
19
|
+
@padding = [0, 0, 0, 0]
|
20
|
+
end
|
21
|
+
|
22
|
+
# By default, a span dummy will never increase the height demand.
|
23
|
+
#
|
24
|
+
def natural_content_height
|
25
|
+
0
|
26
|
+
end
|
27
|
+
|
28
|
+
# By default, a span dummy will never increase the width demand.
|
29
|
+
#
|
30
|
+
def natural_content_width
|
31
|
+
0
|
32
|
+
end
|
33
|
+
|
34
|
+
def avg_spanned_min_width
|
35
|
+
@master_cell.avg_spanned_min_width
|
36
|
+
end
|
37
|
+
|
38
|
+
# Dummy cells have nothing to draw.
|
39
|
+
#
|
40
|
+
def draw_borders(pt)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Dummy cells have nothing to draw.
|
44
|
+
#
|
45
|
+
def draw_bounded_content(pt)
|
46
|
+
end
|
47
|
+
|
48
|
+
def padding_right=(val)
|
49
|
+
@master_cell.padding_right = val if rightmost?
|
50
|
+
end
|
51
|
+
|
52
|
+
def padding_bottom=(val)
|
53
|
+
@master_cell.padding_bottom = val if bottommost?
|
54
|
+
end
|
55
|
+
|
56
|
+
def border_right_color=(val)
|
57
|
+
@master_cell.border_right_color = val if rightmost?
|
58
|
+
end
|
59
|
+
|
60
|
+
def border_bottom_color=(val)
|
61
|
+
@master_cell.border_bottom_color = val if bottommost?
|
62
|
+
end
|
63
|
+
|
64
|
+
def border_right_width=(val)
|
65
|
+
@master_cell.border_right_width = val if rightmost?
|
66
|
+
end
|
67
|
+
|
68
|
+
def border_bottom_width=(val)
|
69
|
+
@master_cell.border_bottom_width = val if bottommost?
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
# Are we on the right border of the span?
|
75
|
+
#
|
76
|
+
def rightmost?
|
77
|
+
@column == @master_cell.column + @master_cell.colspan - 1
|
78
|
+
end
|
79
|
+
|
80
|
+
# Are we on the bottom border of the span?
|
81
|
+
#
|
82
|
+
def bottommost?
|
83
|
+
@row == @master_cell.row + @master_cell.rowspan - 1
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -47,7 +47,7 @@ module Prawn
|
|
47
47
|
# from the final width if the text is long.
|
48
48
|
#
|
49
49
|
def natural_content_width
|
50
|
-
[styled_width_of(@content), @pdf.bounds.width].min
|
50
|
+
@natural_content_width ||= [styled_width_of(@content), @pdf.bounds.width].min
|
51
51
|
end
|
52
52
|
|
53
53
|
# Returns the natural height of this block of text, wrapped to the
|
@@ -55,7 +55,7 @@ module Prawn
|
|
55
55
|
#
|
56
56
|
def natural_content_height
|
57
57
|
with_font do
|
58
|
-
b = text_box(:width =>
|
58
|
+
b = text_box(:width => spanned_content_width + FPTolerance)
|
59
59
|
b.render(:dry_run => true)
|
60
60
|
b.height + b.line_gap
|
61
61
|
end
|
@@ -67,8 +67,8 @@ module Prawn
|
|
67
67
|
with_font do
|
68
68
|
@pdf.move_down((@pdf.font.line_gap + @pdf.font.descender)/2)
|
69
69
|
with_text_color do
|
70
|
-
text_box(:width =>
|
71
|
-
:height =>
|
70
|
+
text_box(:width => spanned_content_width + FPTolerance,
|
71
|
+
:height => spanned_content_height + FPTolerance,
|
72
72
|
:at => [0, @pdf.cursor]).render
|
73
73
|
end
|
74
74
|
end
|
@@ -78,9 +78,11 @@ module Prawn
|
|
78
78
|
# Sets a reasonable minimum width. If the cell has any content, make
|
79
79
|
# sure we have enough width to be at least one character wide. This is
|
80
80
|
# a bit of a hack, but it should work well enough.
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
unless @min_width
|
82
|
+
min_content_width = [natural_content_width, styled_width_of_single_character].min
|
83
|
+
@min_width = padding_left + padding_right + min_content_width
|
84
|
+
super
|
85
|
+
end
|
84
86
|
end
|
85
87
|
|
86
88
|
protected
|
@@ -97,21 +99,28 @@ module Prawn
|
|
97
99
|
end
|
98
100
|
|
99
101
|
def with_text_color
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
102
|
+
if @text_color
|
103
|
+
begin
|
104
|
+
old_color = @pdf.fill_color || '000000'
|
105
|
+
@pdf.fill_color(@text_color)
|
106
|
+
yield
|
107
|
+
ensure
|
108
|
+
@pdf.fill_color(old_color)
|
109
|
+
end
|
110
|
+
else
|
111
|
+
yield
|
112
|
+
end
|
105
113
|
end
|
106
114
|
|
107
115
|
def text_box(extra_options={})
|
108
116
|
if @text_options[:inline_format]
|
109
117
|
options = @text_options.dup
|
110
118
|
options.delete(:inline_format)
|
119
|
+
options.merge!(extra_options)
|
120
|
+
options[:document] = @pdf
|
111
121
|
|
112
122
|
array = ::Prawn::Text::Formatted::Parser.to_array(@content)
|
113
|
-
::Prawn::Text::Formatted::Box.new(array,
|
114
|
-
options.merge(extra_options).merge(:document => @pdf))
|
123
|
+
::Prawn::Text::Formatted::Box.new(array, options)
|
115
124
|
else
|
116
125
|
::Prawn::Text::Box.new(@content, @text_options.merge(extra_options).
|
117
126
|
merge(:document => @pdf))
|
@@ -124,6 +133,19 @@ module Prawn
|
|
124
133
|
@pdf.width_of(text, @text_options)
|
125
134
|
end
|
126
135
|
|
136
|
+
private
|
137
|
+
|
138
|
+
# Returns the greatest possible width of any single character
|
139
|
+
# under the given text options.
|
140
|
+
# (We use this to determine the minimum width of a table cell)
|
141
|
+
# (Although we currently determine this by measuring "M", it should really
|
142
|
+
# use whichever character is widest under the current font)
|
143
|
+
#
|
144
|
+
def styled_width_of_single_character
|
145
|
+
key = (@text_options[:style] == :bold) ? :bold_char_width : :plain_char_width
|
146
|
+
cache = Thread.current[key] ||= {}
|
147
|
+
cache[@pdf.font] ||= styled_width_of("M")
|
148
|
+
end
|
127
149
|
end
|
128
150
|
end
|
129
151
|
end
|
data/lib/prawn/table/cells.rb
CHANGED
@@ -9,13 +9,6 @@
|
|
9
9
|
module Prawn
|
10
10
|
class Table
|
11
11
|
|
12
|
-
# Returns a Cells object that can be used to select and style cells. See
|
13
|
-
# the Cells documentation for things you can do with cells.
|
14
|
-
#
|
15
|
-
def cells
|
16
|
-
@cell_proxy ||= Cells.new(@cells)
|
17
|
-
end
|
18
|
-
|
19
12
|
# Selects the given rows (0-based) for styling. Returns a Cells object --
|
20
13
|
# see the documentation on Cells for things you can do with cells.
|
21
14
|
#
|
@@ -54,13 +47,20 @@ module Prawn
|
|
54
47
|
#
|
55
48
|
def rows(row_spec)
|
56
49
|
index_cells unless @indexed
|
57
|
-
row_spec = transform_spec(row_spec, @row_count)
|
50
|
+
row_spec = transform_spec(row_spec, @first_row, @row_count)
|
58
51
|
Cells.new(@rows[row_spec] ||= select { |c|
|
59
52
|
row_spec.respond_to?(:include?) ?
|
60
53
|
row_spec.include?(c.row) : row_spec === c.row })
|
61
54
|
end
|
62
55
|
alias_method :row, :rows
|
63
|
-
|
56
|
+
|
57
|
+
# Returns the number of rows in the list.
|
58
|
+
#
|
59
|
+
def row_count
|
60
|
+
index_cells unless @indexed
|
61
|
+
@row_count
|
62
|
+
end
|
63
|
+
|
64
64
|
# Limits selection to the given column or columns. +col_spec+ can be
|
65
65
|
# anything that responds to the === operator selecting a set of 0-based
|
66
66
|
# column numbers; most commonly a number or a range.
|
@@ -70,13 +70,20 @@ module Prawn
|
|
70
70
|
#
|
71
71
|
def columns(col_spec)
|
72
72
|
index_cells unless @indexed
|
73
|
-
col_spec = transform_spec(col_spec, @column_count)
|
73
|
+
col_spec = transform_spec(col_spec, @first_column, @column_count)
|
74
74
|
Cells.new(@columns[col_spec] ||= select { |c|
|
75
75
|
col_spec.respond_to?(:include?) ?
|
76
76
|
col_spec.include?(c.column) : col_spec === c.column })
|
77
77
|
end
|
78
78
|
alias_method :column, :columns
|
79
79
|
|
80
|
+
# Returns the number of columns in the list.
|
81
|
+
#
|
82
|
+
def column_count
|
83
|
+
index_cells unless @indexed
|
84
|
+
@column_count
|
85
|
+
end
|
86
|
+
|
80
87
|
# Allows you to filter the given cells by arbitrary properties.
|
81
88
|
#
|
82
89
|
# table.column(4).filter { |cell| cell.content =~ /Yes/ }.
|
@@ -92,7 +99,33 @@ module Prawn
|
|
92
99
|
# table.cells[0, 0].content # => "First cell content"
|
93
100
|
#
|
94
101
|
def [](row, col)
|
95
|
-
|
102
|
+
return nil if empty?
|
103
|
+
index_cells unless @indexed
|
104
|
+
row_array, col_array = @rows[@first_row + row] || [], @columns[@first_column + col] || []
|
105
|
+
if row_array.length < col_array.length
|
106
|
+
row_array.find { |c| c.column == @first_column + col }
|
107
|
+
else
|
108
|
+
col_array.find { |c| c.row == @first_row + row }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Puts a cell in the collection at the given position. Internal use only.
|
113
|
+
#
|
114
|
+
def []=(row, col, cell) # :nodoc:
|
115
|
+
cell.extend(Cell::InTable)
|
116
|
+
cell.row = row
|
117
|
+
cell.column = col
|
118
|
+
|
119
|
+
if @indexed
|
120
|
+
(@rows[row] ||= []) << cell
|
121
|
+
(@columns[col] ||= []) << cell
|
122
|
+
@first_row = row if !@first_row || row < @first_row
|
123
|
+
@first_column = col if !@first_column || col < @first_column
|
124
|
+
@row_count = @rows.size
|
125
|
+
@column_count = @columns.size
|
126
|
+
end
|
127
|
+
|
128
|
+
self << cell
|
96
129
|
end
|
97
130
|
|
98
131
|
# Supports setting multiple properties at once.
|
@@ -110,51 +143,43 @@ module Prawn
|
|
110
143
|
# table.cells.style { |cell| cell.border_width += 12 }
|
111
144
|
#
|
112
145
|
def style(options={}, &block)
|
113
|
-
each
|
146
|
+
each do |cell|
|
147
|
+
next if cell.is_a?(Cell::SpanDummy)
|
148
|
+
cell.style(options, &block)
|
149
|
+
end
|
114
150
|
end
|
115
151
|
|
116
152
|
# Returns the total width of all columns in the selected set.
|
117
153
|
#
|
118
154
|
def width
|
119
|
-
|
120
|
-
each do |cell|
|
121
|
-
|
122
|
-
|
155
|
+
widths = {}
|
156
|
+
each do |cell|
|
157
|
+
index = cell.column
|
158
|
+
per_cell_width = cell.width_ignoring_span.to_f / cell.colspan
|
159
|
+
cell.colspan.times do |n|
|
160
|
+
widths[cell.column+n] = [widths[cell.column+n], per_cell_width].
|
161
|
+
compact.max
|
162
|
+
end
|
123
163
|
end
|
124
|
-
|
164
|
+
widths.values.inject(0, &:+)
|
125
165
|
end
|
126
166
|
|
127
167
|
# Returns minimum width required to contain cells in the set.
|
128
168
|
#
|
129
169
|
def min_width
|
130
|
-
|
131
|
-
each do |cell|
|
132
|
-
column_min_widths[cell.column] =
|
133
|
-
[column_min_widths[cell.column], cell.min_width].compact.max
|
134
|
-
end
|
135
|
-
column_min_widths.values.inject(0) { |sum, width| sum + width }
|
170
|
+
aggregate_cell_values(:column, :avg_spanned_min_width, :max)
|
136
171
|
end
|
137
172
|
|
138
173
|
# Returns maximum width that can contain cells in the set.
|
139
174
|
#
|
140
175
|
def max_width
|
141
|
-
|
142
|
-
each do |cell|
|
143
|
-
column_max_widths[cell.column] =
|
144
|
-
[column_max_widths[cell.column], cell.max_width].compact.min
|
145
|
-
end
|
146
|
-
column_max_widths.values.inject(0) { |sum, width| sum + width }
|
176
|
+
aggregate_cell_values(:column, :max_width_ignoring_span, :min)
|
147
177
|
end
|
148
178
|
|
149
179
|
# Returns the total height of all rows in the selected set.
|
150
180
|
#
|
151
181
|
def height
|
152
|
-
|
153
|
-
each do |cell|
|
154
|
-
row_heights[cell.row] =
|
155
|
-
[row_heights[cell.row], cell.height].compact.max
|
156
|
-
end
|
157
|
-
row_heights.values.inject(0) { |sum, width| sum + width }
|
182
|
+
aggregate_cell_values(:row, :height_ignoring_span, :max)
|
158
183
|
end
|
159
184
|
|
160
185
|
# Supports setting arbitrary properties on a group of cells.
|
@@ -162,7 +187,11 @@ module Prawn
|
|
162
187
|
# table.cells.row(3..6).background_color = 'cc0000'
|
163
188
|
#
|
164
189
|
def method_missing(id, *args, &block)
|
165
|
-
|
190
|
+
if id.to_s =~ /=\z/
|
191
|
+
each { |c| c.send(id, *args, &block) if c.respond_to?(id) }
|
192
|
+
else
|
193
|
+
super
|
194
|
+
end
|
166
195
|
end
|
167
196
|
|
168
197
|
protected
|
@@ -185,24 +214,45 @@ module Prawn
|
|
185
214
|
@columns[cell.column] << cell
|
186
215
|
end
|
187
216
|
|
217
|
+
@first_row = @rows.keys.min
|
218
|
+
@first_column = @columns.keys.min
|
219
|
+
|
188
220
|
@row_count = @rows.size
|
189
221
|
@column_count = @columns.size
|
190
222
|
|
191
223
|
@indexed = true
|
192
224
|
end
|
193
225
|
|
226
|
+
# Sum up a min/max value over rows or columns in the cells selected.
|
227
|
+
# Takes the min/max (per +aggregate+) of the result of sending +meth+ to
|
228
|
+
# each cell, grouped by +row_or_column+.
|
229
|
+
#
|
230
|
+
def aggregate_cell_values(row_or_column, meth, aggregate)
|
231
|
+
values = {}
|
232
|
+
each do |cell|
|
233
|
+
index = cell.send(row_or_column)
|
234
|
+
values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
|
235
|
+
end
|
236
|
+
values.values.inject(0, &:+)
|
237
|
+
end
|
238
|
+
|
194
239
|
# Transforms +spec+, a column / row specification, into an object that
|
195
240
|
# can be compared against a row or column number using ===. Normalizes
|
196
|
-
# negative indices to be positive, given a total size of +total+.
|
241
|
+
# negative indices to be positive, given a total size of +total+. The
|
242
|
+
# first row/column is indicated by +first+; this value is considered row
|
243
|
+
# or column 0.
|
197
244
|
#
|
198
|
-
def transform_spec(spec, total)
|
245
|
+
def transform_spec(spec, first, total)
|
199
246
|
case spec
|
200
247
|
when Range
|
201
|
-
transform_spec(spec.begin,
|
248
|
+
transform_spec(spec.begin, first, total) ..
|
249
|
+
transform_spec(spec.end, first, total)
|
202
250
|
when Integer
|
203
|
-
spec < 0 ? (total + spec) : spec
|
251
|
+
spec < 0 ? (first + total + spec) : first + spec
|
252
|
+
when Enumerable
|
253
|
+
spec.map { |x| first + x }
|
204
254
|
else # pass through
|
205
|
-
spec
|
255
|
+
raise "Don't understand spec #{spec.inspect}"
|
206
256
|
end
|
207
257
|
end
|
208
258
|
end
|
data/lib/prawn/text.rb
CHANGED
@@ -152,6 +152,7 @@ module Prawn
|
|
152
152
|
# any text
|
153
153
|
#
|
154
154
|
def text(string, options={})
|
155
|
+
return false if string.nil?
|
155
156
|
# we modify the options. don't change the user's hash
|
156
157
|
options = options.dup
|
157
158
|
|
@@ -176,7 +177,7 @@ module Prawn
|
|
176
177
|
# text([{ :text => "hello" },
|
177
178
|
# { :text => "world",
|
178
179
|
# :size => 24,
|
179
|
-
# :
|
180
|
+
# :styles => [:bold, :italic] }])
|
180
181
|
#
|
181
182
|
# == Options
|
182
183
|
#
|
@@ -314,7 +315,7 @@ module Prawn
|
|
314
315
|
# height_of_formatted([{ :text => "hello" },
|
315
316
|
# { :text => "world",
|
316
317
|
# :size => 24,
|
317
|
-
# :
|
318
|
+
# :styles => [:bold, :italic] }])
|
318
319
|
#
|
319
320
|
def height_of_formatted(array, options={})
|
320
321
|
if options[:indent_paragraphs]
|
@@ -49,6 +49,9 @@ module Prawn
|
|
49
49
|
# created to that destination. Note that you must explicitly underline
|
50
50
|
# and color using the appropriate tags if you which to draw attention
|
51
51
|
# to the link
|
52
|
+
# <tt>:draw_text_callback</tt>:
|
53
|
+
# if provided, this Proc will be called instead of #draw_text! once
|
54
|
+
# per fragment for every low-level addition of text to the page.
|
52
55
|
# <tt>:callback</tt>::
|
53
56
|
# an object (or array of such objects) with two methods:
|
54
57
|
# #render_behind and #render_in_front, which are called immediately
|
@@ -101,7 +104,8 @@ module Prawn
|
|
101
104
|
:skip_encoding,
|
102
105
|
:document,
|
103
106
|
:direction,
|
104
|
-
:fallback_fonts
|
107
|
+
:fallback_fonts,
|
108
|
+
:draw_text_callback]
|
105
109
|
end
|
106
110
|
|
107
111
|
# The text that was successfully printed (or, if <tt>dry_run</tt> was
|
@@ -205,6 +209,7 @@ module Prawn
|
|
205
209
|
@rotate_around = options[:rotate_around] || :upper_left
|
206
210
|
@single_line = options[:single_line]
|
207
211
|
@skip_encoding = options[:skip_encoding] || @document.skip_encoding
|
212
|
+
@draw_text_callback = options[:draw_text_callback]
|
208
213
|
|
209
214
|
if @overflow == :expand
|
210
215
|
# if set to expand, then we simply set the bottom
|
@@ -310,8 +315,13 @@ module Prawn
|
|
310
315
|
draw_fragment_underlays(fragment)
|
311
316
|
|
312
317
|
@document.word_spacing(word_spacing) {
|
313
|
-
@
|
314
|
-
|
318
|
+
if @draw_text_callback
|
319
|
+
@draw_text_callback.call(fragment.text, :at => [x, y],
|
320
|
+
:kerning => @kerning)
|
321
|
+
else
|
322
|
+
@document.draw_text!(fragment.text, :at => [x, y],
|
323
|
+
:kerning => @kerning)
|
324
|
+
end
|
315
325
|
}
|
316
326
|
|
317
327
|
draw_fragment_overlays(fragment)
|
@@ -371,8 +381,7 @@ module Prawn
|
|
371
381
|
# all fonts
|
372
382
|
fallback_fonts << fragment_font
|
373
383
|
|
374
|
-
hash[:text].
|
375
|
-
char = [char_int].pack("U")
|
384
|
+
hash[:text].unicode_characters do |char|
|
376
385
|
@document.font(fragment_font)
|
377
386
|
font_glyph_pairs << [find_font_for_this_glyph(char,
|
378
387
|
@document.font.family,
|