File Coverage

blib/lib/PostScript/Columns.pm
Criterion Covered Total %
statement 112 112 100.0
branch 18 30 60.0
condition 8 16 50.0
subroutine 4 4 100.0
pod 0 1 0.0
total 142 163 87.1


line stmt bran cond sub pod time code
1            
2             =head1 NAME
3            
4             PostScript::Columns - Squeeze a text file into multiple columns.
5            
6             =head1 SYNOPSIS
7            
8             use PostScript::ColDoc;
9            
10             $psdoc= pscolumns(
11             -margins => [30,20], # NSEW or NS,EW or N,EW,S or N,E,W,S (like CSS)
12             -headfont => 'NimbusMonL-Bold',
13             -headsize => 12,
14             -head => $head,
15             -font => 'NimbusMonL-Regu',
16             -size => 10,
17             -text => $text,
18             # default font/size for foot:
19             -foot => "Page \$p of \$pp", # will interpolate later :)
20             );
21            
22             # use all defaults, no footer
23             $doc= pscolumns(
24             -size => 5,
25             -head => "Left\nLeft Also\tTest Document\tRight",
26             -text => $text,
27             -foot => scalar(localtime)."\tFoot\tPage \$p of \$pp",
28             );
29            
30            
31             =head1 DESCRIPTION
32            
33             Creates a PostScript document with a user-defined header and footer,
34             then attempts to squeeze the data into as many columns as possible.
35            
36             =head1 AVAILABLE FONTS
37            
38             Only the monospace PostScript fonts are available:
39            
40             =over 4
41            
42             =item C
43            
44             =item C
45            
46             =item C
47            
48             =item C
49            
50             =back
51            
52             =head1 OPTIONS
53            
54             =over 4
55            
56             =item -margins
57            
58             Array ref that specifies page margins, in I (1/72 of an inch).
59             North, East, West South are expressed as
60             four elements: [ N, E, S, W ], three elements [ N, E_W, S ], two elements [ N_S, E_W ],
61             or one element [ N_S_E_W ].
62             (This is the same order that CSS uses.)
63            
64             B Different printers may require drastically different margins.
65             You'll have to experiment each time you use this module with a new printer.
66            
67             =item -headfont
68            
69             Name of the font to use for the header (see L<"AVAILABLE FONTS">).
70            
71             =item -headsize
72            
73             Size of the font to use for the header (in points).
74            
75             =item -head
76            
77             String to use as header.
78             Upper-right, centered, and upper-left fields are tab-separated.
79             In the string, C<$p> will be replaced by the current page number,
80             and C<$pp> with the total number of pages.
81            
82             =item -font
83            
84             Name of the font to use for the text (see L<"AVAILABLE FONTS">).
85            
86             =item -size
87            
88             Size of the font to use for the text (in points).
89            
90             =item -text
91            
92             Columnar text.
93            
94             =item -footfont
95            
96             Name of the font to use for the footer (see L<"AVAILABLE FONTS">).
97            
98             =item -footsize
99            
100             Size of the font to use for the footer (in points).
101            
102             =item -foot
103            
104             String to use as footer.
105             Lower-right, centered, and lower-left fields are tab-separated.
106             In the string, C<$p> will be replaced by the current page number,
107             and C<$pp> with the total number of pages.
108            
109             =back
110            
111             =head1 AUTHOR
112            
113             v, Efive@rant.scriptmania.comE
114            
115             =head1 SEE ALSO
116            
117             perl(1).
118            
119             =cut
120            
121             package PostScript::Columns;
122            
123 1     1   734 use strict;
  1         2  
  1         35  
124 1     1   5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         1  
  1         71  
125 1     1   4 use vars qw(%wratio);
  1         10  
  1         2602  
126            
127             $VERSION = '1.23';
128             require Exporter;
129             @ISA = qw(Exporter);
130             @EXPORT = qw(pscolumns);
131            
132             sub pscolumns
133             { # Hey! I know what's mine! ;)
134 1     1 0 686 my %arg= @_;
135 1         915 my($now,$who)= (scalar localtime, getlogin);
136             ## initial metrics
137 1 50       4 my($margin_N,$margin_E,$margin_S,$margin_W)= @{$arg{-margins}||[]};
  1         11  
138 1 50       4 $margin_N= 30 unless defined $margin_N;
139 1 50       3 $margin_E= 20 unless defined $margin_E;
140 1 50       4 $margin_S= $margin_N unless defined $margin_S;
141 1 50       5 $margin_W= $margin_E unless defined $margin_W;
142 1 50       5 my $font= ( $wratio{$arg{-font}} ? $arg{-font} : 'NimbusMonL-Regu' );
143 1   50     4 my $font_Y= $arg{-size} || 7;
144 1         5 my $font_X= $font_Y * $wratio{$font};
145 1   50     6 my $line_Y= $arg{-linewidth} || 0.2;
146             ## head metrics
147 1         7 my @head_right= split /\t/, $arg{-head};
148 1         4 my @head_left= split /\n/, $head_right[0];
149 1         4 my @head_center= split /\n/, $head_right[1];
150 1         4 @head_right= split /\n/, $head_right[2];
151 1         8 my($head_lines)= sort {$b<=>$a}
  3         6  
152             (scalar @head_left, scalar @head_center, scalar @head_right);
153 1   50     13 my $head_font= $arg{-headfont} || 'NimbusMonL-Bold';
154 1   50     6 my $head_font_Y= $arg{-headsize} || 10;
155 1         3 my $head_font_X= $head_font_Y * $wratio{$head_font};
156 1         2 my $head_Y= $head_font_Y * $head_lines;
157             ## foot metrics
158 1         5 my @foot_right= split /\t/, $arg{-foot};
159 1         3 my @foot_left= split /\n/, $foot_right[0];
160 1         2 my @foot_center= split /\n/, $foot_right[1];
161 1         4 @foot_right= split /\n/, $foot_right[2];
162 1         4 my($foot_lines)= sort {$b<=>$a}
  3         4  
163             (scalar @foot_left, scalar @foot_center, scalar @foot_right);
164 1   50     5 my $foot_font= $arg{-footfont} || 'NimbusMonL-Regu';
165 1   50     12 my $foot_font_Y= $arg{-footsize} || 8;
166 1         2 my $foot_font_X= $foot_font_Y * $wratio{$foot_font};
167 1         1 my $foot_Y= $foot_font_Y * $foot_lines;
168             ## text metrics
169 1   50     4 local $_= $arg{-text} || ' '; s/\t/ /g;
  1         52  
170 1         475 my @text= split /\n/;
171 1         25 my($maxlen)= sort {$b<=>$a} map {length} @text;
  7387         6449  
  968         1018  
172 1         30 my $col_X= $maxlen * $font_X;
173 1         3 my $paper_Y= 792;
174 1         3 my $paper_X= 612;
175 1         2 my $right= $paper_X-$margin_E;
176 1         3 my $head_top= $paper_Y-$margin_N;
177 1         4 my $head_line_top= $head_top-$head_Y+($head_font_Y/2);
178 1         4 my $text_top= $head_top-$head_Y-($font_Y/2);
179 1         2 my $foot_top= $foot_Y+$margin_S;
180 1         2 my $foot_line_top= $foot_top+($foot_font_Y);
181 1         4 my $text_Y= $text_top-$foot_line_top-4;
182 1         2 my $text_X= $paper_X-$margin_E-$margin_W;
183 1         3 my $rows= int( $text_Y / $font_Y );
184 1   50     10 my $cols= int( $text_X / $col_X ) || 1;
185 1         1 $col_X= $text_X / $cols;
186 1         3 my $pagelines= $rows * $cols;
187 1         4 my $pp= int( ( @text / $pagelines ) +0.999 );
188 1         27 my $ps= <<".";
189             %!PS-Adobe-3.0
190             %%Title: Columnar Document
191             %%Creator: PostScript::Columns v$VERSION
192             %%CreationDate: $now
193             %%For: $who
194             %%BoundingBox: 0 0 $paper_X $paper_Y
195             %%Pages: $pp
196             %Columns: $cols @ $col_X pt
197             %%EndComments
198             .
199 1         26 my $ps_head= "/$head_font findfont $head_font_Y scalefont setfont\n";
200 1         7 for my $y (map {$head_top-$head_font_Y*$_} reverse (0..$head_lines-1))
  2         8  
201             {
202 2         5 local $_= pop @head_left;
203 2         8 s/(\(|\)|\\)/\\$1/g;
204 2 50       10 $ps_head.= "$margin_W $y moveto ($_) show\n" if $_;
205 2         4 $_= pop @head_center;
206 2         6 my $x= ( $paper_X - ($head_font_X * length) )/2;
207 2         4 s/(\(|\)|\\)/\\$1/g;
208 2 100       9 $ps_head.= "$x $y moveto ($_) show\n" if $_;
209 2         21 $_= pop @head_right;
210 2         5 $x= $paper_X - $margin_E - ($head_font_X * length);
211 2         4 s/(\(|\)|\\)/\\$1/g;
212 2 100       9 $ps_head.= "$x $y moveto ($_) show\n" if $_;
213             }
214 1         11 $ps_head.= "$margin_W $head_line_top moveto $right $head_line_top ".
215             "lineto $line_Y setlinewidth stroke\n".
216             "/$foot_font findfont $foot_font_Y scalefont setfont\n";
217 1         4 for my $y (map {$foot_top-$foot_font_Y*$_} (0..$foot_lines-1))
  1         3  
218             {
219 1         3 local $_= shift @foot_left;
220 1         3 s/(\(|\)|\\)/\\$1/g;
221 1 50       8 $ps_head.= "$margin_W $y moveto ($_) show\n" if $_;
222 1         3 $_= shift @foot_center;
223 1         3 my $x= ( $paper_X - ($foot_font_X * length) )/2;
224 1         4 s/(\(|\)|\\)/\\$1/g;
225 1 50       8 $ps_head.= "$x $y moveto ($_) show\n" if $_;
226 1         3 $_= shift @foot_right;
227 1         2 $x= $paper_X - $margin_E - ($foot_font_X * length);
228 1         3 s/(\(|\)|\\)/\\$1/g;
229 1 50       8 $ps_head.= "$x $y moveto ($_) show\n" if $_;
230             }
231 1         6 $ps_head.= "$margin_W $foot_line_top moveto $right $foot_line_top ".
232             "lineto $line_Y setlinewidth stroke\n";
233 1         3 $ps_head.= "/$font findfont $font_Y scalefont setfont\n";
234 1         11 $ps_head=~ s/\$pp\b/$pp/g;
235 1         7 my $p;
236 1         4 PAGE: while(@text)
237             {
238 4         5 $p++;
239 4         25 (my $thishead= $ps_head)=~ s/\$p\b/$p/g;
240 4         18 $ps.= "\n%%Page: (Page $p) $p\n".$thishead;
241 4         11 for my $x (map {$margin_W+$col_X*$_} (0..$cols-1))
  8         19  
242             {
243 8         49 for my $y (map {$text_top-$font_Y*$_} (0..$rows-1))
  1096         1225  
244             {
245 968 50       2039 next unless local $_= shift @text;
246 968 50       2185 last if /\x0c/; # end col at formfeed
247 968         2478 s/(\(|\)|\\)/\\$1/g;
248 968         3211 $ps.= "$x $y moveto ($_) show\n";
249 968 100       2558 last PAGE unless @text;
250             }
251             }
252 3         13 $ps.= "showpage\n";
253             }
254 1         11 $ps.= "showpage\n";
255 1         159 return $ps;
256             }
257            
258             %wratio=
259             ( # Hmmm.... not a lot of variance. Keep?
260             'NimbusMonL-Regu' => 0.6,
261             'NimbusMonL-Bold' => 0.6,
262             'NimbusMonL-ReguObli' => 0.6,
263             'NimbusMonL-BoldObli' => 0.6,
264             );
265            
266             1;