File Coverage

blib/lib/PDF/Imposition.pm
Criterion Covered Total %
statement 78 78 100.0
branch 8 8 100.0
condition 5 8 62.5
subroutine 18 18 100.0
pod 4 4 100.0
total 113 116 97.4


line stmt bran cond sub pod time code
1             package PDF::Imposition;
2              
3 10     10   915196 use strict;
  10         108  
  10         297  
4 10     10   54 use warnings;
  10         17  
  10         300  
5 10     10   5423 use Module::Load;
  10         11569  
  10         59  
6 10     10   6678 use Types::Standard qw/Enum Object Maybe Str HashRef/;
  10         787821  
  10         133  
7 10     10   19475 use File::Temp;
  10         159944  
  10         749  
8 10     10   4613 use File::Copy;
  10         21660  
  10         560  
9 10     10   73 use File::Spec;
  10         23  
  10         233  
10 10     10   58 use File::Basename;
  10         22  
  10         891  
11 10     10   5752 use Data::Dumper;
  10         63375  
  10         644  
12 10     10   5411 use PDF::Cropmarks;
  10         2828251  
  10         476  
13 10     10   98 use namespace::clean;
  10         22  
  10         94  
14              
15             use constant {
16             DEBUG => $ENV{AMW_DEBUG},
17 10     10   5013 };
  10         27  
  10         816  
18              
19 10     10   70 use Moo;
  10         21  
  10         65  
20              
21             =head1 NAME
22              
23             PDF::Imposition - Perl module to manage the PDF imposition
24              
25             =head1 VERSION
26              
27             Version 0.26
28              
29             =cut
30              
31             our $VERSION = '0.26';
32              
33             sub version {
34 91     91 1 580 return "PDF::Imposition $VERSION PDF::Cropmarks "
35             . $PDF::Cropmarks::VERSION;
36             }
37              
38              
39             =head1 SYNOPSIS
40              
41             This module is meant to simplify the so-called imposition, i.e.,
42             rearrange the pages of a PDF to get it ready to be printed and folded,
43             with more logical pages placed on the sheet, usually (but not
44             exclusively) on recto and verso.
45              
46             This is what the routine looks like:
47              
48             use PDF::Imposition;
49             my $imposer = PDF::Imposition->new(file => "test.pdf",
50             outfile => "out.pdf",
51             # or # suffix => "-imposed",
52             signature => "40-80",
53             cover => 0,
54             schema => "2up");
55             $imposer->impose;
56             print "Output left in " . $imposer->outfile;
57              
58              
59             Please note that you don't pass the PDF dimensions (which are
60             extracted from the source PDF itself by the class, using the very
61             first page: if you want imposition, I do the reasonable assumption you
62             have all the pages with the same dimensions).
63              
64             =head1 METHODS
65              
66             =head2 Costructor options and accessors
67              
68             =head3 file
69              
70             The input file
71              
72             =head3 outfile
73              
74             The output file
75              
76             =head3 suffix
77              
78             The suffix of the output file (don't mix the two options).
79              
80             =head3 schema
81              
82             The schema to use.
83              
84             =over 4
85              
86             =item 2up
87              
88             See L
89              
90             =item duplex2up
91              
92             See L
93              
94             =item 2down
95              
96             See L
97              
98             =item 2x4x1
99              
100             See L
101              
102             =item 2x4x2
103              
104             See L
105              
106             =item 2side
107              
108             See L
109              
110             =item 4up
111              
112             See L
113              
114             =item 1x4x2cutfoldbind
115              
116             See L
117              
118             =item 1repeat2top
119              
120             See L
121              
122             =item 1repeat2side
123              
124             See L
125              
126             =item 1repeat4
127              
128             See L
129              
130             =item ea4x4
131              
132             See L
133              
134             =item 1x8x2
135              
136             See L
137              
138             =item 1x1
139              
140             See L
141              
142             =back
143              
144             =head3 cover
145              
146             If the last logical page must be placed at the very end, B the
147             blank pages used to pad the signature. (C<2up>, C<2down>
148             C<1x4x2cutfoldbind>, C<4up>, C<1x1> only).
149              
150             Often it happens that we want the last page of the pdf to be the last
151             one on the physical booklet after folding. If C is set to a
152             true value, the last page of the logical pdf will be placed on the
153             last page of the last signature.
154              
155             =head3 signature
156              
157             The signature (integer multiple of four or range): C<2up> and C<2down> only.
158              
159             =head3 paper
160              
161             Passing this option triggers the cropmarks. While the original
162             dimensions are left unchanged, this size represents the size of the
163             logical page which is actually imposed.
164              
165             For example, you have a PDF in a6, you pass C as paper, and schema
166             C<2up>, you are going to get an a4 with 2 a6 with cropmarks.
167              
168             This option is passed to L. See the module
169             documentation for the accepted values.
170              
171             =head3 title
172              
173             The title to set in the PDF meta information. Defaults to the basename.
174              
175             =head2 Cropmarks options
176              
177             The following options are passed verbatim to L. See
178             the module documentation for the meaning and accepted values.
179              
180             =head3 paper_thickness
181              
182             Defaults to C<0.1mm>
183              
184             =head3 font_size
185              
186             Defaults to C<8pt>
187              
188             =head3 cropmark_offset
189              
190             Defaults to C<1mm>
191              
192             =head3 cropmark_length
193              
194             Defaults to C<12mm>
195              
196             =head2 impose
197              
198             Main method which does the actual job. You have to call this to get
199             your file. It returns the output filename.
200              
201             =head2 version
202              
203             Return the version string.
204              
205             =cut
206              
207             sub BUILDARGS {
208 91     91 1 7050792 my ($class, %options) = @_;
209 91   100     764 my $schema = lc(delete $options{schema} || '2up'); # default
210 91         469 $options{_version} = $class->version;
211 91         351 my $loadclass = __PACKAGE__ . '::Schema' . $schema;
212 91         236 my %our_options;
213 91         312 foreach my $cropmark_opt (qw/paper
214             cropmark_offset
215             cropmark_length
216             font_size
217             paper_thickness/) {
218 455 100       1133 if (exists $options{$cropmark_opt}) {
219 60         177 $our_options{$cropmark_opt} = $options{$cropmark_opt};
220             }
221             }
222 91         627 load $loadclass;
223 90 100       5142 unless ($options{title}) {
224 89 100       379 if ($options{file}) {
225 68         4023 $options{title} = basename($options{file});
226             }
227             }
228              
229 90         1965 my $imposer = $loadclass->new(%options);
230 90         4573 $our_options{imposer} = $imposer;
231 90         263 $our_options{schema} = $schema;
232 90         253 $our_options{_schema_class} = $loadclass;
233 90         262 $our_options{title} = $options{title};
234 90         434 $our_options{_schema_options} = { %options };
235 90         1856 return \%our_options;
236             }
237              
238             has schema => (is => 'ro',
239             required => 1,
240             isa => Enum[__PACKAGE__->available_schemas]);
241              
242             has _schema_class => (is => 'ro',
243             isa => Str,
244             required => 1);
245              
246             has _schema_options => (is => 'ro',
247             isa => HashRef,
248             required => 1);
249              
250             has imposer => (is => 'rwp',
251             required => 1,
252             handles => [qw/file outfile suffix
253             cover
254             signature
255             computed_signature
256             total_pages
257             orig_width
258             orig_height
259             dimensions
260             total_output_pages
261             /],
262             isa => Object);
263              
264             has paper => (is => 'ro',
265             isa => Maybe[Str]);
266              
267             has paper_thickness => (is => 'ro',
268             isa => Str,
269             default => sub { '0.1mm' });
270              
271             has cropmark_offset => (is => 'ro',
272             isa => Str,
273             default => sub { '1mm' });
274              
275             has cropmark_length => (is => 'ro',
276             isa => Str,
277             default => sub { '12mm' });
278              
279             has font_size => (is => 'ro',
280             isa => Str,
281             default => sub { '8pt' });
282              
283             has title => (is => 'ro',
284             isa => Maybe[Str]);
285              
286             has job_name => (is => 'lazy',
287             isa => Str);
288              
289             sub _build_job_name {
290 28     28   421 my $self = shift;
291 28   33     174 my $name = $self->title || basename($self->file);
292 28         563 return $name;
293             }
294              
295             sub impose {
296 68     68 1 25068 my $self = shift;
297 68         532 my $tmpdir = File::Temp->newdir(CLEANUP => !DEBUG);
298 68 100       24316 if (my $cropmark_paper = $self->paper) {
299 28         75 my %imposer_options = %{ $self->_schema_options };
  28         331  
300             # clone the parameter and set outfile and file
301              
302 28   66     158 $imposer_options{outfile} ||= $self->imposer->output_filename;
303 28         415 my $crop_output = $imposer_options{file} = File::Spec->catfile($tmpdir, 'with-crop-marks.pdf');
304              
305             # pass it to cropmarks
306             my %crop_args = (
307             title => $self->job_name,
308             input => $self->file,
309             output => $crop_output,
310             paper => $cropmark_paper,
311             cover => $imposer_options{cover},
312 28         1146 signature => $self->imposer->computed_signature,
313             paper_thickness => $self->paper_thickness,
314             cropmark_offset => $self->cropmark_offset,
315             cropmark_length => $self->cropmark_length,
316             font_size => $self->font_size,
317             $self->imposer->cropmarks_options,
318             );
319 28         93 print Dumper(\%crop_args) if DEBUG;
320              
321             # rebuild the imposer, which should free the memory as well
322 28         901 $self->_set_imposer($self->_schema_class->new(%imposer_options));
323              
324 28         94869 my $cropper = PDF::Cropmarks->new(%crop_args);
325 28         100995 $cropper->add_cropmarks;
326 24         30006553 print "# cropping output in $crop_output\n" if DEBUG;
327 24         164 print Dumper($self->imposer) if DEBUG;
328             }
329             # in any case impose
330 64         20133 return $self->imposer->impose;
331             }
332              
333             =head2 available_schemas
334              
335             Called on the class (not on the object returned by C) will report
336             the list of available schema.
337              
338             E.g.
339              
340             PDF::Imposition->available_schemas;
341              
342             =cut
343              
344             sub available_schemas {
345 13     13 1 6527 return qw/2up 2down 2side 2x4x2 1x4x2cutfoldbind
346             2x4x1
347             duplex2up
348             4up 1repeat2top 1repeat2side 1repeat4 ea4x4
349             1x8x2 1x1/
350             }
351              
352             =head1 INTERNALS
353              
354             =over 4
355              
356             =item BUILDARGS
357              
358             =item imposer
359              
360             =item DEBUG
361              
362             Constant picked from AMW_DEBUG environment.
363              
364             =back
365              
366             =head1 AUTHOR
367              
368             Marco Pessotto, C<< >>
369              
370             =head1 BUGS
371              
372             Please report any bugs or feature requests to the author's email. If
373             you find a bug, please provide a minimal example file which reproduces
374             the problem (so I can add it to the test suite).
375              
376             Or, at your discretion, feel free to use the CPAN's RT.
377              
378             =head1 SUPPORT
379              
380             You can find documentation for this module with the perldoc command.
381              
382             perldoc PDF::Imposition
383              
384             =head1 REPOSITORY
385              
386             L
387              
388             =head1 SEE ALSO
389              
390             =over 4
391              
392             =item psutils
393              
394             L (shipped by any decent
395             GNU/Linux distro and in TeXlive!). If you don't bother the
396             PDF->PS->PDF route, it's a great and useful tool which just aged well.
397              
398             =item pdfpages
399              
400             L
401              
402             =item pdfjam
403              
404             L
405             (buil on the top of pdfpages)
406              
407             =item ConTeXt
408              
409             L
410              
411             The names of schemas are taken straight from the ConTeXt ones (if
412             existing), as described in the book I, by Willi
413             Egger, Hans Hagen and Taco Hoekwater, 2011.
414              
415             =back
416              
417             =head1 TODO
418              
419             The idea is to provide a wide range of imposition schemas (at least
420             the same provided by ConTeXt). This could require some time. If you
421             want to contribute, feel free to fork the repository and send a pull
422             request or a patch (please include documentation and at some tests).
423              
424             =head1 LICENSE
425              
426             This program is free software; you can redistribute it and/or modify
427             it under the terms of either: the GNU General Public License as
428             published by the Free Software Foundation; or the Artistic License.
429              
430             =cut
431              
432             1; # End of PDF::Imposition