Skip to content

Commit

Permalink
Backport code prawn to correctly render colspan table cells
Browse files Browse the repository at this point in the history
Ports the following prs:
prawnpdf#712
prawnpdf#620
  • Loading branch information
TheSmartnik committed Apr 15, 2022
1 parent 0649c53 commit 48e2f9e
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 69 deletions.
1 change: 1 addition & 0 deletions lib/prawn.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#
module Prawn #:nodoc:
VERSION = "1.0.0.rc2"
FLOAT_PRECISION = 1.0e-9
end

require "prawn/utilities"
Expand Down
17 changes: 2 additions & 15 deletions lib/prawn/table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#
# This is free software. Please see the LICENSE and COPYING files for details.

require 'prawn/table/column_width_calculator'
require 'prawn/table/cells'
require 'prawn/table/cell'
require 'prawn/table/cell/in_table'
Expand Down Expand Up @@ -567,21 +568,7 @@ def assert_proper_table_data(data)
# Returns an array of each column's natural (unconstrained) width.
#
def natural_column_widths
@natural_column_widths ||=
begin
widths_by_column = Hash.new(0)
cells.each do |cell|
next if cell.is_a?(Cell::SpanDummy)

# Split the width of colspanned cells evenly by columns
width_per_column = cell.width.to_f / cell.colspan
cell.colspan.times do |i|
widths_by_column[cell.column + i] =
[widths_by_column[cell.column + i], width_per_column].max
end
end
widths_by_column.sort_by { |col, _| col }.map { |_, w| w }
end
@natural_column_widths ||= ColumnWidthCalculator.new(cells).natural_widths
end

# Returns the "natural" (unconstrained) width of the table. This may be
Expand Down
54 changes: 2 additions & 52 deletions lib/prawn/table/cells.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,7 @@ def style(options={}, &block)
# Returns the total width of all columns in the selected set.
#
def width
widths = {}
each do |cell|
index = cell.column
per_cell_width = cell.width_ignoring_span.to_f / cell.colspan
cell.colspan.times do |n|
widths[cell.column+n] = [widths[cell.column+n], per_cell_width].
compact.max
end
end
widths.values.inject(0, &:+)
ColumnWidthCalculator.new(self).natural_widths.inject(0, &:+)
end

# Returns minimum width required to contain cells in the set.
Expand Down Expand Up @@ -228,48 +219,7 @@ def index_cells
# each cell, grouped by +row_or_column+.
#
def aggregate_cell_values(row_or_column, meth, aggregate)
values = {}

#calculate values for all cells that do not span accross multiple cells
#this ensures that we don't have a problem if the first line includes
#a cell that spans across multiple cells
each do |cell|
#don't take spanned cells
if cell.colspan == 1 and cell.class != Prawn::Table::Cell::SpanDummy
index = cell.send(row_or_column)
values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
end
end

each do |cell|
index = cell.send(row_or_column)
if cell.colspan > 1
#calculate current (old) return value before we do anything
old_sum = 0
cell.colspan.times { |i|
old_sum += values[index+i] unless values[index+i].nil?
}

#calculate future return value
new_sum = cell.send(meth) * cell.colspan

if new_sum >= old_sum
#not entirely sure why we need this line, but with it the tests pass
values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
#overwrite the old values with the new ones, but only if all entries existed
entries_exist = true
cell.colspan.times { |i| entries_exist = false if values[index+i].nil? }
cell.colspan.times { |i|
values[index+i] = cell.send(meth) if entries_exist
}
end
else
if cell.class == Prawn::Table::Cell::SpanDummy
values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
end
end
end
values.values.inject(0, &:+)
ColumnWidthCalculator.new(self).aggregate_cell_values(row_or_column, meth, aggregate)
end

# Transforms +spec+, a column / row specification, into an object that
Expand Down
53 changes: 51 additions & 2 deletions spec/table_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,34 @@

end

it "illustrates issue #710", :issue => 710 do
partial_width = 40
pdf = Prawn::Document.new({page_size: "LETTER", page_layout: :portrait})
col_widths = [
50,
partial_width, partial_width, partial_width, partial_width
]

day_header = [{
content: "Monday, August 5th, A.S. XLIX",
colspan: 5,
}]

times = [{
content: "Loc",
colspan: 1,
}, {
content: "8:00",
colspan: 4,
}]

data = [ day_header ] + [ times ]

#raised a Prawn::Errors::CannotFit:
#Table's width was set larger than its contents' maximum width (max width 210, requested 218.0)
table = Prawn::Table.new data, pdf, :column_widths => col_widths
end

it "illustrate issue #533" do
data = [['', '', '', '', '',''],
['',{:content => '', :colspan => 5}]]
Expand All @@ -91,15 +119,36 @@
pdf = Prawn::Document.new
first = {:content=>"Foooo fo foooooo",:width=>50,:align=>:center}
second = {:content=>"Foooo",:colspan=>2,:width=>70,:align=>:center}
third = {:content=>"fooooooooooo, fooooooooooooo, fooo, foooooo fooooo",:width=>55,:align=>:center}
fourth = {:content=>"Bar",:width=>15,:align=>:center}
third = {:content=>"fooooooooooo, fooooooooooooo, fooo, foooooo fooooo",:width=>50,:align=>:center}
fourth = {:content=>"Bar",:width=>20,:align=>:center}
table_content = [[
first,
[[second],[third,fourth]]
]]
pdf.move_down(20)
table = Prawn::Table.new table_content, pdf
pdf.table(table_content)
end

#https://github.com/prawnpdf/prawn/issues/407#issuecomment-28556698
it "correctly computes column widths with empty cells + colspan" do
data = [['', ''],
[{:content => '', :colspan => 2}]
]
pdf = Prawn::Document.new

table = Prawn::Table.new data, pdf, :column_widths => [50, 200]
table.column_widths.should == [50.0, 200.0]
end

it "illustrates a variant of problem in issue #407 - comment 28556698" do
pdf = Prawn::Document.new
table_data = [["a", "b", "c"], [{:content=>"d", :colspan=>3}]]
column_widths = [50, 60, 400]

# Before we fixed #407, this line incorrectly raise a CannotFit error
pdf.table(table_data, :column_widths => column_widths)
end
end

describe "#initialize" do
Expand Down

0 comments on commit 48e2f9e

Please sign in to comment.