+    $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();