File Coverage

blib/lib/CtrlO/PDF.pm
Criterion Covered Total %
statement 124 212 58.4
branch 20 68 29.4
condition 8 22 36.3
subroutine 26 39 66.6
pod 10 10 100.0
total 188 351 53.5


line stmt bran cond sub pod time code
1             package CtrlO::PDF;
2              
3 2     2   108279 use strict;
  2         11  
  2         58  
4 2     2   10 use warnings;
  2         4  
  2         44  
5 2     2   1269 use utf8;
  2         28  
  2         10  
6              
7 2     2   70 use Carp qw/croak carp/;
  2         3  
  2         116  
8 2     2   1070 use Image::Info qw(image_info image_type);
  2         3467  
  2         119  
9 2     2   1330 use Moo;
  2         23943  
  2         9  
10 2     2   4240 use MooX::Types::MooseLike::Base qw(:all);
  2         13859  
  2         668  
11 2     2   1906 use PDF::Table;
  2         16200  
  2         75  
12 2     2   1110 use PDF::TextBlock 0.13;
  2         63281  
  2         17  
13              
14             our $VERSION = '0.21';
15              
16             =head1 NAME
17              
18             CtrlO::PDF - high level PDF creator
19              
20             =head1 SYNOPSIS
21              
22             use CtrlO::PDF;
23             use Text::Lorem;
24              
25             my $pdf = CtrlO::PDF->new(
26             logo => "sample/logo.png", # optional
27             logo_scaling => 0.5, # Default
28             width => 595, # Default (A4, portrait mode)
29             height => 842, # Default (A4, portrait mode)
30             orientation => "portrait", # Default
31             margin => 40, # Default, all 4 sides
32             top_padding => 0, # Default
33             header => "My PDF document header", # optional
34             footer => "My PDF document footer", # optional
35             PDFlib => "API2", # Default is Builder
36             );
37             # width, height page dimensions in points (default A4 paper)
38             # orientation defaults to portrait (taller than wide)
39             # margin in points on all four sides
40             # top padding below header in points
41             # header, footer text line to place at top or bottom
42             # PDFlib actually checked only for '[aA]' or '[bB]', permitting a wide
43             # range of formats to specify the PDF support library
44              
45             # Add a page
46             $pdf->add_page;
47              
48             # Add headings
49             $pdf->heading('This is the main heading');
50             $pdf->heading('This is a sub-heading', size => 12);
51              
52             # Add paragraph text
53             my $lorem = Text::Lorem->new();
54             my $paras = $lorem->paragraphs(30);
55             $pdf->text($paras);
56              
57             # Add a table
58             my $data =[
59             ['Fruit', 'Quantity'], # Table header
60             ['Apples', 120],
61             ['Pears', 90],
62             ['Oranges', 30],
63             ];
64              
65             my $hdr_props = {
66             repeat => 1,
67             justify => 'center',
68             font_size => 8,
69             };
70              
71             $pdf->table(
72             data => $data,
73             header_props => $hdr_props,
74             );
75              
76             my $file = $pdf->content;
77              
78             # output the file
79             open my $pdf_out, '>', 'out.pdf';
80             binmode $pdf_out;
81             print $pdf_out $file;
82             close $pdf_out;
83              
84             =head1 DESCRIPTION
85              
86             This module tries to make it easy to create PDFs by providing a high level
87             interface to a number of existing PDF modules. It aims to "do the right thing"
88             by default, allowing minimal coding to create long PDFs. It includes
89             pagination, headings, paragraph text, images and tables. Although there are a
90             number of other modules to create PDFs with a high-level interface, I found
91             that these each lack certain features (e.g. image insertion, paragraph text).
92             This module tries to include each of those features through another existing
93             module. Also, it is built on either PDF::Builder or PDF::API2, and provides
94             access to that object, so content can also be added directly using that,
95             thereby providing any powerful features required.
96              
97             B<Updates in v0.20> Note that version 0.20 contains a number breaking changes
98             to improve the default layout and spacing of a page. This better ensures that
99             content added to a page "just works" in terms of its layout, without needing
100             tweaks to its spacing. For example, headers have better spacing above and below
101             by default. This means that PDFs produced with this version will be laid out
102             differently to those produced with earlier versions. In the main, old code
103             should be able to be updated by simply removing any manual spacing fudges (e.g.
104             manual spacing for headers).
105              
106             =head1 METHODS
107              
108             =cut
109              
110             =head2 pdf
111              
112             Returns the C<PDF::Builder> or C<PDF::API2> object used to create the PDF.
113              
114             =cut
115              
116             has pdf => (
117             is => 'lazy',
118             );
119              
120             sub _build_pdf
121 1     1   10 { my $self = shift;
122              
123             # what's available?
124 1         2 my ($rc);
125 1 50       9 if (lc($self->PDFlib) =~ m/b/) {
126             # PDF::Builder preferred, try to see if it's installed
127 1         2 $rc = eval {
128 1         907 require PDF::Builder;
129 1         240602 1;
130             };
131 1 50       7 if (!defined $rc) {
132             # PDF::Builder not available, try PDF::API2
133 0         0 $rc = eval {
134 0         0 require PDF::API2;
135 0         0 1;
136             };
137 0 0       0 if (!defined $rc) {
138 0         0 die "Neither PDF::Builder nor PDF::API2 is installed!\n";
139             } else {
140             #print "PDF::Builder requested, but was not available. Using PDF::API2\n";
141 0         0 PDF::API2->new;
142             }
143             } else {
144 1         10 PDF::Builder->new;
145             }
146              
147             } else {
148             # PDF::API2 preferred, try to see if it's installed
149 0         0 $rc = eval {
150 0         0 require PDF::API2;
151 0         0 1;
152             };
153 0 0       0 if (!defined $rc) {
154             # PDF::API2 not available, try PDF::Builder
155 0         0 $rc = eval {
156 0         0 require PDF::Builder;
157 0         0 1;
158             };
159 0 0       0 if (!defined $rc) {
160 0         0 die "Neither PDF::API2 nor PDF::Builder is installed!\n";
161             } else {
162             #print "PDF::API2 requested, but was not available. Using PDF::Builder\n";
163 0         0 PDF::Builder->new;
164             }
165             } else {
166 0         0 PDF::API2->new;
167             }
168              
169             }
170              
171             }
172              
173             =head2 page
174              
175             Returns the current PDF page.
176              
177             =cut
178              
179             # Current page
180             has page => (
181             is => 'rwp',
182             lazy => 1,
183 0     0   0 builder => sub { $_[0]->add_page },
184             );
185              
186             =head2 add_page
187              
188             Adds a PDF page and returns it.
189              
190             Note that when a PDF page is added (either via this method or automatically)
191             the is_new_page flag records that a new page is in use with no content. See
192             that method for more details.
193              
194             =cut
195              
196             sub add_page
197 1     1 1 5937 { my $self = shift;
198 1         19 my $page = $self->pdf->page;
199 1         2202 $page->mediabox(0, 0, $self->width, $self->height);
200 1         217 $self->_set_page($page);
201 1         5 $self->_set__y($self->_y_start_default); # Reset y cursor
202             # Flag that we have just started a new page. Because text is positioned from
203             # its bottom-left corner, we will need to move the cursor down further to
204             # account for the font size of the text, but we don't know that yet.
205 1         80 $self->_set_is_new_page(1);
206 1         60 return $page;
207             }
208              
209             =head2 is_new_page
210              
211             Whether the current page is new with no content. When the heading or text
212             methods are called and this is true, additional top margin is added to account
213             for the height of the text being added. Any other content manually added will
214             not include this margin and will leave the internal new page flag as true.
215              
216             =cut
217              
218             has is_new_page => (
219             is => 'rwp',
220             isa => Bool,
221             default => 1,
222             );
223              
224             =head2 clear_new_page
225              
226             Manually clears the is_new_page flag.
227              
228             =cut
229              
230             sub clear_new_page
231 0     0 1 0 { my $self = shift;
232 0         0 $self->_set_is_new_page(0);
233             }
234              
235             =head2 orientation
236              
237             Sets or returns the page orientation (portrait or landscape). The default is
238             Portrait (taller than wide).
239              
240             =cut
241              
242             has orientation => (
243             is => 'ro',
244             isa => Str,
245             default => 'portrait',
246             );
247              
248             =head2 PDFlib
249              
250             Sets or returns the PDF-building library in use. The choices are "PDF::Builder"
251             and "PDF::API2" (case-insensitive). "PDF::Builder" is the default, indicating
252             that PDF::Builder will be used I<unless> it is not found, in which case
253             PDF::API2 will be used. If neither is found, CtrlO::PDF will fail.
254              
255             =cut
256              
257             has PDFlib => (
258             is => 'ro',
259             isa => Str,
260             default => 'PDF::Builder',
261             );
262              
263             =head2 width
264              
265             Sets or returns the width. Default is A4.
266              
267             =cut
268              
269             has width => (
270             is => 'lazy',
271             isa => Int,
272             );
273              
274             sub _build_width
275 1     1   17 { my $self = shift;
276 1 50       23 $self->orientation eq 'portrait' ? 595 : 842; # A4 media
277             }
278              
279             has _width_print => (
280             is => 'lazy',
281             isa => Int,
282             );
283              
284             sub _build__width_print
285 1     1   102 { my $self = shift;
286 1         20 $self->width - $self->margin * 2;
287             }
288              
289             =head2 height
290              
291             Sets or returns the height. Default is A4.
292              
293             =cut
294              
295             has height => (
296             is => 'lazy',
297             isa => Int,
298             );
299              
300             sub _build_height
301 1     1   91 { my $self = shift;
302 1 50       26 $self->orientation eq 'portrait' ? 842 : 595; # A4 media
303             }
304              
305             =head2 margin
306              
307             Sets or returns the page margin. Default 40 pixels.
308              
309             =cut
310              
311             has margin => (
312             is => 'ro',
313             isa => Int,
314             default => 40,
315             );
316              
317             =head2 margin_top
318              
319             Sets or returns the top margin. Defaults to the margin + top_padding +
320             room for the header (if defined) + room for the logo (if defined).
321              
322             =cut
323              
324             has margin_top => (
325             is => 'lazy',
326             isa => Num,
327             );
328              
329             sub _build_margin_top
330 1     1   40 { my $self = shift;
331 1         8 my $size = $self->margin + $self->top_padding;
332 1 50       6 $size += 15 if $self->header; # Arbitrary number to allow 10px of header text
333 1 50       8 if ($self->logo)
334             {
335 0         0 $size += $self->logo_height;
336 0         0 $size += $self->logo_padding;
337             }
338 1         18 return int $size;
339             };
340              
341             =head2 margin_bottom
342              
343             Sets or returns the bottom margin. Defaults to the margin + room for the
344             footer.
345              
346             =cut
347              
348             has margin_bottom => (
349             is => 'lazy',
350             isa => Int,
351             );
352              
353             sub _build_margin_bottom
354 1     1   127 { my $self = shift;
355 1         5 my $size = $self->margin;
356 1         3 $size += 15; # Arbitrary number to allow 10px of footer text
357 1         17 return $size;
358             };
359              
360             =head2 top_padding
361              
362             Sets or returns the top padding (additional to the margin). Default 0.
363              
364             =cut
365              
366             has top_padding => (
367             is => 'ro',
368             isa => Int,
369             default => 0,
370             );
371              
372             =head2 header
373              
374             Sets or returns the header text.
375              
376             =cut
377              
378             has header => (
379             is => 'ro',
380             );
381              
382             =head2 footer
383              
384             Sets or returns the footer text. Page numbers are added automatically.
385              
386             =cut
387              
388             has footer => (
389             is => 'ro',
390             );
391              
392             =head2 font
393              
394             Sets or returns the font. This is based on PDF::Builder or PDF::API2 ttfont,
395             which returns a TrueType or OpenType font object. By default it assumes the
396             font is available in the exact path
397             C<truetype/liberation/LiberationSans-Regular.ttf>. A future
398             version may make this more flexible.
399              
400             =cut
401              
402             has font => (
403             is => 'lazy',
404             );
405              
406             sub _build_font
407 1     1   33 { my $self = shift;
408 1         35 $self->pdf->ttfont('truetype/liberation/LiberationSans-Regular.ttf');
409             }
410              
411             =head2 fontbold
412              
413             As font, but a bold font.
414              
415             =cut
416              
417             has fontbold => (
418             is => 'lazy',
419             );
420              
421             sub _build_fontbold
422 1     1   49 { my $self = shift;
423 1         16 $self->pdf->ttfont('truetype/liberation/LiberationSans-Bold.ttf');
424             }
425              
426             =head2 logo
427              
428             The path to a logo to include in the top-right corner of every page (optional).
429              
430             =cut
431              
432             has logo => (
433             is => 'ro',
434             isa => Str,
435             );
436              
437             =head2 logo_scaling
438              
439             The scaling of the logo. For best results a setting of 0.5 is recommended (the
440             default).
441              
442             =cut
443              
444             has logo_scaling => (
445             is => 'ro',
446             default => 0.5,
447             );
448              
449             =head2 logo_padding
450              
451             The padding below the logo before the text. Defaults to 10 pixels.
452              
453             =cut
454              
455             has logo_padding => (
456             is => 'ro',
457             default => 10,
458             );
459              
460             has logo_height => (
461             is => 'lazy',
462             );
463              
464             sub _build_logo_height
465 0     0   0 { my $self = shift;
466 0 0       0 return 0 if !$self->_logo_info;
467 0         0 $self->_logo_info->{height} * $self->logo_scaling;
468             }
469              
470             has logo_width => (
471             is => 'lazy',
472             );
473              
474             sub _build_logo_width
475 0     0   0 { my $self = shift;
476 0 0       0 return 0 if !$self->_logo_info;
477 0         0 $self->_logo_info->{width} * $self->logo_scaling;
478             }
479              
480             has _logo_info => (
481             is => 'lazy',
482             );
483              
484             sub _build__logo_info
485 0     0   0 { my $self = shift;
486 0 0       0 return if !$self->logo;
487 0         0 image_info($self->logo);
488             }
489              
490             has _x => (
491             is => 'rwp',
492             lazy => 1,
493 1     1   81 builder => sub { $_[0]->margin },
494             );
495              
496             sub _down
497 7     7   21 { my ($self, $points) = @_;
498 7         133 my $y = $self->_y;
499 7         117 $self->_set__y($y - $points);
500             }
501              
502             =head2 y_position
503              
504             Returns the current y position on the page. This value updates as the page is
505             written to, and is the location that content will be positioned at the next
506             write. Note that the value is measured from the bottom of the page.
507              
508             =cut
509              
510             sub y_position
511 0     0 1 0 { my $self = shift;
512 0         0 $self->_y;
513             }
514              
515             =head2 set_y_position($pixels)
516              
517             Sets the current Y position. See L</y_position>.
518              
519             =cut
520              
521             sub set_y_position
522 0     0 1 0 { my ($self, $y) = @_;
523 0 0 0     0 $y && $y =~ /^[0-9]+(\.[0-9]+)?$/
524             or croak "Invalid y value for set_y_position: $y";
525 0         0 $self->_set__y($y);
526             }
527              
528             =head2 move_y_position($pixels)
529              
530             Moves the current Y position, relative to its current value. Positive values
531             will move the cursor up the page, negative values down. See L</y_position>.
532              
533             =cut
534              
535             sub move_y_position
536 0     0 1 0 { my ($self, $y) = @_;
537 0 0 0     0 $y && $y =~ /^[0-9]+(\.[0-9]+)?$/
538             or croak "Invalid y value for move_y_position: $y";
539 0         0 $self->_set__y($self->_y + $y);
540             }
541              
542             has _y => (
543             is => 'rwp',
544             lazy => 1,
545 0     0   0 builder => sub { $_[0]->_y_start_default },
546             );
547              
548             sub _y_start_default
549 1     1   2 { my $self = shift;
550 1         21 return $self->height - $self->margin_top;
551             }
552              
553             =head2 heading($text, %options)
554              
555             Add a heading. If called on a new page, will automatically move the cursor down
556             to account for the heading's height (based on the assumption that one pixel
557             equals one point). Options available are:
558              
559             =over
560              
561             =item size I<n>
562              
563             C<n> is the font size in points, B<default 16>
564              
565             =item indent I<n>
566              
567             C<n> is the amount (in points) to indent the text, B<default 0>
568              
569             =item topmargin I<n>
570              
571             C<n> is the amount (in points) of vertical skip for the margin I<above> the
572             heading, B<default:> calculated automatically based on font size
573              
574             =item bottommargin I<n>
575              
576             C<n> is the amount (in points) of vertical skip for the margin I<below> the
577             heading, B<default:> calculated automatically based on the font size
578              
579             =back
580              
581             =cut
582              
583             # Return the line height based on a font size, with optional ratio
584             sub _line_height {
585 10     10   151 my ($self, $size, $ratio) = @_;
586 10   100     109 $size * ($ratio || 1.5);
587             }
588              
589             # Return the spacing above/below a line based on font size and line height
590             sub _line_spacing {
591 2     2   8 my ($self, $size) = @_;
592 2         9 my $spacing = $self->_line_height($size);
593 2         15 ($spacing - $size) / 2;
594             }
595              
596             sub heading
597 2     2 1 18 { my ($self, $string, %options) = @_;
598              
599 2         41 $self->page; # Ensure that page is built and cursor adjusted for first use
600              
601 2 50       49 $self->add_page if $self->_y < 150; # Make sure there is room for following paragraph text
602 2   100     28 my $size = $options{size} || 16;
603              
604 2 50       13 if ($options{topmargin}) {
    100          
605             # Always let override take precedence
606 0 0       0 $self->_down($options{topmargin}) if $options{topmargin};
607             }
608             elsif ($self->is_new_page)
609             {
610             # If a new page then move down just enough to fit in the font size
611 1         4 $self->_down($size);
612 1         16 $self->_set_is_new_page(0);
613             }
614             else {
615             # Default to top margin based on font size, with slightly higher
616             # spacing ratio than normal text
617 1         6 $self->_down($self->_line_height($size, 1.8));
618             }
619             my $tb = PDF::TextBlock->new({
620             pdf => $self->pdf,
621             page => $self->page,
622 2   50     75 x => $self->_x + ($options{indent} || 0),
623             y => $self->_y,
624             lead => $self->_line_height($size, 1.6),
625             fonts => {
626             # Workaround a bug in PDF::TextBlock which defines word spacing
627             # based on the default font. This can lead to spacing that is too
628             # small if only using a bold font with a large font size. Define
629             # the default font to be the same as the bold font that we will
630             # use.
631             default => PDF::TextBlock::Font->new({
632             pdf => $self->pdf,
633             font => $self->fontbold,
634             size => $size,
635             }),
636             b => PDF::TextBlock::Font->new({
637             pdf => $self->pdf,
638             font => $self->fontbold,
639             size => $size,
640             }),
641             },
642             });
643 2         620620 $tb->text('<b>'.$string.'</b>');
644 2         37 my ($endw, $ypos) = $tb->apply;
645 2         270830 $self->_set__y($ypos + $self->_line_height($size)); # Move cursor back to end of last line printed
646              
647             # Unless otherwise defined, add a bottom margin relative to the font size,
648             # but smaller than the top margin
649 2 50       12 my $bottommargin = defined $options{bottommargin} ? $options{bottommargin} : $self->_line_height($size, 0.4);;
650              
651 2         12 $self->_down($bottommargin);
652             }
653              
654             =head2 text($text, %options)
655              
656             Add paragraph text. This will automatically paginate. Options available are:
657              
658             =over
659              
660             =item size I<n>
661              
662             C<n> is the font size in points, B<default 10>
663              
664             =item indent I<n>
665              
666             C<n> is the amount (in points) to indent the paragraph first line, B<default 0>
667              
668             =item color I<name>
669              
670             C<name> is the string giving the text color, B<default 'black'>
671              
672             =back
673              
674             =cut
675              
676             sub text
677 1     1 1 8 { my ($self, $string, %options) = @_;
678 1         26 my $text = $self->page->text;
679 1   50     501 my $size = $options{size} || 10;
680 1   50     7 my $color = $options{color} || 'black';
681              
682 1         47 $self->page; # Ensure that page is built and cursor adjusted for first use
683              
684 1 50       16 if ($self->is_new_page)
685             {
686 0         0 $self->_set_is_new_page(0);
687             }
688             else {
689             # Only create spacing if below other content
690 1         6 $self->_down($self->_line_spacing($size));
691             }
692              
693             # Line spacing already accounted for above, now allow enough room for actual font size
694 1         5 $self->_down($size);
695              
696             my $tb = PDF::TextBlock->new({
697             pdf => $self->pdf,
698             page => $self->page,
699 1   50     20 x => $self->_x + ($options{indent} || 0),
700             y => $self->_y,
701             w => $self->_width_print,
702             h => $self->_y - $self->margin_bottom,
703             lead => $self->_line_height($size),
704             align => 'left',
705             fonts => {
706             default => PDF::TextBlock::Font->new({
707             pdf => $self->pdf,
708             font => $self->font,
709             size => $size,
710             fillcolor => $color,
711             }),
712             b => PDF::TextBlock::Font->new({
713             pdf => $self->pdf,
714             font => $self->fontbold,
715             size => $size,
716             fillcolor => $color,
717             }),
718             },
719             });
720 1         477600 while (1)
721             {
722             # First check whether there is any room on the page for the text. If
723             # not, start a new page. This code is copied directly from the same
724             # check in PDF::TextBlock, with 15 being the default lead. We can no
725             # longer rely on PDF::TextBlock returning the same $string to know to
726             # insert a new page, as we now use that to check for words that are too
727             # long
728 1 50       28 if ($tb->y >= $tb->y - $tb->h + 15) # Same condition as PDF::TextBlock
729             {
730             # For reasons I do not understand, $string manages to gain newlines
731             # between the end and beginning of this loop. Chop them off, and end if
732             # there's nothing left
733 1         41 $string =~ s/\s+$//;
734 1 50       4 !$string and last;
735 1         22 $tb->text($string);
736 1         11 my $endw; my $ypos;
737 1         3 my $string_before = $string;
738 1         9 ($endw, $ypos, $string) = $tb->apply;
739             # Check whether no text has been added to the page. This happens if the
740             # word is too long. If so, warn, chop-off and retry, otherwise an
741             # infinite loop occurs. Ideally the word would be broken - issue will
742             # be raised in PDF::TextBlock to see if this is possible.
743 1 50       63732 if ($string_before eq $string)
744             {
745 0         0 carp "Unable to fit text onto line: $string";
746             # If no more breaks then skip
747 0 0       0 last if $string !~ /\s/;
748             # Otherwise start from after next break
749 0         0 $string =~ s/\S+\s//;
750 0         0 $tb->text($string);
751 0         0 ($endw, $ypos, $string) = $tb->apply;
752             }
753              
754             # Set y cursor to be where the textblock finished, but move cursor
755             # back up to remove new line
756 1         25 $self->_set__y($ypos + $tb->lead);
757             # Now shift down the actual line spacing distance
758 1         16 $self->_down($self->_line_spacing($size));
759 1 50       17 last unless $string; # while loop does not work with $string
760             }
761 0         0 $self->add_page;
762 0         0 $self->_down($size);
763 0         0 $tb = PDF::TextBlock->new({
764             pdf => $self->pdf,
765             page => $self->page,
766             x => $self->_x,
767             y => $self->_y,
768             w => $self->_width_print,
769             h => $self->_y - $self->margin_bottom,
770             lead => $self->_line_height($size),
771             align => 'left',
772             fonts => {
773             default => PDF::TextBlock::Font->new({
774             pdf => $self->pdf,
775             font => $self->font,
776             size => $size,
777             fillcolor => $color,
778             }),
779             b => PDF::TextBlock::Font->new({
780             pdf => $self->pdf,
781             font => $self->fontbold,
782             size => $size,
783             fillcolor => $color,
784             }),
785             },
786             });
787             }
788             }
789              
790             =head2 table(%options)
791              
792             Add a table, based on PDF::Table. Options available are C<data> to pass in the
793             data for the table; all other options are passed to the table method of
794             PDF::Table.
795              
796             =cut
797              
798             sub table
799 0     0 1 0 { my ($self, %options) = @_;
800              
801 0         0 $self->page; # Ensure that page is built and cursor adjusted for first use
802              
803             # Move onto new page if little space left on this one.
804             # TODO Change arbitary "60" to something calculated? Needs to be able to
805             # fit header and one row as a minimum.
806 0 0       0 $self->add_page if $self->_y < 60 + $self->margin_bottom;
807              
808 0         0 my $table = PDF::Table->new;
809              
810 0         0 my $data = delete $options{data};
811              
812             # Create spacing above and below table based on the line spacing for text
813             # of 10 points
814 0         0 $self->_down($self->_line_height(10));
815              
816             # Keep separate so easy to dump for debug
817 0         0 my %dimensions = (
818             next_h => $self->_y_start_default - $self->margin_bottom,
819             x => $self->_x,
820             w => $self->_width_print,
821             font_size => 10,
822             padding => 5,
823             y => $self->_y,
824             h => $self->_y - $self->margin_bottom,
825             next_y => $self->_y_start_default,
826             );
827             my ($final_page, $number_of_pages, $final_y) = $table->table(
828             $self->pdf,
829             $self->page,
830             $data,
831             %dimensions,
832             h_border_w => 2,
833             v_border_w => 0,
834             border_c => '#dddddd',
835             bg_color_odd => '#f9f9f9',
836 0     0   0 new_page_func => sub { $self->add_page },
837 0         0 font => $self->font,
838             header_props => {
839             font => $self->fontbold,
840             repeat => 1,
841             justify => 'left',
842             font_size => 10,
843             bg_color => 'white',
844             fg_color => 'black',
845             },
846             %options,
847             );
848 0         0 $self->clear_new_page;
849 0         0 $self->_set__y($final_y);
850             # As above, padding below table
851 0         0 $self->_down($self->_line_height(10));
852             }
853              
854             sub _image_type
855 0     0   0 { my $file = shift;
856 0         0 my $type = image_type($file);
857             croak "Unable to identify image type for $file: ".$type->{Errno}
858 0 0       0 if $type->{error};
859 0         0 return $type->{file_type};
860             }
861              
862             =head2 image($file, %options)
863              
864             Add an image. Options available are:
865              
866             =over
867              
868             =item scaling I<n>
869              
870             C<n> is the scaling factor for the image, B<default 0.5> (50%)
871              
872             =item alignment I<name>
873              
874             C<name> is the horizontal alignment, B<default center>
875              
876             =back
877              
878             =cut
879              
880             sub image
881 0     0 1 0 { my ($self, $file, %options) = @_;
882 0   0     0 my $scaling = $options{scaling} || 0.5;
883 0         0 my $info = image_info($file);
884 0         0 my $width = $info->{width};
885 0         0 my $height = $info->{height};
886 0   0     0 my $alignment = $options{alignment} || 'center';
887 0         0 $height = $height * $scaling;
888 0         0 $width = $width * $scaling;
889 0 0       0 $self->add_page if $height > $self->_y;
890 0         0 $self->_down($height);
891 0 0       0 my $x = $alignment eq 'left'
    0          
892             ? $self->margin
893             : $alignment eq 'right'
894             ? $self->width - $self->margin - $width
895             : ($self->width / 2) - ($width / 2);
896 0         0 my $type = lc 'image_'._image_type($file);
897 0         0 my $image = $self->pdf->$type($file);
898 0         0 my $gfx = $self->page->gfx;
899 0         0 $gfx->image($image, $x, $self->_y, $scaling);
900 0         0 $self->clear_new_page;
901             }
902              
903             =head2 content
904              
905             Return the PDF content.
906              
907             =cut
908              
909             sub content
910 1     1 1 8 { my $self = shift;
911              
912 1         3 my $logo;
913 1 50       8 if ($self->logo)
914             {
915 0         0 my $type = lc 'image_'._image_type($self->logo);
916 0         0 $logo = $self->pdf->$type($self->logo);
917             }
918 1         47 my $count = $self->pdf->pages;
919 1         26 foreach my $p (1..$count)
920             {
921 1         17 my $page = $self->pdf->openpage($p);
922 1 50       80 if ($logo)
923             {
924 0         0 my $gfx = $page->gfx;
925 0         0 $gfx->image($logo, $self->width - $self->margin - $self->logo_width, $self->height - $self->margin - $self->logo_height, $self->logo_scaling);
926             }
927 1         10 my $text = $page->text;
928 1         458 $text->font($self->font, 10);
929             # Specify the header and footer color, otherwise it takes the color of
930             # the last text block which can lead to unexpected behaviour. TODO:
931             # Allow this to be defined somehow.
932 1         281 $text->fillcolor('black');
933 1 50       190 if (my $header = $self->header)
934             {
935 0         0 $text->translate(int($self->width / 2), $self->height - $self->margin);
936 0         0 $text->text_center($header);
937             }
938 1         28 $text->translate($self->width - $self->margin, $self->margin);
939 1         593 $text->text_right("Page $p of $count");
940 1 50       7658 if (my $footer = $self->footer)
941             {
942 1         15 $text->translate($self->margin, $self->margin);
943 1         606 $text->text($footer);
944             }
945             }
946              
947 1         12378 $self->pdf->stringify;
948             }
949              
950             =head1 LICENSE AND COPYRIGHT
951              
952             Copyright 2018-2021 Ctrl O Ltd
953              
954             This program is free software; you can redistribute it and/or modify it under
955             the terms of either: the GNU General Public License (GPL) as published by the
956             Free Software Foundation; or the Perl Artistic License (PAL).
957              
958             See http://dev.perl.org/licenses/ for more information.
959              
960             =cut
961              
962             1;