+ $num_header_rows = scalar @{ $self->{custom_headers} };
+
+ foreach my $custom_header_row (@{ $self->{custom_headers} }) {
+ $data_row = [];
+ $cell_props_row = [];
+ push @data, $data_row;
+ push @cell_props, $cell_props_row;
+
+ foreach my $custom_header_col (@{ $custom_header_row }) {
+ push @{ $data_row }, $custom_header_col->{text};
+
+ my $num_output = ($custom_header_col->{colspan} * 1 > 1) ? $custom_header_col->{colspan} : 1;
+ if ($num_output > 1) {
+ push @{ $data_row }, ('') x ($num_output - 1);
+ push @{ $cell_props_row }, { 'colspan' => $num_output };
+ push @{ $cell_props_row }, ({ }) x ($num_output - 1);
+
+ } else {
+ push @{ $cell_props_row }, {};
+ }
+ }
+ }
+ }
+
+ foreach my $row_set (@{ $self->{data} }) {
+ if ('HASH' eq ref $row_set) {
+ if ($row_set->{type} eq 'colspan_data') {
+ push @data, [ $row_set->{data} ];
+
+ $cell_props_row = [];
+ push @cell_props, $cell_props_row;
+
+ foreach (0 .. $num_columns - 1) {
+ push @{ $cell_props_row }, { 'background_color' => '#666666',
+ # BUG PDF:Table -> 0.9.12:
+ # font_color is used in next row, so dont set font_color
+ # 'font_color' => '#ffffff',
+ 'colspan' => $_ == 0 ? -1 : undef, };
+ }
+ }
+ next;
+ }
+
+ foreach my $row (@{ $row_set }) {
+ $data_row = [];
+ $cell_props_row = [];
+
+ push @data, $data_row;
+ push @cell_props, $cell_props_row;
+
+ my $col_idx = 0;
+ foreach my $col_name (@visible_columns) {
+ my $col = $row->{$col_name};
+ push @{ $data_row }, join("\n", @{ $col->{data} || [] });
+
+ $column_props[$col_idx]->{justify} = 'right' if ($col->{align} eq 'right');
+
+ my $cell_props = { };
+ push @{ $cell_props_row }, $cell_props;
+
+ if ($col->{colspan} && $col->{colspan} > 1) {
+ $cell_props->{colspan} = $col->{colspan};
+ }
+
+ $col_idx++;
+ }
+ }
+ }
+
+ foreach my $i (0 .. scalar(@data) - 1) {
+ my $aref = $data[$i];
+ my $num_columns_here = scalar @{ $aref };
+
+ if ($num_columns_here < $num_columns) {
+ push @{ $aref }, ('') x ($num_columns - $num_columns_here);
+ } elsif ($num_columns_here > $num_columns) {
+ splice @{ $aref }, $num_columns;
+ }
+ }
+
+ my $papersizes = {
+ 'a3' => [ 842, 1190 ],
+ 'a4' => [ 595, 842 ],
+ 'a5' => [ 420, 595 ],
+ 'letter' => [ 612, 792 ],
+ 'legal' => [ 612, 1008 ],
+ };
+
+ my %supported_fonts = map { $_ => 1 } qw(courier georgia helvetica times verdana);
+
+ my $paper_size = defined $pdfopts->{paper_size} && defined $papersizes->{lc $pdfopts->{paper_size}} ? lc $pdfopts->{paper_size} : 'a4';
+ my ($paper_width, $paper_height);
+
+ if (lc $pdfopts->{orientation} eq 'landscape') {
+ ($paper_width, $paper_height) = @{$papersizes->{$paper_size}}[1, 0];
+ } else {
+ ($paper_width, $paper_height) = @{$papersizes->{$paper_size}}[0, 1];
+ }
+
+ my $margin_top = _cm2bp($pdfopts->{margin_top} || 1.5);
+ my $margin_bottom = _cm2bp($pdfopts->{margin_bottom} || 1.5);
+ my $margin_left = _cm2bp($pdfopts->{margin_left} || 1.5);
+ my $margin_right = _cm2bp($pdfopts->{margin_right} || 1.5);
+
+ my $table = PDF::Table->new();
+ my $pdf = PDF::API2->new();
+ my $page = $pdf->page();
+
+ $pdf->mediabox($paper_width, $paper_height);
+
+ my $font = $pdf->corefont(defined $pdfopts->{font_name} && $supported_fonts{lc $pdfopts->{font_name}} ? ucfirst $pdfopts->{font_name} : 'Verdana',
+ '-encoding' => $font_encoding);
+ my $font_size = $pdfopts->{font_size} || 7;
+ my $title_font_size = $font_size + 1;
+ my $padding = 1;
+ my $font_height = $font_size + 2 * $padding;
+ my $title_font_height = $font_size + 2 * $padding;
+
+ my $header_height = $opts->{title} ? 2 * $title_font_height : undef;
+ my $footer_height = $pdfopts->{number} ? 2 * $font_height : undef;
+
+ my $top_text_height = 0;
+
+ if ($self->{options}->{top_info_text}) {
+ my $top_text = $self->{options}->{top_info_text};
+ $top_text =~ s/\r//g;
+ $top_text =~ s/\n+$//;
+
+ my @lines = split m/\n/, $top_text;
+ $top_text_height = $font_height * scalar @lines;
+
+ foreach my $line_no (0 .. scalar(@lines) - 1) {
+ my $y_pos = $paper_height - $margin_top - $header_height - $line_no * $font_height;
+ my $text_obj = $page->text();
+
+ $text_obj->font($font, $font_size);
+ $text_obj->translate($margin_left, $y_pos);
+ $text_obj->text($lines[$line_no]);
+ }
+ }
+
+ $table->table($pdf,
+ $page,
+ \@data,
+ 'x' => $margin_left,
+ 'w' => $paper_width - $margin_left - $margin_right,
+ 'start_y' => $paper_height - $margin_top - $header_height - $top_text_height,
+ 'next_y' => $paper_height - $margin_top - $header_height,
+ 'start_h' => $paper_height - $margin_top - $margin_bottom - $header_height - $footer_height - $top_text_height,
+ 'next_h' => $paper_height - $margin_top - $margin_bottom - $header_height - $footer_height,
+ 'padding' => 1,
+ 'background_color_odd' => '#ffffff',
+ 'background_color_even' => '#eeeeee',
+ 'font' => $font,
+ 'font_size' => $font_size,
+ 'font_color' => '#000000',
+ 'num_header_rows' => $num_header_rows,
+ 'header_props' => {
+ 'bg_color' => '#ffffff',
+ 'repeat' => 1,
+ 'font_color' => '#000000',
+ },
+ 'column_props' => \@column_props,
+ 'cell_props' => \@cell_props,
+ 'max_word_length' => 60,
+ 'border' => 0.5,
+ );
+
+ foreach my $page_num (1..$pdf->pages()) {
+ my $curpage = $pdf->openpage($page_num);
+
+ if ($pdfopts->{number}) {
+ my $label = $main::locale->text("Page #1/#2", $page_num, $pdf->pages());
+ my $text_obj = $curpage->text();
+
+ $text_obj->font($font, $font_size);
+ $text_obj->translate(($paper_width - $margin_left - $margin_right) / 2 + $margin_left - $text_obj->advancewidth($label) / 2, $margin_bottom);
+ $text_obj->text($label);
+ }
+
+ if ($opts->{title}) {
+ my $title = $opts->{title};
+ my $text_obj = $curpage->text();
+
+ $text_obj->font($font, $title_font_size);
+ $text_obj->translate(($paper_width - $margin_left - $margin_right) / 2 + $margin_left - $text_obj->advancewidth($title) / 2,
+ $paper_height - $margin_top);
+ $text_obj->text($title, '-underline' => 1);
+ }
+ }
+
+ my $content = $pdf->stringify();
+
+ $main::lxdebug->message(LXDebug->DEBUG2(),"addattachments ?? =".$form->{report_generator_addattachments}." GL=".$form->{GL});
+ if ($form->{report_generator_addattachments} && $form->{GL}) {
+ $content = $self->append_gl_pdf_attachments($form,$content);
+ }
+
+ # 1. check if we return the report as binary pdf
+ if ($params{want_binary_pdf}) {
+ return $content;
+ }
+ # 2. check if we want and can directly print the report
+ my $printer_command;
+ if ($pdfopts->{print} && $pdfopts->{printer_id}) {
+ $form->{printer_id} = $pdfopts->{printer_id};
+ $form->get_printer_code($myconfig);
+ $printer_command = $form->{printer_command};
+ }
+ if ($printer_command) {
+ $self->_print_content('printer_command' => $printer_command,
+ 'content' => $content,
+ 'copies' => $pdfopts->{copies});
+ $form->{report_generator_printed} = 1;
+
+ } else {
+ # 3. default: redirect http with file attached
+ my $filename = $self->get_attachment_basename();
+
+ print qq|content-type: application/pdf\n|;
+ print qq|content-disposition: attachment; filename=${filename}.pdf\n\n|;
+
+ $::locale->with_raw_io(\*STDOUT, sub {
+ print $content;
+ });
+ }
+}
+
+sub verify_paper_size {
+ my $self = shift;
+ my $requested_paper_size = lc shift;
+ my $default_paper_size = shift;
+
+ my %allowed_paper_sizes = map { $_ => 1 } qw(a3 a4 a5 letter legal);
+
+ return $allowed_paper_sizes{$requested_paper_size} ? $requested_paper_size : $default_paper_size;
+}
+
+sub _print_content {
+ my $self = shift;
+ my %params = @_;
+
+ foreach my $i (1 .. max $params{copies}, 1) {
+ my $printer = IO::File->new("| $params{printer_command}");
+ $main::form->error($main::locale->text('Could not spawn the printer command.')) if (!$printer);
+ $printer->print($params{content});
+ $printer->close();