File Coverage

blib/lib/CtrlO/PDF.pm
Criterion Covered Total %
statement 118 191 61.7
branch 19 60 31.6
condition 10 27 37.0
subroutine 24 38 63.1
pod 10 10 100.0
total 181 326 55.5


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