File Coverage

blib/lib/PCL/Simple.pm
Criterion Covered Total %
statement 45 48 93.7
branch 37 50 74.0
condition n/a
subroutine 6 6 100.0
pod 0 2 0.0
total 88 106 83.0


line stmt bran cond sub pod time code
1             package PCL::Simple;
2              
3             =head1 NAME
4              
5             PCL::Simple - Create PCL for printing plain text files
6              
7             =head1 SYNOPSIS
8              
9             use PCL::Simple qw( PCL_pre PCL_post );
10              
11             open PLAIN, '
12             open SNAZZY, '>ready_for_printing.txt' or die;
13              
14             print SNAZZY PCL_pre( -w => 132, -lpp => 66 );
15             print SNAZZY while ();
16             print SNAZZY PCL_post;
17              
18             close PLAIN;
19             close SNAZZY;
20              
21             =head1 DESCRIPTION
22              
23             PCL::Simple will provide PCL strings that cause your printer to print a plain text file with *exactly* the right font -- i.e. the exact font needed to fill the page with as many fixed width characters across and down as you specify.
24              
25             In addition to providing for your desired width and height layout, the provided PCL strings will also cause the printer to honor your other desires regarding paper size, paper orientation, sides printed, and number of copies.
26              
27             =head1 USAGE
28              
29             Two functions are exportable: PCL_pre and PCL_post.
30              
31             PCL_post takes no parameters, it simply returns a string containing the "Printer Reset Command" and "Universal Exit Language Command" as specified by PCL documentation. This string is meant for appending to the end of your plain text document.
32              
33             PCL_pre takes a list or an href of key value pairs and returns a PCL string for insertion at the beginning of your plain text document. PCL_pre Paramaters are:
34              
35             =over 2
36              
37             =item C<-w>
38              
39             Width (Required)
40              
41             =item C<-lpp>
42              
43             Lines Per Page (Required)
44              
45             =item C<-ms>
46              
47             Media Size defaults to letter. Valid values are: executive, letter, legal, ledger, a4, a3, monarch, com-10, d1, c5, b5
48              
49             =item C<-msrc>
50              
51             Media Source is not set by default. Valid values are: numbers from 0 to 69. Generally refers to paper trays or feeders. See your printer documentation for details.
52              
53             =item C<-o>
54              
55             Orientation defaults to portrait. Valid values are: landscape, portrait.
56              
57             =item C<-s>
58              
59             Sides defaults to 0. Valid values are: 0 (Single), 1 (Double Long), 2 (Double Short)
60              
61             =item C<-c>
62              
63             Copies defaults to 1.
64              
65             =back 2
66              
67             =cut
68              
69 1     1   8448 use base Exporter;
  1         3  
  1         127  
70              
71 1     1   7 use vars qw/ @EXPORT_OK $VERSION /;
  1         3  
  1         94  
72             @EXPORT_OK = qw/ PCL_pre PCL_post /;
73             $VERSION = 1.01;
74              
75             # for converting millemeters to inches
76 1     1   8 use constant MM_PER_IN => 25.4;
  1         15  
  1         90  
77              
78             # used in logical page setup to convert dot values to inches
79 1     1   5 use constant DPI_LP_CALC => 300;
  1         2  
  1         1643  
80              
81             sub PCL_pre {
82              
83 4     4 0 222 my $args;
84 4 50       12 if ($#_) {
    0          
85 4         16 $args = { @_ };
86             } elsif (ref $_[0] eq 'HASH') {
87 0         0 $args = $_[0];
88             } else {
89 0         0 die "parameters to PCL_pre must be in list or href format!"
90             }
91              
92             # acceptable key => value combinations
93 4         64 my $ok = {
94             -w => qr/^\d+$/,
95             -lpp => qr/^\d+$/,
96             -ms => [qw/ executive letter legal ledger a4 a3 monarch com-10 d1 c5 b5 /],
97             -msrc => [ 0..69 ],
98             -o => qr/^(landscape|portrait)$/i,
99             -s => [ 0, 1, 2 ],
100             -c => qr/^\d+$/,
101             };
102              
103             # make sure all parms are ok
104 4         6 for my $key (keys %{$args}) {
  4         13  
105 14 50       14 die "An invalid parameter key ($key) was passed to PCL_pre!" unless ( grep /^$key$/ => keys(%{$ok}) );
  14         231  
106 14 100       42 if (ref $ok->{$key} eq 'Regexp') {
107 11 50       73 die "An invalid paramater value ($args->{$key}) was passed to PCL_pre!" unless ( $args->{$key} =~ /$ok->{$key}/ );
108             } else {
109 3 50       3 die "An invalid paramater value ($args->{$key}) was passed to PCL_pre!" unless ( grep /^$args->{$key}$/ => @{$ok->{$key}} );
  3         42  
110             }
111             }
112              
113 4 50       13 die "No width was specified!" unless $args->{-w};
114 4 50       10 die "No lines per page was specified!" unless $args->{-lpp};
115              
116 4 100       12 $args->{-ms} = 'letter' unless (defined $args->{-ms});
117 4 100       11 $args->{-o} = 'portrait' unless (defined $args->{-o});
118 4 100       11 $args->{-s} = 0 unless (defined $args->{-s});
119 4 100       11 $args->{-c} = 1 unless (defined $args->{-c});
120              
121 4         199 my %page =
122             (
123             executive =>
124             {
125             type => 'paper',
126             note => 'Executive',
127             page_size_code => 1,
128             physical_page_width => 7.25, # inches
129             physical_page_length => 10.5, # inches
130             logical_page_width =>
131             {
132             portrait => 2025 / DPI_LP_CALC, # inches
133             landscape => 3030 / DPI_LP_CALC, # inches
134             },
135             },
136             letter =>
137             {
138             type => 'paper',
139             note => 'Letter',
140             page_size_code => 2,
141             physical_page_width => 8.5,
142             physical_page_length => 11,
143             logical_page_width =>
144             {
145             portrait => 2400 / DPI_LP_CALC,
146             landscape => 3180 / DPI_LP_CALC,
147             },
148             },
149             legal =>
150             {
151             type => 'paper',
152             note => 'Legal',
153             page_size_code => 3,
154             physical_page_width => 8.5,
155             physical_page_length => 14,
156             logical_page_width =>
157             {
158             portrait => 2400 / DPI_LP_CALC,
159             landscape => 4080 / DPI_LP_CALC,
160             },
161             },
162             ledger =>
163             {
164             type => 'paper',
165             note => 'Ledger',
166             page_size_code => 6,
167             physical_page_width => 11,
168             physical_page_length => 17,
169             logical_page_width =>
170             {
171             portrait => 3150 / DPI_LP_CALC,
172             landscape => 4980 / DPI_LP_CALC,
173             },
174             },
175             a4 =>
176             {
177             type => 'paper',
178             note => 'A4',
179             page_size_code => 26,
180             physical_page_width => 210 / MM_PER_IN,
181             physical_page_length => 297 / MM_PER_IN,
182             logical_page_width =>
183             {
184             portrait => 2338 / DPI_LP_CALC,
185             landscape => 3389 / DPI_LP_CALC,
186             },
187             },
188             a3 =>
189             {
190             type => 'paper',
191             note => 'A3',
192             page_size_code => 27,
193             physical_page_width => 297 / MM_PER_IN,
194             physical_page_length => 420 / MM_PER_IN,
195             logical_page_width =>
196             {
197             portrait => 3365 / DPI_LP_CALC,,
198             landscape => 4842 / DPI_LP_CALC,,
199             },
200             },
201             monarch =>
202             {
203             type => 'envelope',
204             note => 'Monarch',
205             page_size_code => 80,
206             physical_page_width => 3.875,
207             physical_page_length => 7.5,
208             logical_page_width =>
209             {
210             portrait => 1012 / DPI_LP_CALC,
211             landscape => 2130 / DPI_LP_CALC,
212             },
213             },
214             'com-10' =>
215             {
216             type => 'envelope',
217             note => 'Com-10',
218             page_size_code => 81,
219             physical_page_width => 4.125,
220             physical_page_length => 9.5,
221             logical_page_width =>
222             {
223             portrait => 1087 / DPI_LP_CALC,
224             landscape => 2730 / DPI_LP_CALC,
225             },
226             },
227             dl =>
228             {
229             type => 'envelope',
230             note => 'International DL',
231             page_size_code => 90,
232             physical_page_width => 110 / MM_PER_IN,
233             physical_page_length => 220 / MM_PER_IN,
234             logical_page_width =>
235             {
236             portrait => 1157 / DPI_LP_CALC,
237             landscape => 2480 / DPI_LP_CALC,
238             },
239             },
240             c5 =>
241             {
242             type => 'envelope',
243             note => 'International C5',
244             page_size_code => 91,
245             physical_page_width => 162 / MM_PER_IN,
246             physical_page_length => 229 / MM_PER_IN,
247             logical_page_width =>
248             {
249             portrait => 1771 / DPI_LP_CALC,
250             landscape => 2586 / DPI_LP_CALC,
251             },
252             },
253             b5 =>
254             {
255             type => 'envelope',
256             note => 'International B5',
257             page_size_code => 100,
258             physical_page_width => 176 / MM_PER_IN,
259             physical_page_length => 250 / MM_PER_IN,
260             logical_page_width =>
261             {
262             portrait => 1936 / DPI_LP_CALC,
263             landscape => 2834 / DPI_LP_CALC,
264             },
265             },
266             );
267              
268 4         8 my $orientation_code;
269 4 100       14 if ($args->{-o} eq 'landscape') {
    50          
270 2         3 $orientation_code = 1;
271             } elsif ($args->{-o} eq 'portrait') {
272 2         3 $orientation_code = 0;
273             } else {
274 0         0 die;
275             }
276              
277 4 50       15 (defined $page{$args->{-ms}}{page_size_code})
278             ? my $page_size_code = $page{$args->{-ms}}{page_size_code}
279             : die;
280              
281 4 100       26 my $num_left_margin_chars = ($orientation_code == 0)
282             # My trial and error constant...
283             ? ( int(.51 * $args->{-w} / $page{$args->{-ms}}{logical_page_width}{portrait}) + 1 )
284             : ( int(.25 * $args->{-w} / $page{$args->{-ms}}{logical_page_width}{landscape}) + 1 );
285              
286 4         38 my $pitch = sprintf(
287             "%3.2f",
288             (
289             ($args->{-w} + ($num_left_margin_chars * 2))
290             /
291             $page{$args->{-ms}}{logical_page_width}{$args->{-o}}
292             )
293             );
294              
295 4 100       10 my $num_right_margin_position = ($orientation_code == 0)
296             ? (($num_left_margin_chars - 1) + $args->{-w})
297             : ( $num_left_margin_chars + $args->{-w});
298              
299             # Assume .5 inch default top and bottom margins
300 4 100       11 my $l = ($orientation_code == 0)
301             ? $page{$args->{-ms}}{physical_page_length}
302             : $page{$args->{-ms}}{physical_page_width};
303              
304 4 100       9 my $num_top_margin_lines = ($orientation_code == 1)
305             ? ( int(.7 * $args->{-lpp} / $l) + 1)
306             : 0;
307              
308 4         19 my $vmi = sprintf(
309             "%2.4f",
310             ( ($l - 1)/($args->{-lpp} + int($num_top_margin_lines / 2)) * 48 )
311             );
312              
313 4 100       9 my $num_bottom_margin_position = ($orientation_code == 1)
314             ? $args->{-lpp}
315             : 0;
316              
317             return
318             # Universal Exit Language Command
319 4 50       98 "\e%-12345X" .
    50          
    50          
    100          
    100          
320              
321             # Printer Reset Command
322             "\eE" .
323              
324             # Number of Copies Command
325             "\e&l" . $args->{-c} . "X" .
326              
327             # Simplex/Duplex Print Command
328             "\e&l" . $args->{-s} . "S" .
329              
330             # Page Size Command
331             "\e&l" . $page_size_code . "A" .
332              
333             # Page Source Command
334             (
335             (defined $args->{-msrc})
336             ? "\e&l" . $args->{-msrc} . "H"
337             : ''
338             ) .
339              
340             # Logical Page Orientation Command
341             "\e&l" . $orientation_code . "O" .
342              
343             # Roman-8 symbol set
344             "\e(8U" .
345              
346             # Fixed Spacing for primary font
347             "\e(s0P" .
348              
349             # Pitch (horizontal spacing) for primary font
350             "\e(s" . $pitch . "H" .
351              
352             # Vertical Motion Index (VMI) Command
353             "\e&l" . $vmi . "C" .
354              
355             # Stroke Weight
356             "\e(s3B" .
357              
358             # Left Margin Command
359             (
360             ($num_left_margin_chars)
361             ? "\e&a" . $num_left_margin_chars . "L"
362             : ''
363             ) .
364              
365             # Right Margin Command
366             (
367             ($num_right_margin_position)
368             ? "\e&a" . $num_right_margin_position . "M"
369             : ''
370             ) .
371              
372             # Top Margin Command
373             (
374             ($num_top_margin_lines)
375             ? "\e&l" . $num_top_margin_lines . "E"
376             : ''
377             ) .
378              
379             # Text Length Command (bottom margin)
380             (
381             ($num_bottom_margin_position)
382             ? "\e&l" . $num_bottom_margin_position . "F"
383             : ''
384             );
385             }
386              
387             sub PCL_post {
388             return
389             # Printer Reset Command
390 1     1 0 44 "\eE" .
391              
392             # Universal Exit Language Command
393             "\e%-12345X";
394             }
395              
396             1;
397              
398             =head1 AUTHOR
399              
400             PCL::Simple by Phil R Lawrence.
401              
402             =head1 COPYRIGHT
403              
404             The PCL::Simple module is Copyright (c) 2002 Phil R Lawrence. All rights reserved.
405              
406             This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
407              
408             =head1 NOTE
409              
410             This module was developed while I was in the employ of Lehigh University. They kindly allowed me to have ownership of the work with the understanding that I would release it to open source. :-)
411              
412             =cut