- # If the content is wider than the specified width, we need to add the text as a text block
- if($record->[$j] !~ m#(.\n.)# and $record_widths->[$j] and ($record_widths->[$j] < $this_width))
- {
- my $space = $pad_left;
- if($col_props->[$j]->{justify} eq 'right')
- {
- $space = $this_width -($txt->advancewidth($record->[$j]) + $pad_right);
- }
- $txt->translate( $cur_x + $space, $text_start );
- $txt->text( $record->[$j] );
- }
- # Otherwise just use the $page->text() method
- else
- {
- my($width_of_last_line, $ypos_of_last_line, $left_over_text) = $self->text_block(
- $txt,
- $record->[$j],
- x => $cur_x + $pad_left,
- y => $text_start,
- w => $this_width - $pad_w,
- h => $cur_y - $bot_marg - $pad_top - $pad_bot,
- align => $col_props->[$j]->{justify},
- lead => $lead
- );
- # Desi - Removed $lead because of fixed incorrect ypos bug in text_block
- my $this_row_h = $cur_y - ( $ypos_of_last_line - $pad_bot );
- $row_h = $this_row_h if $this_row_h > $row_h;
- if( $left_over_text )
- {
- $leftovers->[$j] = $left_over_text;
- $do_leftovers = 1;
- }
- }
- $cur_x += $calc_column_widths->[$j];
-
- push @vertical_lines, (!$colspan || (1 >= $colspan)) ? 1 : 0;
- $colspan-- if ($colspan);
- }
- if( $do_leftovers )
- {
- unshift @$data, $leftovers;
- unshift @$row_props, $record_widths;
- $rows_counter--;
- }
- # Draw cell bgcolor
- # This has to be separately from the text loop
- # because we do not know the final height of the cell until all text has been drawn
- $cur_x = $xbase;
- for(my $j =0;$j < scalar(@$record);$j++)
- {
- if ( $cell_props->[$row_cnt][$j]->{'background_color'} ||
- $col_props->[$j]->{'background_color'} ||
- $background_color )
- {
- $gfx_bg->rect( $cur_x, $cur_y-$row_h, $calc_column_widths->[$j], $row_h);
- if ( $cell_props->[$row_cnt][$j]->{'background_color'} && !$first_row )
- {
- $gfx_bg->fillcolor($cell_props->[$row_cnt][$j]->{'background_color'});
- }
- elsif( $col_props->[$j]->{'background_color'} && !$first_row )
- {
- $gfx_bg->fillcolor($col_props->[$j]->{'background_color'});
- }
- else
- {
- $gfx_bg->fillcolor($background_color);
- }
- $gfx_bg->fill();
- }
-
- $cur_x += $calc_column_widths->[$j];
-
- if ($line_w && $vertical_lines[$j] && ($j != (scalar(@{ $record }) - 1))) {
- $gfx->move($cur_x, $cur_y);
- $gfx->vline($cur_y - $row_h);
- $gfx->fillcolor($border_color);
+ # Init cell size limits
+ $space_w = $txt->advancewidth( "\x20" );
+ $column_widths->[$column_idx] = 0;
+ $max_col_w = 0;
+ $min_col_w = 0;
+
+ my @words = split( /\s+/, $data->[$row_idx][$column_idx] );
+
+ foreach( @words )
+ {
+ unless( exists $word_widths->{$_} )
+ { # Calculate the width of every word and add the space width to it
+ $word_widths->{$_} = $txt->advancewidth( $_ ) + $space_w;
+ }
+
+ $column_widths->[$column_idx] += $word_widths->{$_};
+ $min_col_w = $word_widths->{$_} if( $word_widths->{$_} > $min_col_w );
+ $max_col_w += $word_widths->{$_};
+ }
+
+ $min_col_w += $pad_left + $pad_right;
+ $max_col_w += $pad_left + $pad_right;
+ $column_widths->[$column_idx] += $pad_left + $pad_right;
+
+ # Keep a running total of the overall min and max widths
+ $col_props->[$column_idx]->{'min_w'} ||= 0;
+ $col_props->[$column_idx]->{'max_w'} ||= 0;
+
+ if( $min_col_w > $col_props->[$column_idx]->{'min_w'} )
+ { # Calculated Minimum Column Width is more than user-defined
+ $col_props->[$column_idx]->{'min_w'} = $min_col_w ;
+ }
+
+ if( $max_col_w > $col_props->[$column_idx]->{'max_w'} )
+ { # Calculated Maximum Column Width is more than user-defined
+ $col_props->[$column_idx]->{'max_w'} = $max_col_w ;
+ }
+ }#End of for(my $column_idx....
+
+ $row_col_widths->[$row_idx] = $column_widths;
+
+ # Copy the calculated row properties of header row.
+ if (ref $header_props && $row_idx < $header_props->{num_header_rows}) {
+ push @header_row_widths, [ @{ $column_widths } ];
+ }
+ }
+
+ # Calc real column widths and expand table width if needed.
+ my $calc_column_widths;
+ ($calc_column_widths, $width) = CalcColumnWidths( $col_props, $width );
+ my $num_cols = scalar @{ $calc_column_widths };
+
+ # Lets draw what we have!
+ my $row_index = 0;
+ # Store header row height for later use if headers have to be repeated
+ my @header_row_heights = @$rows_height[0 .. $header_props->{num_header_rows}-1];
+
+ my ( $gfx, $gfx_bg, $background_color, $font_color, $bot_marg, $table_top_y, $text_start);
+
+ my $remaining_header_rows = $header_props ? $header_props->{num_header_rows} : 0;
+
+ # Each iteration adds a new page as neccessary
+ while(scalar(@{$data}))
+ {
+ my ($page_header, $columns_number);
+
+ if($pg_cnt == 1)
+ {
+ $table_top_y = $ybase;
+ $bot_marg = $table_top_y - $height;
+ }
+ else
+ {
+ if(ref $arg{'new_page_func'})
+ {
+ $page = &{$arg{'new_page_func'}};
+ }
+ else
+ {
+ $page = $pdf->page;
+ }
+
+ $table_top_y = $next_y;
+ $bot_marg = $table_top_y - $next_h;
+
+ if( ref $header_props and $header_props->{'repeat'})
+ {
+ unshift @$data, @header_rows;
+ unshift @$row_col_widths, @header_row_widths;
+ unshift @$rows_height, @header_row_heights;
+ $remaining_header_rows = $header_props->{num_header_rows};
+ }
+ }
+
+ # Check for safety reasons
+ if( $bot_marg < 0 )
+ { # This warning should remain i think
+# carp "!!! Warning: !!! Incorrect Table Geometry! Setting bottom margin to end of sheet!\n";
+ $bot_marg = 0;
+ }
+
+ $gfx_bg = $page->gfx;
+ $txt = $page->text;
+ $txt->font($fnt_name, $fnt_size);
+
+ $cur_y = $table_top_y;
+
+ if ($line_w)
+ {
+ $gfx = $page->gfx;
+ $gfx->strokecolor($border_color);
+ $gfx->linewidth($line_w);
+
+ # Draw the top line
+ if ($horiz_borders)
+ {
+ $gfx->move( $xbase , $cur_y );
+ $gfx->hline($xbase + $width );
+ }
+ }
+ else
+ {
+ $gfx = undef;
+ }
+
+ # Each iteration adds a row to the current page until the page is full
+ # or there are no more rows to add
+ # Row_Loop
+ while(scalar(@{$data}) and $cur_y-$row_h > $bot_marg)
+ {
+ # Remove the next item from $data
+ my $record = shift @{$data};
+
+ # Get columns number to know later how many vertical lines to draw
+ # TODO: get the max number of columns per page as currently last row's columns overrides
+ $columns_number = scalar(@$record);
+
+ # Get the next set of row related settings
+ # Row Height
+ my $pre_calculated_row_height = shift @$rows_height;
+
+ # Row cell widths
+ my $record_widths = shift @$row_col_widths;
+
+ # Row coloumn props - TODO in another commit
+
+ # Row cell props - TODO in another commit
+
+ # Added to resolve infite loop bug with returned undef values
+ for(my $d = 0; $d < scalar(@{$record}) ; $d++)
+ {
+ $record->[$d] = ' ' unless( defined $record->[$d]);
+ }
+
+ # Choose colors for this row
+ $background_color = ($row_index - $header_props->{num_header_rows}) % 2 ? $background_color_even : $background_color_odd;
+ $font_color = ($row_index - $header_props->{num_header_rows}) % 2 ? $font_color_even : $font_color_odd;
+
+ #Determine current row height
+ my $current_row_height = $pad_top + $pre_calculated_row_height + $pad_bot;
+
+ # $row_h is the calculated global user requested row height.
+ # It will be honored, only if it has bigger value than the calculated one.
+ # TODO: It's questionable if padding should be inclided in this calculation or not
+ if($current_row_height < $row_h){
+ $current_row_height = $row_h;
+ }
+
+ # Define the font y base position for this line.
+ $text_start = $cur_y - ($current_row_height - $pad_bot);
+
+ my $cur_x = $xbase;
+ my $leftovers = undef; # Reference to text that is returned from textblock()
+ my $do_leftovers = 0;
+ my ($colspan, @vertical_lines);
+
+ # Process every cell(column) from current row
+ for( my $column_idx = 0; $column_idx < scalar( @$record); $column_idx++ )
+ {
+ next unless $col_props->[$column_idx]->{'max_w'};
+ next unless $col_props->[$column_idx]->{'min_w'};
+ $leftovers->[$column_idx] = undef;
+
+ # look for font information for this cell
+ my ($cell_font, $cell_font_size, $cell_font_color, $justify);
+
+ if( $remaining_header_rows and ref $header_props)
+ {
+ $cell_font = $header_props->{'font'};
+ $cell_font_size = $header_props->{'font_size'};
+ $cell_font_color = $header_props->{'font_color'};
+ $justify = $header_props->{'justify'};
+ }
+
+ # Get the most specific value if none was already set from header_props
+ $cell_font ||= $cell_props->[$row_index][$column_idx]->{'font'}
+ || $col_props->[$column_idx]->{'font'}
+ || $fnt_name;
+
+ $cell_font_size ||= $cell_props->[$row_index][$column_idx]->{'font_size'}
+ || $col_props->[$column_idx]->{'font_size'}
+ || $fnt_size;
+
+ $cell_font_color ||= $cell_props->[$row_index][$column_idx]->{'font_color'}
+ || $col_props->[$column_idx]->{'font_color'}
+ || $font_color;
+
+ $justify ||= $cell_props->[$row_index][$column_idx]->{'justify'}
+ || $col_props->[$column_idx]->{'justify'}
+ || $arg{'justify'}
+ || 'left';
+
+ # Init cell font object
+ $txt->font( $cell_font, $cell_font_size );
+ $txt->fillcolor($cell_font_color);
+
+ my $this_width;
+ if (!$remaining_header_rows && $cell_props->[$row_index + $header_props->{num_header_rows}][$column_idx]->{colspan}) {
+ $colspan = $cell_props->[$row_index + $header_props->{num_header_rows}][$column_idx]->{colspan};
+ } elsif ($remaining_header_rows && ($header_row_cell_props[$header_props->{num_header_rows} - $remaining_header_rows][$column_idx]->{colspan})) {
+ $colspan = $header_row_cell_props[$header_props->{num_header_rows} - $remaining_header_rows][$column_idx]->{colspan};
+ }
+
+ if ($colspan) {
+ $colspan = $num_cols - $column_idx if (-1 == $colspan);
+ my $last_idx = $column_idx + $colspan - 1;
+ $this_width = sum @{ $calc_column_widths }[$column_idx..$last_idx];
+ } else {
+ $this_width = $calc_column_widths->[$column_idx];
+ }
+
+ # If the content is wider than the specified width, we need to add the text as a text block
+ if( $record->[$column_idx] !~ m/(.\n.)/ and
+ $record_widths->[$column_idx] and
+ $record_widths->[$column_idx] <= $this_width
+ ){
+ my $space = $pad_left;
+ if ($justify eq 'right')
+ {
+ $space = $this_width -($txt->advancewidth($record->[$column_idx]) + $pad_right);
+ }
+ elsif ($justify eq 'center')
+ {
+ $space = ($this_width - $txt->advancewidth($record->[$column_idx])) / 2;