File Coverage

blib/lib/Pod/Pdf.pm
Criterion Covered Total %
statement 15 893 1.6
branch 0 348 0.0
condition 0 60 0.0
subroutine 5 48 10.4
pod 0 41 0.0
total 20 1390 1.4


line stmt bran cond sub pod time code
1             package Pod::Pdf;
2              
3             # version 1.2 26 May 2000
4             # © Alan Fry
5              
6             ################################################################################
7             # 24-May-2000 -- v1.2 File input methods extended to STDIN and options (AJF) #
8             # 23-May-2000 -- v1.2 Variable initialisations into define_variables() (AJF) #
9             # 22-May-2000 -- v1.2 Opening statements put into pod2pdf() (Axel Rose) #
10             # 18-Apr-2000 -- v1.1 File::Basename routines added and ToC revised #
11             # 09-Apr-2000 -- v1.1 Text formatting routines revised #
12             # 09-Apr-2000 -- v1.1 URI Link implemented #
13             ################################################################################
14              
15 1     1   11509 use File::Basename;
  1         3  
  1         448  
16 1     1   1434 use Getopt::Long;
  1         24933  
  1         8  
17 1     1   179 use Exporter;
  1         7  
  1         33  
18 1     1   5 use strict;
  1         2  
  1         36  
19 1     1   4 use vars qw(@ISA @EXPORT $VERSION);
  1         2  
  1         14461  
20             @ISA = qw( Exporter );
21             @EXPORT = qw( pod2pdf );
22             $VERSION = "1.2";
23              
24             my $in_file = ''; # Full path 'pod' file name
25             my $title = ''; # 'pod' leaf file-name
26             my $dir = ''; # path to '$title'
27             my $out_file = ''; # Full path 'pdf' output file name
28             my $buf = ''; # Occasional buffer string
29              
30             my %HTML; # HTML escapes
31             my @wx; # Font metrics arrays
32              
33             my $x_size = 595; # default page width (pixels)
34             my $y_size = 842; # default page height (pixels)
35             my $verbose = 0; # error message flag
36              
37             my %fontstyle; # definitions for 'link' and 'files'
38             my %fontdef; # definition of hash key names
39             my %setStyles; # definition of POD element styles
40             my %colorstyle; # definition of POD element colours
41             my @Roman; # Arabic to Roman numeral conversion
42              
43             my $f_pos = 0; # position in PDF file
44             my $obj = 0; # PDF object number
45             my @o_loc = (); # PDF object's file position
46             my $resources = ''; # Resources object number
47             my %o_rec = (); # Record of named objects
48             my @Kids = (); # Page object numbers of document
49             my @tocKids = (); # Page object numbers of ToC
50             my @coverKids = (); # Page object numbers for cover page
51             my @Fonts = (); # List of fonts used on a page
52             my $stream_start = 0; # Stream start position in file
53             my $stream_end = 0; # Stream_end position in file
54             my $stream_length = 0; # Stream length
55             my %fonts_used = (); # List of fonts actually used on a page
56             my @levels = (); # List of outline levels
57             my @ol = (); # List of outline parameters
58             my $no = 0; # Index of outline entries
59             my $i = 0; # Occasional index
60             my $h2 = 0; # Flag set after head2 level
61              
62             my $start_time = 0; # Time at start of process
63             my $finish_time = 0; # Time at end of process
64             my $more = 0; # Flag indicating more to come from pod file
65             my $in_text = 0; # Flag set while processing a text block
66             my $in_pod = 0; # Flag set when in a POD section
67             my $pod_found = 0; # Flag set if POD text found
68             my $in_verbatim = 0; # Flag set while processing a verbatim block
69             my $in_tab = 0; # Flag set after a tab
70             my $in_heading = 0; # Heading flag
71             my $was_item = 0; # Last heading was an '=item'
72             my $bl = 0; # blank line flag
73             my $zlf = 1; # zero line feed flag
74             my $for = 0; # '=for' block flag
75             my $special = 0; # '=begin' block flag
76             my $j = 0; # scratch-pad index
77             my $p = 0; # scratch-pad indeces
78             my @jt = (); # scratch-pad pointers
79             my @pt = (); # scratch-pad pointers
80             my @scratch_pad = (); # scratch pad
81             my @sc = (); # colour scratch-pad
82             my $sp = 1; # Starting page number
83             my $lp = 0; # Last page number of document section
84             my $page = 1; # Current page number (start at 1)
85             my $start_page = 1; # start page number
86             my $ypos = 0; # Current height on page (pixels)
87             my $xpos = 0; # Current line position
88             my $yrem = 0; # Height currently remaining on page
89             my $inside_margin = 72; # Inside page margin
90             my $outside_margin = 72; # Outside page margin
91             my $left_margin = 72; # Left margin
92             my $right_margin = 72; # Right margin
93             my $end = 0; # Position of end of line
94             my $top_margin = 72; # top page margin for body text
95             my $bottom_margin = 62; # bottom page margin for body text
96             my $top_bar = 50; # distance from top of page to header bar
97             my $bottom_bar = 50; # distance from bottom of page to footer bar
98             my $left_indent = 30; # Amount by which to indent everything but H1 and H2
99             my $leading = 1.2; # multiply by current fontsize to get line spacing
100             my $paragraph_space = 0.5; # multiply by line spacing to get space between paragaphs
101             my $tab_per_char = 6; # points per character multiplier for tab stops
102             my $heading_lift = 0.2; # multiply by line spacing to get extra space under heading
103             my $index_indent = 20; # Amount to indent for every new level of ToC
104             my $LF = 0; # Line feed == $leading * $fs;
105             my $uH = 0; # Heading lift == $LF * $heading_lift;
106             my $WS = 0; # White Space == $LF * $paragraph_space;
107             my $cLM = 0; # Current left margin on page
108             my $set = 0; # Tab stop number
109             my @ov = (); # Tab position array
110             my $indent = 0, # Current tab indent (in points)
111             my $lineleng = 0; # Current linelength in points
112             my $line = ''; # String
113             my $k = 0; # Line length error per space
114             my $k_max = 5; # if $k > $k_max the line is not justified
115             my $spaces = 0; # Count of spaces in line
116             my $fs = 0; # Font size
117             my @lk = (); # List of links
118             my $in_link = 0; # Processing link (flag)
119             my $link_string = ''; # Link string
120             my $wordleng = 0; # Word length (used in sub 'just')
121             my $tab_str = 0; # Flag for string containing a tab character
122             my @annot = (); # List of 'link' annotations
123              
124              
125             my $current_color = 0;
126             my $date = ''; # Footer date string
127             my $h_str = 'pod2pdf'; # Inside string for header
128             my $section = ''; # Section type: 'doc', 'cat', 'ind', etc.
129              
130             sub pod2pdf {
131 0     0 0   local @ARGV = @_;
132 0 0 0       unless ( @ARGV && $ARGV[0] ) { die "no input, no output!\n" }
  0            
133            
134 0           parse_command_line();
135              
136 0 0         unless ($ARGV[0]) {
137 0 0         $in_file = '-' unless $in_file
138             }
139             else {
140 0           $in_file = $ARGV[0]
141             }
142              
143 0           $title = basename($in_file);
144 0           $dir = dirname($in_file);
145              
146 0           $title = pdfEscape($title);
147 0           $out_file = $in_file.'.pdf';
148 0           $date = page_date();
149              
150 0           define_variables();
151              
152             #$start_time = (times)[0]; # fails on Windows perl 5.003
153 0           $start_time = time;
154              
155 0           pdfOpen($out_file);
156 0           pdfOutline(0, 'Table of Contents', undef, $y_size);
157              
158 0           $section = 'doc';
159 0           my $in_pod = 0;
160 0           my $pod_found = 0;
161 0           readFile($in_file);
162 0 0         unless ($page % 2) {
163 0           pageHeader($h_str, $title);
164 0           pageFooter();
165 0           $lp++;
166             }
167              
168 0           $section = 'toc';
169 0           buildTOC();
170              
171 0           $section = 'cov';
172 0           coverPage();
173              
174 0           outlineTree();
175 0           pdfTrailer();
176              
177             #my $finish = (times)[0];
178 0           my $finish = time;
179 0 0         printf( STDERR "PDF generation time = %4.2f sec)\n", $finish - $start_time ) if $verbose;
180 0           exit 0;
181              
182             }
183              
184             sub parse_command_line {
185 0     0 0   my( $opt_paper, $opt_help, $result);
186 0           my $usage = qq{
187             $0
188             [ --help --verbose <1|2 --paper --podfile ]
189            
190             --help
191             displays this explanation of correct usage
192            
193             --vebose <1|2>
194             regulates the volume of progress comments: argument must be 1 or 2
195            
196             --podfile
197             supplies the input file to process as an explicit parameter. The
198             input file may also be supplied from STDIN or from the command
199             line as the array element $ARGV[0].
200            
201             Further information can be found in the POD section of Pod.pm. Enter:
202             perl -e "use Pod::Pdf; pod2pdf('/Pod/Pdf.pm')"
203             to get the POD in PDF format :)
204              
205             };
206            
207             $result = GetOptions(
208             'paper:s' => \$opt_paper,
209             'podfile:s' => \$in_file,
210             'verbose=i' => \$verbose,
211 0     0     'help' => sub { print STDERR $usage; exit(0) }
  0            
212 0           );
213              
214 0 0         if ((defined $opt_paper) =~ /usletter/i) {$x_size = 612; $y_size = 792}
  0            
  0            
215 0 0 0       unless ($result or $opt_help) { print STDERR $usage; exit(0) }
  0            
  0            
216             }
217              
218             sub define_variables {
219              
220 0     0 0   %setStyles = (
221             'H1' => [ 12, 'Helvetica', 'Bold' ],
222             'H2' => [ 10, 'Helvetica', 'Bold' ],
223             'H3' => [ 10, 'Helvetica', 'Regular' ],
224             'Body' => [ 10, 'Times', 'Regular' ],
225             'Verbatim' => [ 10, 'Courier', 'Regular' ],
226             'header' => [ 10, 'Helvetica', 'Bold' ],
227             'footer' => [ 10, 'Helvetica', 'Bold' ],
228             'ToC' => [ 24, 'Helvetica', 'Regular' ],
229             'coverTitle' => [ 48, 'Times', 'Italic' ],
230             );
231            
232 0           %fontstyle = (
233             'link' => 2,
234             'file' => 3,
235             );
236            
237 0           %colorstyle = (
238             'link' => '0 0 0.8 rg',
239             'text' => '0 g',
240             'special' => '0.8 0 0 rg'
241             );
242              
243 0           %fontdef = (
244             '/F00' => 'Times-Roman',
245             '/F01' => 'Times-Bold',
246             '/F02' => 'Times-Italic',
247             '/F03' => 'Times-BoldItalic',
248             '/F10' => 'Courier',
249             '/F11' => 'Courier-Bold',
250             '/F12' => 'Courier-Oblique',
251             '/F13' => 'Courier-BoldOblique',
252             '/F20' => 'Helvetica',
253             '/F21' => 'Helvetica-Bold',
254             '/F22' => 'Helvetica-Oblique',
255             '/F23' => 'Helvetica-BoldOblique'
256             );
257            
258 0           @Roman = qw(0 i ii iii iv v vi vii viii ix x
259             xi xii xiii xiv xv xvi xvii xviii xix xx
260             xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix xxx
261             xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix xl);
262              
263 0           &ESC; # initialise escapes
264 0           afm(); # Initialise fonts
265             }
266              
267             sub readFile {
268              
269 0 0   0 0   if( !open(IN, "<$in_file") ) {
270 0           print STDERR "WARNING: Could not read file $in_file.\n";
271 0           unlink $out_file;
272 0           exit 0;
273             }
274 0           while() {
275 0 0         if (/^=include\s*(.*)/) {
276 0           $in_pod = 0;
277 0 0         if(!open(INCLUDE, "$dir:$1")) {
278 0           print STDERR "WARNING: Could not read file $in_file.\n";
279 0           unlink $out_file;
280 0           exit 0
281             }
282 0           while() {
283 0 0         parsePod() if defined $_;
284             }
285             }
286 0 0         parsePod() if defined $_;
287             }
288              
289 0           close IN;
290 0 0         if( !$pod_found ) {
291 0 0         print STDERR "SKIPPING FILE: No pod text found in $in_file\n" if $verbose;
292 0           unlink $out_file;
293 0           return 0;
294             }
295              
296 0           $more = 0;
297 0           &just("\n");
298 0           $lp = $page;
299 0           &pageFooter;
300             }
301              
302             my $m;
303             sub parsePod {
304 0     0 0   my $store = '';
305              
306 0 0         if ( /^=(back|over|head|item|pod)/ ) {
307 0           $in_pod = 1;
308 0 0         if( !$pod_found ) {
309 0           $pod_found = 1;
310 0           _initPod($in_file);
311             }
312             }
313              
314 0 0         return if !$pod_found;
315 0 0         if ( /^=(cut)/ ) {$in_pod = 0 };
  0            
316 0 0         if ( !$in_pod ) { return } # Skip non-pod text.
  0            
317 0 0         if ( /^=(pod)/ ) { return };
  0            
318 0 0         if ( /^=(begin)/ ) { $special = 1; return }
  0            
  0            
319 0 0         if ( /^=(for)/ ) { $special = 1; $for = 2; return }
  0            
  0            
  0            
320 0 0         if ( /^=end/ ) { $special = 0; return }
  0            
  0            
321 0 0         if ( /^\s*$/ ) { $more = 0 } else { $more = 1 }
  0            
  0            
322 0 0         if ( /^=over.*/ ) { &IND($_); return } # indent
  0            
  0            
323 0 0         if ( /^=back/ ) { &BAK; return } # cancel indent
  0            
  0            
324 0 0         if ( /^\s*\n/ ) { &BL; return } # blank line
  0            
  0            
325 0 0 0       if ( /(^\s+.*)$/ and !$in_text) { &VRB($1); return } # verbatim txt
  0            
  0            
326 0 0         if ( /S
  0            
327             #$_ =~ s/"(.*?)"/\252$1\272/g; # convert double quotes
328             #s/([&\$]\S*)/C<$1>/g; # convert $XYZ or &XYZ to code
329             #s/(\S*\(\))/C<$1>/g; # convert XYZ() to code
330 0           s/\\([2-3][0-7][0-7])/chr(oct($1))/ge; #convert octal to character
  0            
331 0           s/\'([^\s>\.\)])/\140$1/g; #convert single quotes
332 0           s/Z<.*?>//; #zero-width character
333 0           s/--/\217/g; #convert -- to emdash
334 0           s/B
335 0           s/I
336 0           s/C
337 0           s/F
338 0           s/L
339 0 0         if ($_ =~ /(L<[^>]*)\n/) { $store .= $` . $1 . " "; return }
  0            
  0            
340 0           $_ = $store.$_; $store = ""; #mend broken links (if any)
  0            
341             #if (/L
342 0           s/E<(.*?)>/$HTML{$1}/g; #escape HTML entities
343 0           s/>/\001/g; #cancel last encoding
344 0           s/(<.*?)\001/$1>/g; #match opening < (if any)
345 0 0         if ( /^=head1\s+(.*)$/) { &H1($1); return } #heading 1
  0            
  0            
346 0 0         if ( /^=head2\s+(.*)$/) { &H2($1); return } #heading 2
  0            
  0            
347 0 0         if ( /^=item\s+(.*)$/) { &H3($1); return } #item heading
  0            
  0            
348 0 0         if ( /(^\s+.*)$/ ) { &TAB($1); return } #tabbed text txt
  0            
  0            
349             #$in_text = 0;
350 0           chomp $_; &TXT($_); #anything else must be text
  0            
351             }
352              
353             sub _initPod {
354 0     0     my $ifname = shift;
355 0 0         print STDERR "Processing pod file $ifname\n" if $verbose;
356              
357 0           $sp = $page;
358            
359 0           $in_verbatim = 0; # verbatim block flag (set to 1 in verbatim block)
360 0           $in_text = 0; # text block flag (set to 1 in text block)
361 0           $in_tab = 0; # set after an indented line in a text-block
362 0           $bl = 0; # blank line flag
363 0           $zlf = 1; # zero line feed flag
364 0           $more = 0; # more to come (from file)
365 0           $j = $p = 0; # scratch-pad indeces
366 0           $jt[$j] = $pt[$p] = [0, 0]; # scratch-pad pointers
367 0           $sc[$p] = 'text'; # scratch-pad color
368 0           setColor();
369 0           $ypos = $y_size - $top_margin; # initialise Y position
370 0           &Init; # initialise X margin position and tab settings
371 0           $yrem = $ypos;
372              
373 0           pageHeader($h_str, $title);
374             }
375              
376             sub H1 {
377 0     0 0   my ($str) = @_;
378 0           $ypos -= $WS;
379 0 0         if( $ypos <= ( $bottom_margin + 26 ) ) {
380 0           pageFooter();
381 0           pageHeader($h_str, $title);
382 0           $zlf = 1;
383 0           $bl = 0;
384             }
385 0           setFont('H1');
386 0           $j = $p = 0; $jt[0] = $pt[0] = [@scratch_pad];
  0            
387 0           $sc[$p] = 'text';
388 0           setColor();
389 0           &Init;
390 0           $xpos = $left_margin;
391 0           pdfOutline(1, $str, $page, $ypos+$LF);
392 0           &just($str);
393 0           $in_verbatim = $in_text = $in_tab = $bl = 0;
394 0           $zlf = 1;
395 0           $in_heading = 1;
396             }
397              
398             sub H2 {
399 0     0 0   my ($str) = @_;
400 0           $ypos -= $WS;
401 0           $bl = $in_verbatim = $in_text = $in_tab = 0; $zlf = 1;
  0            
402 0 0         if ($ypos <= ( $bottom_margin + 24 )) {
403 0           pageFooter();
404 0           pageHeader($h_str, $title);
405 0           $zlf = 1;
406 0           $bl = 0;
407             }
408 0           setFont('H2');
409 0           $j = $p = 0; $jt[0] = $pt[0] = [@scratch_pad];
  0            
410 0           $sc[$p] = 'text';
411 0           setColor();
412 0           &Init;
413 0           $xpos = $left_margin;
414 0           pdfOutline(2, $str, $page, $ypos+$LF);
415 0           $in_heading = 1;
416 0           &just($str);
417             }
418              
419             sub H3 {
420 0     0 0   $ypos -= $uH;
421 0           my ($str) = @_;
422 0 0 0       if ($in_verbatim or $in_text ) { $ypos -= $WS; }
  0            
423              
424 0           $str =~ s/^\*\s*(.*)/\007$1/; # bullet
425 0 0         if ($ypos <= $bottom_margin ) {
426 0           pageFooter();
427 0           pageHeader($h_str, $title);
428 0           $zlf = 1;
429 0           $bl = 0;
430             }
431 0           setFont('H3');
432 0           $j = $p = 0; $jt[0] = $pt[0] = [@scratch_pad];
  0            
433 0           $sc[$p] = 'text';
434 0           setColor();
435 0           $xpos = $cLM;
436 0           pdfOutline(3, $str, $page, $ypos+$LF);
437 0           $in_verbatim = $in_text = $in_tab = $bl = 0;
438 0           $in_heading = 1;
439 0           $was_item = 1;
440 0           just($str);
441 0           ZLF($str);
442             }
443              
444             sub IND {
445 0     0 0   my $tab;
446 0 0         if( $_[0] =~ /^=over\s*(\d+)/ ) {
447 0           $tab = $1;
448             } else {
449 0           $tab = 4;
450             }
451 0 0         if ($set) { $cLM += $tab_per_char * $ov[$set] }
  0            
452 0           ++$set; # tab stop number (1, 2, 3, ...)
453 0           $ov[$set] = $tab; # tab indent for tab stop $set (in characters)
454 0           $indent = $tab_per_char * $ov[$set]; # current tab indent (in points)
455             }
456              
457             sub BAK {
458 0 0   0 0   if (--$set < 0) { $set = 0 }
  0            
459 0 0         if (!defined $ov[$set]) { $ov[$set] = 0 }
  0            
460 0           $cLM -= $tab_per_char * $ov[$set];
461 0 0         if ($cLM < $left_margin + $left_indent ) { $cLM = $left_margin + $left_indent }
  0            
462 0           $indent = 6 * $ov[$set];
463             }
464              
465             sub Init {
466 0     0 0   $set = 0; # tab position number
467 0           @ov = (); # tab position array
468 0           $cLM = $left_margin + $left_indent; # current left margin (in points)
469 0           $indent = 0; # current indent (in points)
470             }
471              
472             sub VRB {
473 0     0 0   my ($str) = @_;
474 0           just ("\n");
475 0 0         setFont('Verbatim') unless $in_verbatim;
476 0 0 0       if ($ypos <= ($bottom_margin + $LF) and $more) {
477 0           pageFooter();
478 0           pageHeader($h_str, $title);
479 0           $bl = 0;
480 0           prt("/F$pt[$p][0]$pt[$p][1] $fs Tf\n");
481 0           $fonts_used{"/F$pt[$p][0]$pt[$p][1]"} = ' ';
482 0           @scratch_pad = ($pt[$p][0], $pt[$p][1]);
483             }
484 0           $j = $p = 0; $jt[0] = $pt[0] = [@scratch_pad];
  0            
485 0           $sc[$p] = 'text';
486 0           setColor();
487 0           $xpos = $cLM + $indent;
488 0 0 0       if ($in_verbatim) { $ypos -= $LF }
  0 0          
489 0           elsif (!$in_verbatim and $bl) { $ypos -= $WS }
490 0           $in_verbatim = 1;
491 0           $in_text = $in_tab = $bl = 0;
492 0           $zlf = 1;
493 0           just($str);
494             }
495              
496             sub TAB {
497 0     0 0   my ($str) = @_;
498 0           &just ("\n");
499 0 0         setFont('Body') unless $in_tab;
500 0 0 0       if ($ypos <= ($bottom_margin + $LF) and $more) {
501 0           pageFooter();
502 0           pageHeader($h_str, $title);
503 0           $bl = 0;
504 0           prt("/F$pt[$p][0]$pt[$p][1] $fs Tf\n");
505 0           $fonts_used{"/F$pt[$p][0]$pt[$p][1]"} = ' ';
506 0           @scratch_pad = ($pt[$p][0], $pt[$p][1]);
507             }
508 0           $j = $p = 0; $jt[0] = $pt[0] = [@scratch_pad];
  0            
509 0           $sc[$p] = 'text';
510 0           setColor();
511 0           $xpos = $cLM + $indent;
512 0 0         if ($in_heading) { $ypos -= $uH; $in_heading = 0 }
  0            
  0            
513 0 0         if ($bl) { $ypos -= $WS }
  0            
514 0           else { $ypos -= $LF }
515 0           $bl = 0;
516 0           $zlf = 1;
517 0           $in_tab = 1;
518 0           &just($str);
519 0           &just("\n");
520             }
521              
522             sub TXT {
523 0     0 0   my ($txt) = @_;
524            
525 0 0         if ($in_verbatim) { $ypos -= $LF; $in_verbatim = 0; }
  0            
  0            
526 0 0         if ($in_tab) { $in_text = $in_tab = 0 }
  0            
527 0 0         if ($in_text) { just($txt); return }
  0            
  0            
528 0 0         if ($in_heading) { just($txt); return }
  0            
  0            
529            
530 0           $bl = $in_verbatim = 0;
531            
532 0 0 0       if ($ypos <= ( $bottom_margin + $LF ) and $more and $zlf ) {
      0        
533 0           pageFooter();
534 0           pageHeader($h_str, $title);
535 0           $bl = 0;
536             }
537 0           setFont('Body');
538 0           $j = $p = 0; $jt[0] = $pt[0] = [@scratch_pad];
  0            
539 0 0         $sc[$p] = $special ? 'special' : 'text';
540 0           setColor();
541 0           $xpos = $cLM + $indent;
542 0           $in_text = 1;
543 0           &just($txt);
544             }
545              
546             sub BL {
547 0 0   0 0   return if $bl;
548 0           just("\n");
549 0           $ypos -= $LF;
550 0 0         if ($for) { # '=for' block
551 0           $for--;
552 0 0         $for = $for < 0 ? 0 : $for;
553 0 0         $special = $for ? $special : 0;
554             }
555 0 0         if( $in_text ) {
    0          
    0          
556 0           $in_text = 0;
557 0           $in_tab = 0;
558             return
559 0           }
560             elsif( $in_verbatim ) {
561             }
562             elsif ( $in_heading ) {
563 0           $in_heading = 0;
564 0           $ypos += $LF*(1-$zlf);
565 0           $zlf = 1;
566             }
567 0           $bl = 1;
568             }
569              
570             sub ZLF {
571 0     0 0   my ($str) = @_;
572 0 0 0       if (($lineleng <= $indent - 2) and ($str =~ /\007|\d+/)) {
573 0           $zlf = 0
574             }
575 0           else { $zlf = 1 }
576             }
577              
578             sub HSP {
579 0     0 0   my $str = shift;
580 0           my $new;
581 0           $str =~ s/S
582 0           foreach (split(/S
583 0 0         if (/\001(.*)>(.*)/) {
584 0           my $a = $1;
585 0           my $b = $2;
586 0           $a =~ s/ /\240/g;
587 0           $new .= $a.$b;
588 0           next;
589             }
590 0           $new .= $_;
591             }
592 0           $new;
593             }
594            
595             sub just {
596 0     0 0   my $str = shift;
597 0           $str .= ' ';
598 0           my $used = 0;
599 0           $end = ($x_size - $right_margin);
600 0 0         if ($str =~ /\n/) {
601 0 0         &output($line, 0) if $line;
602 0 0 0       linkBB(2, 0) if ($line and @lk);
603 0           $line = "";
604 0           $k = 0;
605 0           $lineleng = 0;
606 0           $spaces = 0;
607 0           return;
608             }
609             else {
610 0           my $word;
611 0           foreach $word ( split( /([ \t])/, $str ) ) {
612 0           $tab_str= 0;
613 0           $wordleng = 0;
614 0           foreach ( split( //, $word ) ) {
615 0 0         if( / / ) { $tab_str = 0 }
  0            
616 0 0         if( /[\001-\006]/ ) { &REM($_); next; }
  0            
  0            
617 0 0         if( /\t/ ) {
618 0           $tab_str = 1;
619 0 0         &output($line, 0) if $line;
620 0 0 0       linkBB(2, 0) if ($line and @lk);
621 0           $line = "";
622 0           $k = 0;
623 0           $used = (int($lineleng/48) + 1) * 48;
624 0           $xpos += $used;
625 0           $spaces = 0;
626 0           $lineleng = 0;
627 0           next;
628             }
629 0 0         if( $in_link ) { $link_string .= $_ }
  0            
630 0           $wordleng += $wx[ $jt[$j][0] ][ $jt[$j][1] ][ord($_)]*$fs;
631             }
632 0 0 0       if ($lineleng + $wordleng <= ($end - $xpos) or $in_verbatim or $in_tab) {
      0        
633 0           $lineleng += $wordleng;
634 0           $wordleng = 0;
635 0 0         $line .= $word unless $word eq "\t";
636 0 0         $spaces++ if $word eq " ";
637             }
638             else {
639 0           $line =~ s/(.*\S)(\s*)$/$1/;
640 0           $lineleng -= 2.5 * length($2);
641 0           $spaces -= length $2;
642 0 0         if ($spaces < 1) { $spaces = 1 }
  0            
643 0           $k = ($end - $xpos - $lineleng)/$spaces;
644 0           &output($line, $k);
645 0 0         linkBB(2, $k) if @lk;
646 0           $ypos -= $LF;
647 0 0         if ($ypos <= $bottom_margin) {
648 0           pageFooter();
649 0           pageHeader($h_str, $title);
650 0           $ypos -= 12;
651 0           $used = 0;
652 0           prt("/F$pt[$p][0]$pt[$p][1] $fs Tf\n");
653 0           $fonts_used{"/F$pt[$p][0]$pt[$p][1]"} = ' ';
654 0           @scratch_pad = ($pt[$p][0], $pt[$p][1]);
655             }
656 0 0         if ( $word eq " " ) { $line = ""; $lineleng = 0 }
  0            
  0            
657 0           else { $line = $word; $lineleng = $wordleng }
  0            
658 0           $wordleng = 0;
659 0           $spaces = 0;
660 0           $used = 0;
661 0 0 0       if ($xpos != $cLM + $indent and $tab_str) {
662 0           $xpos = $cLM + $indent + 48;
663             }
664             else {
665 0 0         if ($in_heading) { $xpos = $cLM }
  0            
666 0           else { $xpos = $cLM + $indent }
667             }
668             }
669             }
670             }
671             }
672              
673              
674             sub REM {
675 0     0 0   my $rem = shift;
676 0 0         if( $rem =~ /\001/ ) {
677 0 0         if( $in_link ) { &linkBB(0, 0) }
  0            
678 0           $j--;
679 0 0         if ($j < 0) { $j = 0 }
  0            
680             }
681             else {
682 0           $jt[$j+1] = [$jt[$j][0], $jt[$j][1]]; $j++;
  0            
683 0 0         if ($rem =~ /\002/) { $jt[$j][1] = 1; }
  0            
684 0 0         if ($rem =~ /\003/) { $jt[$j][1] = 2; }
  0            
685 0 0         if ($rem =~ /\004/) { $jt[$j][0] = 1 }
  0            
686 0 0         if ($rem =~ /\005/) { $jt[$j][1] = $fontstyle{file} }
  0            
687 0 0         if ($rem =~ /\006/) { $jt[$j][1] = $fontstyle{"link"}; linkBB(1, 6) } #Link
  0            
  0            
688             }
689             }
690              
691             sub linkBB {
692 0     0 0   my $op = shift;
693 0           my $param = shift;
694 0 0         print STDERR "linkBB($op,$param)\n" if $verbose == 2;
695 0 0         if( !$op ) {
    0          
    0          
696 0           push(@lk, $link_string, $wordleng, $spaces);
697 0           $in_link = 0;
698 0           $link_string = '';
699 0 0         print STDERR "\@lk = @lk\n" if $verbose == 2;
700             }
701             elsif( $op == 1 ) {
702 0           $in_link = 1;
703 0           push(@lk, $param, ($lineleng + $xpos));
704 0 0         print STDERR "\@lk = @lk\n" if $verbose == 2;
705             }
706             elsif ($op == 2) { #return if !@lk;
707 0 0         print STDERR "Sifting \@lk = @lk\n" if $verbose == 2;
708 0           my($linktype, $ybase,$xll,$xur,$yll,$yur);
709 0           my $xbase = 0;
710 0           my $str = '';
711 0           my $len = 0;
712 0           my $sps = 0;
713 0           while (@lk) {
714 0           $linktype = shift(@lk); # either 5 or 6
715 0 0         $xbase = shift(@lk); $xbase = 0 if !defined $xbase;
  0            
716 0           $ybase = $ypos;
717 0 0         $str = shift(@lk); $str = '' if !defined $str;
  0            
718 0 0         $len = shift(@lk); $len = 0 if !defined $len;
  0            
719 0 0         $sps = shift(@lk); $sps = 0 if !defined $sps;
  0            
720 0 0         if (($xbase + $len) > $end ) {
721 0           $xbase = $cLM + $indent;
722 0 0         $xbase += 48 if $tab_str;
723 0           $sps = 0;
724 0           $ybase -= $LF;
725             }
726 0           $xll = sprintf "%0.1f", $xbase + $sps * $param - 1;
727 0           $xur = sprintf "%0.1f", $xll + $len + 2;
728 0           $yll = sprintf "%0.1f", $ybase - 0.25*$LF;
729 0           $yur = sprintf "%0.1f", $ybase + 0.63*$LF;
730 0 0         if ($str =~ /(http|ftp|mailto)\s*:/) {
731 0           push @annot, ["[$xll $yll $xur $yur]", $str];
732             }
733             }
734             }
735             }
736              
737             sub pdfEscape {
738 0     0 0   my ($line) = @_;
739 0           $line =~ s/[\000-\024]//g;
740 0           $line =~ s/[\\\(\)\{\}]/\\$&/g;
741 0           $line =~ s/[\200-\377]/sprintf("\\%03o",ord($&))/ge;
  0            
742 0           $line;
743             }
744              
745             sub output {
746 0     0 0   my ($line, $k) = @_;
747 0           $k = sprintf("%0.4f", $k);
748 0 0         $k = 0 if $k >= $k_max;
749 0           $line =~ s/[\020-\024]//g;
750 0           $line =~ s/[\\\(\)\{\}]/\\$&/g;
751 0           $line =~ s/[\200-\377]/sprintf("\\%03o",ord($&))/ge;
  0            
752 0 0         prt(sprintf "1 0 0 1 %0.1f %0.1f Tm\n", $xpos, $ypos) if $line;
753 0           foreach ( split(/([\001-\007])/,$line) ) {
754 0 0         if( /[\001-\007]/ ) {
755 0 0         if( /\007/ ) { BUL()
  0            
756             }
757 0 0         if( /\001/ ) { $p--; $p = 0 if( $p < 0 ) }
  0 0          
  0            
758             else {
759 0           $sc[$p+1] = $sc[$p];
760 0           $pt[$p+1] = [$pt[$p][0], $pt[$p][1]]; $p++;
  0            
761 0 0         if ( /\002/ ) { $pt[$p][1] = 1 } # Bold
  0 0          
    0          
    0          
    0          
762 0           elsif( /\003/ ) { $pt[$p][1] = 2 } # Italic
763 0           elsif( /\004/ ) { $pt[$p][0] = 1 } # Courier
764 0           elsif( /\005/ ) { $pt[$p][1] = $fontstyle{file} }
765             elsif( /\006/ ) {
766 0           $pt[$p][1] = $fontstyle{"link"};
767 0           $sc[$p] = 'link';
768             }
769             }
770 0           $fonts_used{"/F$pt[$p][0]$pt[$p][1]"} = ' ';
771 0           prt("/F$pt[$p][0]$pt[$p][1] $fs Tf\n");
772 0           setColor();
773 0           next;
774             }
775 0           prt("$k Tw\n");
776 0           prt("\($_\) Tj\n");
777             }
778             }
779              
780             sub BUL {
781 0     0 0   my $x = $xpos + 8;
782 0           my $y = $ypos + 1;
783 0           prt("
784             ET
785             q
786             $xpos $y 4 4 re
787             f
788             Q
789             BT
790             1 0 0 1 $x $ypos Tm
791             ");
792             }
793            
794             sub setFont {
795 0     0 0   my($set) = shift;
796 0           my ($font, $style) = ();
797            
798 0           $fs = $setStyles{$set}[0];
799            
800 0 0         if ($setStyles{$set}[1] eq 'Times' ) { $font = 0 }
  0 0          
    0          
801 0           elsif ($setStyles{$set}[1] eq 'Courier' ) { $font = 1 }
802 0           elsif ($setStyles{$set}[1] eq 'Helvetica' ) { $font = 2 }
803            
804 0           else { print STDERR "$setStyles{$set}[1] ($set,$fs) is an unrecognised font\n"; exit }
  0            
805            
806 0 0         if ($setStyles{$set}[2] eq 'Regular' ) { $style = 0 }
  0 0          
    0          
    0          
    0          
    0          
807 0           elsif ($setStyles{$set}[2] eq 'Bold' ) { $style = 1 }
808 0           elsif ($setStyles{$set}[2] eq 'Oblique' ) { $style = 2 }
809 0           elsif ($setStyles{$set}[2] eq 'BoldOblique' ) { $style = 3 }
810 0           elsif ($setStyles{$set}[2] eq 'Italic' ) { $style = 3 }
811 0           elsif ($setStyles{$set}[2] eq 'ItalicOblique') { $style = 3 }
812            
813 0           else { print STDERR "setStyles{$set}[2] ($set,$fs) is an unrecognised style\n"; exit }
  0            
814            
815 0           $fonts_used{"/F$font$style"} = ' ';
816 0           prt("/F$font$style $fs Tf\n");
817 0           @scratch_pad = ($font, $style);
818 0           $LF = $leading * $fs;
819 0           $uH = $LF * $heading_lift;
820 0           $WS = $LF * $paragraph_space;
821             }
822              
823             sub setColor {
824 0 0   0 0   if( $sc[$p] ne $current_color ) {
825 0 0         defined($colorstyle{$sc[$p]}) or die "INTERNAL ERROR \#05 - Unknown colorstyle\n";
826 0           prt("$colorstyle{$sc[$p]}\n");
827 0           $current_color = $sc[$p];
828             }
829             }
830              
831             sub stringLength {
832 0     0 0   my ($str, $font, $style) = @_;
833 0           my $length = 0;
834 0           foreach (split(//, $str)) {
835 0           $length += $wx[$font][$style][ord($_)]*$fs
836             }
837 0           $length;
838             }
839              
840             my ($even);
841             sub pageFooter {
842 0     0 0   my $date_footer = '';
843 0           my $y0 = $bottom_bar;
844 0           my $y1 = $y0 - 13;
845 0           my $x0 = $left_margin;
846 0           my $x1 = $x_size - $right_margin;
847 0           my $x2 = 0.5 * ($x0 + $x1);
848 0           my $p_num;
849              
850 0 0         if ($section eq 'doc') { $p_num = $page }
  0 0          
    0          
851 0           elsif ($section eq 'toc') { $p_num = $Roman[$page - $lp]; }
852 0           elsif ($section eq 'cov') { $p_num = 'Fly leaf' }
853 0           setFont('footer');
854              
855 0 0         if($page % 2) {
856 0           my $buf = stringLength($p_num, @scratch_pad);
857 0           $buf = $x1 - $buf;
858 0           prt("
859             1 0 0 1 $x0 $y1 Tm
860             \($date\) Tj
861             1 0 0 1 $buf $y1 Tm
862             \($p_num\) Tj
863             ");
864             }
865             else {
866 0           my $buf = stringLength($date, @scratch_pad);
867 0           $buf = $x1 - $buf;
868 0           prt("
869             1 0 0 1 $x0 $y1 Tm
870             \($p_num\) Tj
871             1 0 0 1 $buf $y1 Tm
872             \($date\) Tj
873             ");
874             }
875              
876 0           prt("
877             ET
878             $x0 $y0 m
879             $x1 $y0 l
880             S
881             ");
882 0           $stream_end = $f_pos;
883 0           $stream_length = $stream_end - $stream_start;
884 0           prt("
885             endstream
886             endobj
887             ");
888            
889 0           my $contents_object = $obj;
890              
891 0           $o_loc[++$obj] = $f_pos;
892 0           prt("
893             $obj 0 obj
894             $stream_length
895             endobj
896             ");
897            
898 0           $o_loc[++$obj] = $f_pos;
899 0           my $resources_object = $obj;
900 0           $buf = '';
901 0           foreach (sort keys %fonts_used) { $buf .= "$_ $o_rec{$_} 0 R\n" }
  0            
902 0           prt("
903             $obj 0 obj
904             <<
905             /ProcSet [/PDF /Text]
906             /ColorSpace <>
907             /Font
908             <<
909             $buf
910             >>
911             >>
912             endobj
913             ");
914            
915 0           my @annot_objects = ();
916 0           for (0..$#annot) {
917 0           my $next = 0;
918 0           $o_loc[++$obj] = $f_pos;
919 0           push(@annot_objects, $obj);
920 0           $next = $obj+1;
921 0           prt("
922             $obj 0 obj
923             <<
924             /Type /Annot
925             /Subtype /Link
926             /Rect $annot[$_][0]
927             /Border [0 0 1]
928             /C [1 1 0]
929             /A $next 0 R
930             /H /I
931             >>
932             endobj
933             ");
934 0           $o_loc[++$obj] = $f_pos;
935 0           prt("
936             $obj 0 obj
937             <<
938             /S /URI
939             /URI ($annot[$_][1])
940             >>
941             endobj
942             ");
943             }
944            
945 0 0         if (@annot) {
946 0           $buf = join(' 0 R ', @annot_objects, '');
947 0           $o_loc[++$obj] = $f_pos;
948 0           my $annots_object = $obj;
949 0           prt("
950             $obj 0 obj
951             [ $buf ]
952             endobj
953             ");
954 0           $o_loc[++$obj] = $f_pos;
955 0           $o_rec{$page} = $obj;
956 0           prt("
957             $obj 0 obj
958             <<
959             /Type /Page
960             /Parent $o_rec{parent} 0 R
961             /Resources $resources_object 0 R
962             /Contents $contents_object 0 R
963             /Annots $annots_object 0 R
964             >>
965             endobj
966             ");
967             }
968             else {
969 0           $o_loc[++$obj] = $f_pos;
970 0           $o_rec{$page} = $obj;
971 0           prt("
972             $obj 0 obj
973             <<
974             /Type /Page
975             /Parent $o_rec{parent} 0 R
976             /Resources $resources_object 0 R
977             /Contents $contents_object 0 R
978             >>
979             endobj
980             ");
981             }
982            
983 0 0         if ($section eq 'doc') { push @Kids, "$o_rec{$page} 0 R" }
  0 0          
    0          
984 0           elsif ($section eq 'toc') { push @tocKids, "$o_rec{$page} 0 R" }
985 0           elsif ($section eq 'cov') { push @coverKids, "$o_rec{$page} 0 R" }
986              
987 0           ++$page;
988             }
989              
990             sub pageHeader {
991 0     0 0   my ($in_str, $out_str, $type) = @_;
992 0           @annot = ();
993 0           my ($l_str, $r_str);
994 0 0         if ($page % 2) {
995 0           $l_str = $in_str;
996 0           $r_str = $out_str;
997             }
998             else {
999 0           $l_str = $out_str;
1000 0           $r_str = $in_str;
1001             }
1002            
1003 0           my $y0 = $y_size - $top_bar;
1004 0           my $y1 = $y0 + 5;
1005 0           my $x0 = $left_margin;
1006 0           my $x1 = $x_size - $right_margin;
1007 0           my $x2 = 0.5 * ($x0 + $x1);
1008              
1009 0           undef %fonts_used;
1010 0           $o_loc[++$obj] = $f_pos;
1011 0           my $length_obj = $obj + 1;
1012            
1013 0           prt("
1014             $obj 0 obj
1015             <<
1016             /Length $length_obj 0 R
1017             >>
1018             stream
1019             ");
1020            
1021 0           $stream_start = $f_pos;
1022            
1023 0 0         if (defined $in_str) {
1024 0           prt("
1025             $x0 $y0 m
1026             $x1 $y0 l
1027             ")
1028             }
1029            
1030 0           prt("
1031             S
1032             BT
1033             0 G
1034             1 i 0 J 0 j 0.1 w 10 M []0 d
1035             ");
1036              
1037 0           setFont('header');
1038 0 0 0       if (defined $r_str and defined $l_str) {
1039 0           my $buf = stringLength($r_str, @scratch_pad);
1040 0           $buf = $x1 - $buf;
1041 0           prt("
1042             1 0 0 1 $x0 $y1 Tm
1043             \($l_str\) Tj
1044             1 0 0 1 $buf $y1 Tm
1045             \($r_str\) Tj
1046             ");
1047             }
1048 0           $yrem = $ypos = $y_size - $top_margin;
1049 0 0         if ($in_text) { $ypos += $LF };
  0            
1050             }
1051              
1052             sub prt {
1053 0     0 0   my ($str) = @_;
1054 0           $str =~ s/\n\s*/\n/g;
1055 0           $str =~ s/^\n//;
1056 0           $f_pos += length $str;
1057 0           print OUT $str;
1058             }
1059              
1060             sub pdf_date {
1061 0     0 0   my @date = localtime(time);
1062 0           my $year = $date[5] + 1900;
1063 0           my $month = sprintf "%.2d", $date[4]+1;
1064 0           my $day = sprintf "%.2d", $date[3];
1065 0           my $hour = sprintf "%.2d", $date[2];
1066 0           my $min = sprintf "%.2d", $date[1];
1067 0           my $sec = sprintf "%.2d", $date[0];
1068            
1069 0           my $gm = (gmtime(time))[2];
1070 0           my $local = (localtime(time))[2];
1071 0           my $diff = $local - $gm;
1072 0 0         if ($diff <= -12) { $diff += 24 }
  0 0          
1073 0           elsif ($diff > 12) { $diff -= 24 }
1074 0           my $zone = $diff;
1075 0 0         if ($zone =~ /-/) {$zone = sprintf "%.2d00", $zone}
  0            
  0            
1076             else {$zone = sprintf "+%.2d00", $zone}
1077              
1078 0           return "D:$year$month$day$hour$min$sec$zone"
1079             }
1080              
1081             sub page_date {
1082 0     0 0   my @date = localtime(time);
1083 0           my $year = $date[5] + 1900;
1084 0           my $mon = sprintf "%.2d", $date[4];
1085 0           my $day = sprintf "%.2d", $date[3];
1086 0           my @month = qw(January February March April May June July August September October November December);
1087              
1088 0           return "$day $month[$mon] $year";
1089             }
1090              
1091             sub pdfOpen {
1092              
1093 0     0 0   my ($of) = @_;
1094              
1095 0 0         open(OUT, ">$of") or die "Could not open output file '$of': $!\n";
1096 0 0         MacPerl::SetFileInfo("CARO", "PDF ", $of) if ($^O eq "MacOS");
1097              
1098 0 0         print STDERR "Opening output file $of\n" if $verbose;
1099            
1100 0           prt("%PDF-1.2\n");
1101 0           prt("%âãÏÓ\n");
1102              
1103 0           $o_loc[++$obj] = $f_pos;
1104 0           $o_rec{calRGB} = $obj;
1105 0           prt("
1106             $obj 0 obj
1107             [/CalRGB
1108             <<
1109             /WhitePoint [0.9505 1 1.089]
1110             /Gamma [1.8 1.8 1.8]
1111             /Matrix [0.4497 0.2446 0.02518 0.3613 0.672 0.1412 0.1845 0.08334 0.9227]
1112             >>
1113             ]
1114             endobj
1115             ");
1116              
1117 0           $o_loc[++$obj] = $f_pos;
1118 0           $o_rec{info} = $obj;
1119 0           prt("
1120             $obj 0 obj
1121             <<
1122             /CreationDate (".pdf_date().")
1123             /Producer (pod2pdf)
1124             /Title ($title)
1125             >>
1126             endobj
1127             ");
1128              
1129 0           $o_rec{root} = ++$obj;
1130 0           $o_rec{parent} = ++$obj;
1131              
1132 0           $o_loc[++$obj] = $f_pos;
1133 0           $o_rec{encoding} = $obj;
1134 0           prt("
1135             $obj 0 obj
1136             <<
1137             /Type /Encoding
1138             /Differences [ 0 /.notdef /.notdef /.notdef /.notdef
1139             /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
1140             /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
1141             /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
1142             /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
1143             /.notdef /.notdef /.notdef /.notdef /space /exclam
1144             /quotedbl /numbersign /dollar /percent /ampersand
1145             /quoteright /parenleft /parenright /asterisk /plus /comma
1146             /hyphen /period /slash /zero /one /two /three /four /five
1147             /six /seven /eight /nine /colon /semicolon /less /equal
1148             /greater /question /at /A /B /C /D /E /F /G /H /I /J /K /L
1149             /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft
1150             /backslash /bracketright /asciicircum /underscore
1151             /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p
1152             /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright
1153             /asciitilde /.notdef /.notdef /.notdef /.notdef /.notdef
1154             /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
1155             /.notdef /.notdef /.notdef /.notdef /.notdef /emdash
1156             /dotlessi /grave /acute /circumflex /tilde /macron /breve
1157             /dotaccent /dieresis /.notdef /ring /cedilla /.notdef
1158             /hungarumlaut /ogonek /caron /space /exclamdown /cent
1159             /sterling /currency /yen /brokenbar /section /dieresis
1160             /copyright /ordfeminine /guillemotleft /logicalnot /hyphen
1161             /registered /macron /degree /plusminus /twosuperior
1162             /threesuperior /acute /mu /paragraph /periodcentered
1163             /cedilla /onesuperior /ordmasculine /guillemotright
1164             /onequarter /onehalf /threequarters /questiondown /Agrave
1165             /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE
1166             /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave
1167             /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve
1168             /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash
1169             /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn
1170             /germandbls /agrave /aacute /acircumflex /atilde /adieresis
1171             /aring /ae /ccedilla /egrave /eacute /ecircumflex
1172             /edieresis /igrave /iacute /icircumflex /idieresis /eth
1173             /ntilde /ograve /oacute /ocircumflex /otilde /odieresis
1174             /divide /oslash /ugrave /uacute /ucircumflex /udieresis
1175             /yacute /thorn /ydieresis ]
1176             >>
1177             endobj
1178             ");
1179              
1180 0           foreach my $font (sort keys %fontdef) {
1181 0           $o_loc[++$obj] = $f_pos;
1182 0           $o_rec{$font} = $obj;
1183 0           prt("
1184             $obj 0 obj
1185             <<
1186             /Type /Font
1187             /Subtype /Type1
1188             /Name $font
1189             /Encoding $o_rec{encoding} 0 R
1190             /BaseFont /$fontdef{$font}
1191             >>
1192             endobj
1193             ");
1194             }
1195             }
1196              
1197             sub pdfTrailer {
1198 0     0 0   $o_loc[$o_rec{root}] = $f_pos;
1199 0           prt("
1200             $o_rec{root} 0 obj
1201             <<
1202             /Type /Catalog
1203             /Pages $o_rec{parent} 0 R
1204             /PageMode /UseOutlines
1205             /Outlines $o_rec{outlines} 0 R
1206             >>
1207             endobj
1208             ");
1209 0           my $kids = join(' ', @coverKids).' '.join(' ', @tocKids).' '.join(' ', @Kids);
1210 0           my $count = (scalar @coverKids) + (scalar @tocKids) + (scalar @Kids);
1211 0           $o_loc[$o_rec{parent}] = $f_pos;
1212 0           prt("
1213             $o_rec{parent} 0 obj
1214             <<
1215             /Type /Pages
1216             /Kids [ $kids ]
1217             /Count $count
1218             /MediaBox [0 0 $x_size $y_size]
1219             >>
1220             endobj
1221             ");
1222            
1223 0           my $xfer = $f_pos;
1224 0           prt("xref\n");
1225            
1226 0           my $size = $obj+1;
1227            
1228 0           $buf = sprintf "0 %d\n", $size;
1229 0           prt($buf);
1230 0           prt("0000000000 65535 f \n");
1231 0           my $i;
1232 0           for ($i = 1; $i <= $obj; $i++) {
1233 0           $buf = sprintf "%.10d 00000 n \n", $o_loc[$i];
1234 0           prt($buf)
1235             }
1236            
1237 0           $buf = sprintf "/Size %d\n", $size;
1238            
1239 0           prt("
1240             trailer
1241             <<
1242             $buf
1243             /Root $o_rec{root} 0 R
1244             /Info $o_rec{info} 0 R
1245             >>
1246             startxref
1247             $xfer
1248             %%EOF
1249             ");
1250             }
1251              
1252             sub buildTOC {
1253 0     0 0   $ol[1]{page} = $page;
1254            
1255 0           pageHeader();
1256              
1257 0           setFont('ToC');
1258 0           $ypos = $y_size - 72;
1259 0           $xpos = ($x_size - stringLength('Table of Contents', @scratch_pad))/2;
1260 0           prt("
1261             1 0 0 1 $xpos $ypos Tm
1262             \(Table of Contents\) Tj
1263             ");
1264 0           $ypos -= $LF;
1265 0           $xpos = ($x_size - stringLength("$title", @scratch_pad))/2;
1266 0           prt("
1267             1 0 0 1 $xpos $ypos Tm
1268             \($title\) Tj
1269             ");
1270              
1271 0           $ypos -= 2*$LF;
1272            
1273 0           setFont('H3');
1274 0           for (1..$#ol) {
1275 0 0         next if !$ol[$_]{level};
1276 0 0         if ($ypos <= 70) {
1277 0           pageFooter();
1278 0           pageHeader("Table of Contents", $title);
1279 0           $ypos = $y_size - 72;
1280 0           setFont('H3');
1281             }
1282 0           $xpos = $left_margin + ($left_indent * ($ol[$_]{level}));
1283 0           $buf = trimString($xpos, $ol[$_]{string}, @scratch_pad);
1284 0           color_stripe($_);
1285 0           prt("
1286             1 0 0 1 $xpos $ypos Tm
1287             \($buf\) Tj
1288             ");
1289 0           $xpos = $x_size - $right_margin - $left_indent - stringLength($ol[$_]{page}, @scratch_pad);
1290 0           prt("
1291             1 0 0 1 $xpos $ypos Tm
1292             \($ol[$_]{page}\) Tj
1293             ");
1294 0           $ypos -= $LF;
1295             }
1296 0           pageFooter();
1297 0 0         unless ($page % 2) {
1298 0           pageHeader("Table of Contents", $title);
1299 0           pageFooter()
1300             }
1301             }
1302              
1303             sub trimString {
1304 0     0 0   my ($strt, $str, $font, $style) = @_;
1305 0           my $length = 0;
1306 0           my $ret = '';
1307 0           foreach (split(//, $str)) {
1308 0           $length += $wx[$font][$style][ord($_)]*$fs;
1309 0           $ret .= $_;
1310 0 0         if ($length + $strt > 450) {
1311 0 0         if ($ret =~ /(.*)\s+.*/) {
1312 0           $ret = $1.'...';
1313 0           last;
1314             }
1315             }
1316             }
1317 0           $ret;
1318             }
1319              
1320             sub color_stripe {
1321 0     0 0   my $col;
1322 0           my $xll = $left_margin;
1323 0           my $yll = $ypos - 3;
1324 0           my $stripe = $x_size - $left_margin - $right_margin;
1325 0 0         if ($_[0] % 2) { $col = 1}
  0            
1326 0           else { $col = 0.95}
1327 0           prt("
1328             ET
1329             q
1330             $col g
1331             $xll $yll $stripe $LF re
1332             f
1333             Q
1334             BT
1335             ");
1336             }
1337              
1338             sub pdfOutline {
1339 0     0 0   my($level, $str, $page, $ypos) = @_;
1340 0           $str = pdfEscape($str);
1341 0 0         return unless length $str;
1342              
1343 0 0 0       if ($level == 1) { $h2 = 0 }
  0 0          
    0          
1344 0           elsif ($level == 2) { $h2 = 1 }
1345 0           elsif ($level == 3 and !$h2) { $level = 2 }
1346            
1347 0           $ol[++$no] = { level => $level,
1348             string => $str,
1349             page => $page,
1350             ypos => $ypos };
1351             }
1352              
1353             sub outlineTree {
1354 0     0 0   my $z;
1355 0           $o_rec{outlines} = ++$obj;
1356 0           $ol[0]{level} = -1;
1357 0           for (1..$no) {
1358 0           my @kids; undef @kids;
  0            
1359 0           my @gkids; undef @gkids;
  0            
1360 0           my $first = undef;
1361 0           my $last = undef;
1362 0           my $previous = undef;
1363 0           my $next = undef;
1364 0           my $count = undef;
1365            
1366 0           $i = $_;
1367 0           until ($ol[$i]{level} < $ol[$_]{level}) { $i-- }
  0            
1368 0           my $parent = $i;
1369            
1370 0           $i = $_ - 1;
1371 0           until ($ol[$i]{level} <= $ol[$_]{level}) { $i-- };
  0            
1372 0 0         if ($ol[$i]{level} == $ol[$_]{level}) { $previous = $i} else {$previous = undef }
  0            
  0            
1373            
1374 0           $i = $_ + 1;
1375 0 0         if ($i <= $no) {
1376 0   0       until (!defined $ol[$i]{level} or $ol[$i]{level} <= $ol[$_]{level}) { $i++ };
  0            
1377 0 0 0       if (defined $ol[$i]{level} and $ol[$i]{level} == $ol[$_]{level}) { $next = $i} else {$next = undef }
  0            
  0            
1378             }
1379            
1380 0           $i = $_ + 1;
1381 0 0         if ($i <= $no) {
1382 0   0       until (!defined $ol[$i]{level} or $ol[$i]{level} <= $ol[$_]{level}) {
1383 0 0         if ($ol[$i]{level} == $ol[$_]{level} + 1) { push(@kids, "$i") }
  0            
1384 0 0         if ($ol[$i]{level} >= $ol[$_]{level} + 2) { push(@gkids, "$i") }
  0            
1385 0           $i++;
1386             }
1387 0           $count = (scalar @kids) + (scalar @gkids);
1388             }
1389            
1390 0           $z = $obj + $_;
1391 0 0         $parent += $obj if defined $parent;
1392 0 0         $previous += $obj if defined $previous;
1393 0 0         $next += $obj if defined $next;
1394 0 0         $first = $kids[0] + $obj if defined $kids[0];
1395 0 0         $last = $kids[-1] + $obj if defined $kids[-1];
1396 0           $o_loc[$z] = $f_pos;
1397 0 0         my $view = $ol[$_]{level} == 0 ? "/Fit" : "/FitH $ol[$_]{ypos}";
1398 0           prt("
1399             $z 0 obj
1400             <<
1401             /Parent $parent 0 R
1402             /Dest [$o_rec{$ol[$_]{page}} 0 R $view]
1403             ");
1404 0 0         prt("/Previous $previous 0 R\n") if defined $previous;
1405 0 0         prt("/Next $next 0 R\n") if defined $next;
1406 0 0         prt("/First $first 0 R\n") if defined $first;
1407 0 0         prt("/Last $last 0 R\n") if defined $last;
1408 0 0         prt("/Count $count \n") if $count;
1409 0           prt("/Title \($ol[$_]{string}\)\n");
1410 0           prt("
1411             >>
1412             endobj
1413             ");
1414             }
1415 0           $o_loc[$o_rec{outlines}] = $f_pos;
1416 0           prt("
1417             $o_rec{outlines} 0 obj
1418             <<
1419             /Type /Outlines
1420             ");
1421 0           $z = $#ol - 1;
1422 0           prt("/Count $z\n");
1423 0           $z = $obj + 1;
1424 0           prt("/First $z 0 R\n");
1425 0           $z = $obj + $#ol - 1;
1426 0           prt("
1427             /Last $z 0 R
1428             >>
1429             endobj
1430             ");
1431 0           $obj += $no;
1432             }
1433              
1434             sub coverPage {
1435 0     0 0   my $x;
1436             my $y;
1437 0           my $w;
1438 0           my $h;
1439 0           undef %fonts_used;
1440            
1441 0           $o_loc[++$obj] = $f_pos;
1442 0           push @coverKids, "$obj 0 R";
1443 0           $o_rec{$page} = $obj;
1444              
1445 0           my $contents_object = $obj + 1;
1446 0           my $length_obj = $obj + 2;
1447 0           my $resources_object = $obj+3;
1448              
1449 0           prt("
1450             $obj 0 obj
1451             <<
1452             /Type /Page
1453             /Parent $o_rec{parent} 0 R
1454             /Resources $resources_object 0 R
1455             /Contents $contents_object 0 R
1456             >>
1457             endobj
1458             ");
1459            
1460 0           $o_loc[++$obj] = $f_pos;
1461            
1462 0           prt("
1463             $obj 0 obj
1464             <<
1465             /Length $length_obj 0 R
1466             >>
1467             stream
1468             ");
1469            
1470 0           $stream_start = $f_pos;
1471              
1472 0           $x = 180;
1473 0           $y = $y_size - 216;
1474 0           my $ty = $y + 80;
1475            
1476 0           my $xll = 210;
1477 0           my $xlr = $x_size - $right_margin;
1478            
1479 0           $h = 130;
1480 0           $w = 8;
1481            
1482 0           prt("
1483             q
1484             1 0 0 rg
1485             $x $y $w $h re
1486             F
1487             Q
1488             0 G
1489             1 i 0 J 0 j 0.1 w 10 M []0 d
1490             $xll $y m
1491             $xlr $y l
1492             s
1493             BT
1494             ");
1495            
1496 0           $fonts_used{'/F21'} = ' ';
1497 0           $fonts_used{'/F22'} = ' ';
1498            
1499 0           prt("
1500             /F21 30 Tf
1501             1 0 0 1 210 $ty Tm
1502             0 -30 TD
1503             (POD Translation) Tj
1504             T* (by ) Tj
1505             0 0 0.8 rg
1506             /F22 30 Tf
1507             (pod2pdf) Tj
1508             /F21 9 Tf
1509             T* (ajf\@afco.demon.co.uk) Tj
1510             ");
1511            
1512 0           setFont('coverTitle');
1513 0           my $xm = ($x_size - stringLength($title, @scratch_pad))/2;
1514 0           my $ym = $y_size/2 - 50;
1515            
1516 0           prt("
1517             0 g
1518             1 0 0 1 $xm $ym Tm
1519             ($title) Tj
1520             ET
1521             ");
1522            
1523 0           $stream_end = $f_pos;
1524 0           $stream_length = $stream_end - $stream_start;
1525            
1526            
1527 0           prt("
1528             endstream
1529             endobj
1530             ");
1531            
1532 0           $o_loc[++$obj] = $f_pos;
1533            
1534 0           prt("
1535             $obj 0 obj
1536             $stream_length
1537             endobj
1538             ");
1539            
1540 0           $o_loc[++$obj] = $f_pos;
1541 0           $buf = '';
1542 0           foreach (sort keys %fonts_used) { $buf .= "$_ $o_rec{$_} 0 R\n" }
  0            
1543            
1544 0           prt("
1545             $obj 0 obj
1546             <<
1547             /ProcSet [/PDF /Text]
1548             /ColorSpace <>
1549             /Font
1550             <<
1551             $buf
1552             >>
1553             >>
1554             endobj
1555             ");
1556            
1557 0           pageHeader("Title Page", $title);
1558 0           pageFooter();
1559              
1560 0           ++$page;
1561             }
1562              
1563            
1564             sub ESC {
1565 0     0 0   %HTML = (
1566             'lt' => '<', 'gt' => '>', 'amp' => '&',
1567             'quot' => '"', 'nbsp' => "\240", 'Aacute' => "\301",
1568             'Acirc' => "\302", 'Agrave' => "\300", 'Aring' => "\305",
1569             'Atilde' => "\303", 'Auml' => "\304", 'Ccedil' => "\307",
1570             'ETH' => "\320", 'Eacute' => "\311", 'Ecirc' => "\312",
1571             'Egrave' => "\310", 'Euml' => "\313", 'Iacute' => "\315",
1572             'Icirc' => "\316", 'Igrave' => "\314", 'Iuml' => "\317",
1573             'Ntilde' => "\321", 'AElig' => "\306", 'Oacute' => "\323",
1574             'Ocirc' => "\324", 'Ograve' => "\322", 'Oslash' => "\330",
1575             'Otilde' => "\325", 'Ouml' => "\326", 'THORN' => "\336",
1576             'Uacute' => "\332", 'Ucirc' => "\333", 'Ugrave' => "\331",
1577             'Uuml' => "\334", 'Yacute' => "\335", 'aelig' => "\346",
1578             'aacute' => "\341", 'acirc' => "\342", 'agrave' => "\340",
1579             'aring' => "\345", 'atilde' => "\343", 'auml' => "\344",
1580             'ccedil' => "\347", 'eacute' => "\351", 'ecirc' => "\352",
1581             'egrave' => "\350", 'emdash' => "\217", 'eth' => "\360",
1582             'euml' => "\353", 'iacute' => "\355", 'icirc' => "\356",
1583             'igrave' => "\354", 'iuml' => "\357", 'ntilde' => "\361",
1584             'oacute' => "\363", 'ocirc' => "\364", 'ograve' => "\362",
1585             'oslash' => "\370", 'otilde' => "\365", 'ouml' => "\366",
1586             'thorn' => "\376", 'uacute' => "\372", 'ucirc' => "\373",
1587             'ugrave' => "\371", 'uuml' => "\374", 'yacute' => "\375",
1588             'yuml' => "\377", 'reg' => "\256", 'copy' => "\251",
1589             'szlig' => 'sz', '39' => "\047", '96' => "\140");
1590             }
1591              
1592              
1593             #############################################################################
1594             # Font Metrics (font widths) - Data from Adobe Font Metrics Files
1595             #############################################################################
1596              
1597             sub afm {
1598 0     0 0   $wx[0][0] =
1599             [ #Times-Roman ISOLatin1
1600             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1601             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1602             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1603             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1604             0.250, 0.333, 0.408, 0.500, 0.500, 0.833, 0.778, 0.333,
1605             0.333, 0.333, 0.500, 0.564, 0.250, 0.333, 0.250, 0.278,
1606             0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500,
1607             0.500, 0.500, 0.278, 0.278, 0.564, 0.564, 0.564, 0.444,
1608             0.921, 0.722, 0.667, 0.667, 0.722, 0.611, 0.556, 0.722,
1609             0.722, 0.333, 0.389, 0.722, 0.611, 0.889, 0.722, 0.722,
1610             0.556, 0.722, 0.667, 0.556, 0.611, 0.722, 0.722, 0.944,
1611             0.722, 0.722, 0.611, 0.333, 0.278, 0.333, 0.469, 0.500,
1612             0.333, 0.444, 0.500, 0.444, 0.500, 0.444, 0.333, 0.500,
1613             0.500, 0.278, 0.278, 0.500, 0.278, 0.778, 0.500, 0.500,
1614             0.500, 0.500, 0.333, 0.389, 0.278, 0.500, 0.500, 0.722,
1615             0.500, 0.500, 0.444, 0.480, 0.200, 0.480, 0.541, 0.000,
1616             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1617             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 1.000,
1618             0.278, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333,
1619             0.333, 0.000, 0.333, 0.333, 0.000, 0.333, 0.333, 0.333,
1620             0.250, 0.333, 0.500, 0.500, 0.500, 0.500, 0.200, 0.500,
1621             0.333, 0.760, 0.276, 0.500, 0.564, 0.333, 0.760, 0.333,
1622             0.400, 0.564, 0.300, 0.300, 0.333, 0.500, 0.453, 0.250,
1623             0.333, 0.300, 0.310, 0.500, 0.750, 0.750, 0.750, 0.444,
1624             0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 0.889, 0.667,
1625             0.611, 0.611, 0.611, 0.611, 0.333, 0.333, 0.333, 0.333,
1626             0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 0.564,
1627             0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 0.556, 0.500,
1628             0.444, 0.444, 0.444, 0.444, 0.444, 0.444, 0.667, 0.444,
1629             0.444, 0.444, 0.444, 0.444, 0.278, 0.278, 0.278, 0.278,
1630             0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.564,
1631             0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500,
1632             ];
1633              
1634 0           $wx[0][1] =
1635             [ #Times-Bold ISOLatin1
1636             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1637             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1638             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1639             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1640             0.250, 0.333, 0.555, 0.500, 0.500, 1.000, 0.833, 0.333,
1641             0.333, 0.333, 0.500, 0.570, 0.250, 0.333, 0.250, 0.278,
1642             0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500,
1643             0.500, 0.500, 0.333, 0.333, 0.570, 0.570, 0.570, 0.500,
1644             0.930, 0.722, 0.667, 0.722, 0.722, 0.667, 0.611, 0.778,
1645             0.778, 0.389, 0.500, 0.778, 0.667, 0.944, 0.722, 0.778,
1646             0.611, 0.778, 0.722, 0.556, 0.667, 0.722, 0.722, 1.000,
1647             0.722, 0.722, 0.667, 0.333, 0.278, 0.333, 0.581, 0.500,
1648             0.333, 0.500, 0.556, 0.444, 0.556, 0.444, 0.333, 0.500,
1649             0.556, 0.278, 0.333, 0.556, 0.278, 0.833, 0.556, 0.500,
1650             0.556, 0.556, 0.444, 0.389, 0.333, 0.556, 0.500, 0.722,
1651             0.500, 0.500, 0.444, 0.394, 0.220, 0.394, 0.520, 0.000,
1652             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1653             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 1.000,
1654             0.278, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333,
1655             0.333, 0.000, 0.333, 0.333, 0.000, 0.333, 0.333, 0.333,
1656             0.250, 0.333, 0.500, 0.500, 0.500, 0.500, 0.220, 0.500,
1657             0.333, 0.747, 0.300, 0.500, 0.570, 0.333, 0.747, 0.333,
1658             0.400, 0.570, 0.300, 0.300, 0.333, 0.556, 0.540, 0.250,
1659             0.333, 0.300, 0.330, 0.500, 0.750, 0.750, 0.750, 0.500,
1660             0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 1.000, 0.722,
1661             0.667, 0.667, 0.667, 0.667, 0.389, 0.389, 0.389, 0.389,
1662             0.722, 0.722, 0.778, 0.778, 0.778, 0.778, 0.778, 0.570,
1663             0.778, 0.722, 0.722, 0.722, 0.722, 0.722, 0.611, 0.556,
1664             0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.722, 0.444,
1665             0.444, 0.444, 0.444, 0.444, 0.278, 0.278, 0.278, 0.278,
1666             0.500, 0.556, 0.500, 0.500, 0.500, 0.500, 0.500, 0.570,
1667             0.500, 0.556, 0.556, 0.556, 0.556, 0.500, 0.556, 0.500,
1668             ];
1669              
1670 0           $wx[0][2] =
1671             [ #Times-Italic ISOLatin1
1672             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1673             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1674             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1675             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1676             0.250, 0.333, 0.420, 0.500, 0.500, 0.833, 0.778, 0.333,
1677             0.333, 0.333, 0.500, 0.675, 0.250, 0.333, 0.250, 0.278,
1678             0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500,
1679             0.500, 0.500, 0.333, 0.333, 0.675, 0.675, 0.675, 0.500,
1680             0.920, 0.611, 0.611, 0.667, 0.722, 0.611, 0.611, 0.722,
1681             0.722, 0.333, 0.444, 0.667, 0.556, 0.833, 0.667, 0.722,
1682             0.611, 0.722, 0.611, 0.500, 0.556, 0.722, 0.611, 0.833,
1683             0.611, 0.556, 0.556, 0.389, 0.278, 0.389, 0.422, 0.500,
1684             0.333, 0.500, 0.500, 0.444, 0.500, 0.444, 0.278, 0.500,
1685             0.500, 0.278, 0.278, 0.444, 0.278, 0.722, 0.500, 0.500,
1686             0.500, 0.500, 0.389, 0.389, 0.278, 0.500, 0.444, 0.667,
1687             0.444, 0.444, 0.389, 0.400, 0.275, 0.400, 0.541, 0.000,
1688             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1689             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.889,
1690             0.278, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333,
1691             0.333, 0.000, 0.333, 0.333, 0.000, 0.333, 0.333, 0.333,
1692             0.250, 0.389, 0.500, 0.500, 0.500, 0.500, 0.275, 0.500,
1693             0.333, 0.760, 0.276, 0.500, 0.675, 0.333, 0.760, 0.333,
1694             0.400, 0.675, 0.300, 0.300, 0.333, 0.500, 0.523, 0.250,
1695             0.333, 0.300, 0.310, 0.500, 0.750, 0.750, 0.750, 0.500,
1696             0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.889, 0.667,
1697             0.611, 0.611, 0.611, 0.611, 0.333, 0.333, 0.333, 0.333,
1698             0.722, 0.667, 0.722, 0.722, 0.722, 0.722, 0.722, 0.675,
1699             0.722, 0.722, 0.722, 0.722, 0.722, 0.556, 0.611, 0.500,
1700             0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.667, 0.444,
1701             0.444, 0.444, 0.444, 0.444, 0.278, 0.278, 0.278, 0.278,
1702             0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.675,
1703             0.500, 0.500, 0.500, 0.500, 0.500, 0.444, 0.500, 0.444,
1704             ];
1705              
1706 0           $wx[0][3] =
1707             [ #Times-BoldItalic ISOLatin1
1708             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1709             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1710             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1711             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1712             0.250, 0.389, 0.555, 0.500, 0.500, 0.833, 0.778, 0.333,
1713             0.333, 0.333, 0.500, 0.570, 0.250, 0.333, 0.250, 0.278,
1714             0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500,
1715             0.500, 0.500, 0.333, 0.333, 0.570, 0.570, 0.570, 0.500,
1716             0.832, 0.667, 0.667, 0.667, 0.722, 0.667, 0.667, 0.722,
1717             0.778, 0.389, 0.500, 0.667, 0.611, 0.889, 0.722, 0.722,
1718             0.611, 0.722, 0.667, 0.556, 0.611, 0.722, 0.667, 0.889,
1719             0.667, 0.611, 0.611, 0.333, 0.278, 0.333, 0.570, 0.500,
1720             0.333, 0.500, 0.500, 0.444, 0.500, 0.444, 0.333, 0.500,
1721             0.556, 0.278, 0.278, 0.500, 0.278, 0.778, 0.556, 0.500,
1722             0.500, 0.500, 0.389, 0.389, 0.278, 0.556, 0.444, 0.667,
1723             0.500, 0.444, 0.389, 0.348, 0.220, 0.348, 0.570, 0.000,
1724             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1725             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 1.000,
1726             0.278, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333,
1727             0.333, 0.000, 0.333, 0.333, 0.000, 0.333, 0.333, 0.333,
1728             0.250, 0.389, 0.500, 0.500, 0.500, 0.500, 0.220, 0.500,
1729             0.333, 0.747, 0.266, 0.500, 0.606, 0.333, 0.747, 0.333,
1730             0.400, 0.570, 0.300, 0.300, 0.333, 0.576, 0.500, 0.250,
1731             0.333, 0.300, 0.300, 0.500, 0.750, 0.750, 0.750, 0.500,
1732             0.667, 0.667, 0.667, 0.667, 0.667, 0.667, 0.944, 0.667,
1733             0.667, 0.667, 0.667, 0.667, 0.389, 0.389, 0.389, 0.389,
1734             0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 0.570,
1735             0.722, 0.722, 0.722, 0.722, 0.722, 0.611, 0.611, 0.500,
1736             0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.722, 0.444,
1737             0.444, 0.444, 0.444, 0.444, 0.278, 0.278, 0.278, 0.278,
1738             0.500, 0.556, 0.500, 0.500, 0.500, 0.500, 0.500, 0.570,
1739             0.500, 0.556, 0.556, 0.556, 0.556, 0.444, 0.500, 0.444,
1740             ];
1741              
1742 0           $wx[2][0] =
1743             [ #Helvetica ISOLatin1
1744             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1745             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1746             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1747             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1748             0.278, 0.278, 0.355, 0.556, 0.556, 0.889, 0.667, 0.222,
1749             0.333, 0.333, 0.389, 0.584, 0.278, 0.584, 0.278, 0.278,
1750             0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556,
1751             0.556, 0.556, 0.278, 0.278, 0.584, 0.584, 0.584, 0.556,
1752             1.015, 0.667, 0.667, 0.722, 0.722, 0.667, 0.611, 0.778,
1753             0.722, 0.278, 0.500, 0.667, 0.556, 0.833, 0.722, 0.778,
1754             0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944,
1755             0.667, 0.667, 0.611, 0.278, 0.278, 0.278, 0.469, 0.556,
1756             0.222, 0.556, 0.556, 0.500, 0.556, 0.556, 0.278, 0.556,
1757             0.556, 0.222, 0.222, 0.500, 0.222, 0.833, 0.556, 0.556,
1758             0.556, 0.556, 0.333, 0.500, 0.278, 0.556, 0.500, 0.722,
1759             0.500, 0.500, 0.500, 0.334, 0.260, 0.334, 0.584, 0.000,
1760             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1761             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 1.000,
1762             0.278, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333,
1763             0.333, 0.000, 0.333, 0.333, 0.000, 0.333, 0.333, 0.333,
1764             0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.260, 0.556,
1765             0.333, 0.737, 0.370, 0.556, 0.584, 0.333, 0.737, 0.333,
1766             0.400, 0.584, 0.333, 0.333, 0.333, 0.556, 0.537, 0.278,
1767             0.333, 0.333, 0.365, 0.556, 0.834, 0.834, 0.834, 0.611,
1768             0.667, 0.667, 0.667, 0.667, 0.667, 0.667, 1.000, 0.722,
1769             0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278,
1770             0.722, 0.722, 0.778, 0.778, 0.778, 0.778, 0.778, 0.584,
1771             0.778, 0.722, 0.722, 0.722, 0.722, 0.667, 0.667, 0.611,
1772             0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.889, 0.500,
1773             0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278,
1774             0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.584,
1775             0.611, 0.556, 0.556, 0.556, 0.556, 0.500, 0.556, 0.500,
1776             ];
1777              
1778 0           $wx[2][1] =
1779             [ #Helvetica-Bold ISOLatin1
1780             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1781             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1782             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1783             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1784             0.278, 0.333, 0.474, 0.556, 0.556, 0.889, 0.722, 0.278,
1785             0.333, 0.333, 0.389, 0.584, 0.278, 0.584, 0.278, 0.278,
1786             0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556,
1787             0.556, 0.556, 0.333, 0.333, 0.584, 0.584, 0.584, 0.611,
1788             0.975, 0.722, 0.722, 0.722, 0.722, 0.667, 0.611, 0.778,
1789             0.722, 0.278, 0.556, 0.722, 0.611, 0.833, 0.722, 0.778,
1790             0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944,
1791             0.667, 0.667, 0.611, 0.333, 0.278, 0.333, 0.584, 0.556,
1792             0.278, 0.556, 0.611, 0.556, 0.611, 0.556, 0.333, 0.611,
1793             0.611, 0.278, 0.278, 0.556, 0.278, 0.889, 0.611, 0.611,
1794             0.611, 0.611, 0.389, 0.556, 0.333, 0.611, 0.556, 0.778,
1795             0.556, 0.556, 0.500, 0.389, 0.280, 0.389, 0.584, 0.000,
1796             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1797             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 1.000,
1798             0.278, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333,
1799             0.333, 0.000, 0.333, 0.333, 0.000, 0.333, 0.333, 0.333,
1800             0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.280, 0.556,
1801             0.333, 0.737, 0.370, 0.556, 0.584, 0.333, 0.737, 0.333,
1802             0.400, 0.584, 0.333, 0.333, 0.333, 0.611, 0.556, 0.278,
1803             0.333, 0.333, 0.365, 0.556, 0.834, 0.834, 0.834, 0.611,
1804             0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 1.000, 0.722,
1805             0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278,
1806             0.722, 0.722, 0.778, 0.778, 0.778, 0.778, 0.778, 0.584,
1807             0.778, 0.722, 0.722, 0.722, 0.722, 0.667, 0.667, 0.611,
1808             0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.889, 0.556,
1809             0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278,
1810             0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.584,
1811             0.611, 0.611, 0.611, 0.611, 0.611, 0.556, 0.611, 0.556,
1812             ];
1813              
1814 0           $wx[2][2] =
1815             [ #Helvetica-Oblique ISOLatin1
1816             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1817             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1818             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1819             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1820             0.278, 0.278, 0.355, 0.556, 0.556, 0.889, 0.667, 0.222,
1821             0.333, 0.333, 0.389, 0.584, 0.278, 0.584, 0.278, 0.278,
1822             0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556,
1823             0.556, 0.556, 0.278, 0.278, 0.584, 0.584, 0.584, 0.556,
1824             1.015, 0.667, 0.667, 0.722, 0.722, 0.667, 0.611, 0.778,
1825             0.722, 0.278, 0.500, 0.667, 0.556, 0.833, 0.722, 0.778,
1826             0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944,
1827             0.667, 0.667, 0.611, 0.278, 0.278, 0.278, 0.469, 0.556,
1828             0.222, 0.556, 0.556, 0.500, 0.556, 0.556, 0.278, 0.556,
1829             0.556, 0.222, 0.222, 0.500, 0.222, 0.833, 0.556, 0.556,
1830             0.556, 0.556, 0.333, 0.500, 0.278, 0.556, 0.500, 0.722,
1831             0.500, 0.500, 0.500, 0.334, 0.260, 0.334, 0.584, 0.000,
1832             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1833             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 1.000,
1834             0.278, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333,
1835             0.333, 0.000, 0.333, 0.333, 0.000, 0.333, 0.333, 0.333,
1836             0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.260, 0.556,
1837             0.333, 0.737, 0.370, 0.556, 0.584, 0.333, 0.737, 0.333,
1838             0.400, 0.584, 0.333, 0.333, 0.333, 0.556, 0.537, 0.278,
1839             0.333, 0.333, 0.365, 0.556, 0.834, 0.834, 0.834, 0.611,
1840             0.667, 0.667, 0.667, 0.667, 0.667, 0.667, 1.000, 0.722,
1841             0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278,
1842             0.722, 0.722, 0.778, 0.778, 0.778, 0.778, 0.778, 0.584,
1843             0.778, 0.722, 0.722, 0.722, 0.722, 0.667, 0.667, 0.611,
1844             0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.889, 0.500,
1845             0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278,
1846             0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.584,
1847             0.611, 0.556, 0.556, 0.556, 0.556, 0.500, 0.556, 0.500,
1848             ];
1849              
1850 0           $wx[2][3] =
1851             [ #Helvetica-BoldOblique ISOLatin1
1852             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1853             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1854             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1855             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1856             0.278, 0.333, 0.474, 0.556, 0.556, 0.889, 0.722, 0.278,
1857             0.333, 0.333, 0.389, 0.584, 0.278, 0.584, 0.278, 0.278,
1858             0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556,
1859             0.556, 0.556, 0.333, 0.333, 0.584, 0.584, 0.584, 0.611,
1860             0.975, 0.722, 0.722, 0.722, 0.722, 0.667, 0.611, 0.778,
1861             0.722, 0.278, 0.556, 0.722, 0.611, 0.833, 0.722, 0.778,
1862             0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944,
1863             0.667, 0.667, 0.611, 0.333, 0.278, 0.333, 0.584, 0.556,
1864             0.278, 0.556, 0.611, 0.556, 0.611, 0.556, 0.333, 0.611,
1865             0.611, 0.278, 0.278, 0.556, 0.278, 0.889, 0.611, 0.611,
1866             0.611, 0.611, 0.389, 0.556, 0.333, 0.611, 0.556, 0.778,
1867             0.556, 0.556, 0.500, 0.389, 0.280, 0.389, 0.584, 0.000,
1868             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1869             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 1.000,
1870             0.278, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333,
1871             0.333, 0.000, 0.333, 0.333, 0.000, 0.333, 0.333, 0.333,
1872             0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.280, 0.556,
1873             0.333, 0.737, 0.370, 0.556, 0.584, 0.333, 0.737, 0.333,
1874             0.400, 0.584, 0.333, 0.333, 0.333, 0.611, 0.556, 0.278,
1875             0.333, 0.333, 0.365, 0.556, 0.834, 0.834, 0.834, 0.611,
1876             0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 1.000, 0.722,
1877             0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278,
1878             0.722, 0.722, 0.778, 0.778, 0.778, 0.778, 0.778, 0.584,
1879             0.778, 0.722, 0.722, 0.722, 0.722, 0.667, 0.667, 0.611,
1880             0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.889, 0.556,
1881             0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278,
1882             0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.584,
1883             0.611, 0.611, 0.611, 0.611, 0.611, 0.556, 0.611, 0.556,
1884             ];
1885              
1886 0           $wx[1][0] =
1887             [ #Courier ISOLatin1
1888             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1889             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1890             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1891             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1892             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1893             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1894             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1895             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1896             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1897             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1898             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1899             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1900             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1901             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1902             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1903             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.000,
1904             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
1905             0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.600,
1906             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1907             0.600, 0.000, 0.600, 0.600, 0.000, 0.600, 0.600, 0.600,
1908             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1909             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1910             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1911             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1912             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1913             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1914             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1915             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1916             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1917             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1918             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1919             0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600, 0.600,
1920             ];
1921              
1922 0           $wx[1][1] = $wx[1][2] = $wx[1][3] = $wx[1][0];
1923             }
1924              
1925             #NB Width of Times 'hyphen' (ASCII 45) altered to 0.333 which MacOS returns
1926              
1927             1;
1928              
1929             __END__