File Coverage

blib/lib/PDFREP.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package PDFREP;
2              
3             #-----------------------------------------------------------------------------#
4             # #
5             # PDFREP #
6             # #
7             # OVERVIEW #
8             # #
9             # This module is used to create a basic data generated PDF file it's main #
10             # Purpose is to be generic and usable by all perl scripts in an easy manner #
11             # It does create all the indexes, but not the thumbnails #
12             # #
13             # DEVELOPMENT #
14             # #
15             # STARTED 26th June 2001 #
16             # COMPLETED 23rd July 2007 #
17             # #
18             # VERSION 2.20 #
19             # #
20             # WRITTEN BY Trevor Ward #
21             # #
22             # Copyright (c) 2001 Trevor Ward. All rights reserved. #
23             # This program is free software; you can redistribute it and/or #
24             # modify it under the same terms as Perl itself #
25             # MODIFICATION INDEX #
26             # #
27             # This comments area to include all modifications from Version 1.0 #
28             # The version number to be incremented by .1 for each modification #
29             # #
30             # Date Version By Comments #
31             # #
32             # 25/06/2001 1.00 TRW Initial Version #
33             # 10/07/2001 1.01 TRW Added Column offsets #
34             # 12/09/2001 1.02 TRW Added text () escaping #
35             # 10/10/2001 1.03 TRW Removed backslashes from text except octal #
36             # 29/01/2002 1.04 TRW Added columns for Graphics cm #
37             # 16/02/2003 1.05 TRW PFS VERSION Removed GD for base system #
38             # 17/03/2003 1.06 TRW Fixed 100 < 99 Bug #
39             #-----------------------------------------------------------------------------#
40             # Version 2 Updates #
41             # #
42             # 04/08/2005 2.00 TRW New Function lcnt for counting lines left #
43             # 23/07/2007 2.20 TRW Bug fix of bracket display issue #
44             #-----------------------------------------------------------------------------#
45              
46 1     1   1988 use strict;
  1         3  
  1         47  
47 1     1   1051 use English;
  1         5436  
  1         8  
48 1     1   127121 use GD;
  0            
  0            
49              
50             #-----------------------------------------------------------------------------#
51             # Exporter set the exporter information for the module #
52             #-----------------------------------------------------------------------------#
53              
54             use vars qw(@ISA @EXPORT $VERSION);
55              
56             use Exporter;
57              
58             $VERSION = '2.20';
59              
60             @ISA = qw(Exporter);
61              
62             #-----------------------------------------------------------------------------#
63             # As all parts of this module are required to be used @EXPORT is used #
64             #-----------------------------------------------------------------------------#
65              
66             @EXPORT = qw(catalog
67             crashed
68             fontset
69             heading
70             include_image
71             outlines
72             pagedata
73             trailer
74             writepdf
75             xreftrl
76             lcnt);
77              
78             #-----------------------------------------------------------------------------#
79             # GLOBAL VARIABLES #
80             # #
81             # The following list details the global variables and the functions they are #
82             # Updated in and used in #
83             # #
84             # $objcount - This is used to store the total amount of objects created #
85             # It is updated in the ??????? function #
86             # It is output in the trailer function #
87             # #
88             # $startxref - This is used to store the cross reference start value #
89             # It is updated in the ????????? function #
90             # It is output in the trailer function #
91             # #
92             # $rc - This is used as the return code to the calling program which allows #
93             # for the checking of print return codes. #
94             # #
95             # %pdoffs - This hash is used to store the byte offset of the new object #
96             # when created for use by the cross reference. This should then #
97             # ba able to create the index afterwards #
98             # #
99             # $offset - This is used to store the current offset value from all the text #
100             # which has been printed to the file #
101             # #
102             # $pagecnt - This is used to store up the total count of new pages within the #
103             # pdf file. #
104             # #
105             # %pageref - This is used to store up the page number reference as the key #
106             # and the object reference of the page. #
107             # #
108             # %fontstr - This is used to store the font internal name and the font's #
109             # physical name for all the fonts defined. #
110             # #
111             # $filetyp - This is used to store the physical location of the PDF data file #
112             # #
113             # $temptyp - This is used to store the physical location of the TMP data file #
114             # #
115             # $fontcnt - This is used to store the total number of fonts for calculation #
116             # #
117             # @pdpageline - This is the variable used to store the lines of data to be #
118             # output as the text within the document #
119             # #
120             # $pditem - This is used within the pagedata sub as a global counter which #
121             # needs retaining #
122             # #
123             # $pdlcnt - This keeps track of how many line of data have to be written in #
124             # the sub pagedata. #
125             # #
126             # $pdlgth - This is used within the pagedata sub as the total length of the #
127             # data passed to the stream part of the pdf file #
128             # #
129             # $lnum - This is used to store the current line number of the page. It #
130             # starts at line 80 top of page and subtracts down. #
131             # #
132             # $lcnt - This is used to check the amount of lines written out to the page #
133             # #
134             # @image_name - This is used to store the image names #
135             # #
136             #-----------------------------------------------------------------------------#
137              
138             # These variables are initialised within the heading sub routine
139              
140             my ($objcount, $startxref, $rc, %pdoffs, $offset, $pagecnt, %pageref, %fontstr, $filetyp, $temptyp);
141             my ($fontcnt, @pdprintline, $item, $lcnt, $pdlgth, @image_name, $tmpoffs, $rootobj, $infoobj);
142              
143             #-----------------------------------------------------------------------------#
144             # SUB NEW #
145             #-----------------------------------------------------------------------------#
146              
147             sub new
148             {
149             my($proto) = @ARG;
150             my $class = ref($proto) || $proto;
151             my $self = {};
152              
153             bless ($self, $class);
154              
155             return $self;
156             }
157              
158             #-----------------------------------------------------------------------------#
159             # SUB LCNT #
160             #-----------------------------------------------------------------------------#
161              
162             sub lcnt
163             {
164             return $lcnt;
165             }
166              
167             #-----------------------------------------------------------------------------#
168             # SUB HEADING #
169             # #
170             # This receives the file name and directory from the calling program and #
171             # Opens the output file for the first time writing the PDF Header record #
172             # It returns the Message and Status code as with all the functions within #
173             # this package Status code 0 is succesful and 1 is failure. It also #
174             # Initialises all the global variables and counters used #
175             #-----------------------------------------------------------------------------#
176              
177             sub heading
178             {
179             # Receive the passed variables
180             # $callpgm is always PDFREP set by using the Package information
181             # $filenam is the name of the output PDF file required
182             # $filedir is the directory for this file to be created in
183             # $title is the document title
184             # $author is the document author
185             # @rubbish is a catchall filed used incase additional parameters are entered - this is not used
186              
187             my ($callpgm, $filenam, $filedir, $title, $author, @rubbish) = @_;
188              
189             # Initialise all the global variables
190              
191             undef %pdoffs;
192             undef $offset;
193             undef $objcount;
194             undef $startxref;
195             undef $pagecnt;
196             undef %pageref;
197             undef %fontstr;
198             undef $fontcnt;
199             undef $rc;
200              
201             # Set the heading text value this will remain constant
202              
203             my $heading = "%PDF-1.3";
204              
205             # Check the passed parameters contain values return false if not
206              
207             my $mess;
208              
209             if (!$filenam)
210             {
211             $mess = "No File Name";
212             return ('0', $mess);
213             }
214             if (!$filedir)
215             {
216             $mess = "No Directory Details";
217             return ('0', $mess);
218             }
219              
220             # Create the data file name variable and open the file return false if file open fails
221             # Also create the temporary work file which is used to store the page data
222              
223             $filetyp = $filedir . $filenam . ".pdf";
224             $temptyp = $filedir . $filenam . ".tmp";
225              
226             open(PDFFILE, "> $filetyp") || warn return ('0' , "File open failure - $filetyp - $!");
227             binmode(PDFFILE);
228             open(TMPFILE, "> $temptyp") || warn return ('0' , "File open failure - $temptyp - $!");
229              
230             # Write the heading record to the file check the return value
231              
232             $rc = print PDFFILE "$heading\015\012";
233              
234             $offset = 0 if (!$offset);
235             $offset = $offset + length($heading) + 2;
236             if (!$rc)
237             {
238             return ('0', 'PDFREP Write PDF File Failure - Heading');
239             }
240             # Write the info line
241              
242             $objcount++;
243             $infoobj = $objcount;
244              
245             my @outline;
246             my $linecnt = 0;
247              
248             $outline[$linecnt] = "$objcount 0 obj";
249             $linecnt++;
250             $outline[$linecnt] = "<< ";
251              
252             my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime();
253             $year = $year + 1900;
254             $mon = $mon + 1;
255             $mon = '0' . "$mon" if (length($mon) < 2);
256             $mday = '0' . "$mday" if (length($mday) < 2);
257              
258             if ($title)
259             {
260             $outline[$linecnt] .= "/Title ( $title)";
261             $linecnt++;
262             }
263             if ($author)
264             {
265             $outline[$linecnt] .= "/Author ( $author)";
266             $linecnt++;
267             }
268             $outline[$linecnt] .= "/Creator (Perlrep Module V1.00 copyright T.R.Ward 2001)";
269             $linecnt++;
270             $outline[$linecnt] .= "/Producer (Perlrep Module V1.00 copyright T.R.Ward 2001)";
271             $linecnt++;
272             $outline[$linecnt] .= "/CreationDate ( D:$mday-$mon-$year $hour-$min-$sec)";
273             $linecnt++;
274             $outline[$linecnt] .= "/ModDate ( D:$mday-$mon-$year $hour-$min-$sec)";
275             $linecnt++;
276              
277             $outline[$linecnt] = ">>";
278             $linecnt++;
279             $outline[$linecnt] = "endobj";
280              
281             # Set the Offset for this object in the offset hash store
282              
283             $tmpoffs = $objcount;
284              
285             while (length($tmpoffs) < 4)
286             {
287             $tmpoffs = "0" . $tmpoffs;
288             }
289             #(length($objcount) < 2) ? ($tmpoffs = '0' . $objcount) : ($tmpoffs = $objcount);
290             $pdoffs{$tmpoffs} = $offset;
291              
292             # Write out the data to the PDF file check the return code and throw error if failure
293              
294             foreach $item (@outline)
295             {
296             $rc = print PDFFILE "$item\015\012";
297              
298             $offset = $offset + length($item) + 2;
299             }
300             # Call the Catalogue sub which produces the catalogue object
301              
302             $rc = &catalog();
303              
304             if (!$rc)
305             {
306             return ('0', 'PDFREP Write PDF File Failure - Catalog');
307             }
308             # Call the Outline sub which produces the Outlines object
309              
310             $rc = &outlines();
311              
312             if (!$rc)
313             {
314             return ('0', 'PDFREP Write PDF File Failure - Outline');
315             }
316             # Return the succesful message and true value to the called program.
317              
318             return ('1', "PDFREP Heading Succesful");
319             }
320              
321             #-----------------------------------------------------------------------------#
322             # SUB CATALOG #
323             # #
324             # This sub produces the catalog reference which is used to identify the #
325             # Pages object and the Outlines object Which are also fixed objects numbers. #
326             # The Catalog object number is always 1 #
327             # This sub is called from the heading sub as it is fixed #
328             #-----------------------------------------------------------------------------#
329              
330             sub catalog
331             {
332             my @catline = '';
333             my $item = '';
334              
335             # Setup the array of all the data required to produce the catalog object
336              
337             $objcount++;
338             $rootobj = $objcount;
339             my $pages = $objcount + 2;
340             my $outls = $objcount + 1;
341              
342             $catline[0] = "$objcount 0 obj";
343             $catline[1] = "<<";
344             $catline[2] = "/Type /Catalog";
345             $catline[3] = "/Pages $pages 0 R";
346             $catline[4] = "/Outlines $outls 0 R";
347             $catline[5] = ">>";
348             $catline[6] = "endobj";
349              
350             # Set the Offset for this object in the offset hash store
351              
352             $tmpoffs = $objcount;
353              
354             while (length($tmpoffs) < 4)
355             {
356             $tmpoffs = "0" . $tmpoffs;
357             }
358             #(length($objcount) < 2) ? ($tmpoffs = '0' . $objcount) : ($tmpoffs = $objcount);
359             $pdoffs{$tmpoffs} = $offset;
360              
361             # Write out the data to the PDF file check the return code and throw error if failure
362              
363             foreach $item (@catline)
364             {
365             $rc = print PDFFILE "$item\015\012";
366              
367             $offset = $offset + length($item) + 2;
368              
369             if (!$rc)
370             {
371             return 0;
372             }
373             }
374             return 1;
375             }
376              
377             #-----------------------------------------------------------------------------#
378             # SUB OUTLINES #
379             # #
380             # This sub produces the outlines object reference in a fixed format during #
381             # testing at anyway. #
382             # The Outlines object is always number 2 #
383             # This sub is called from the heading sub as it is fixed #
384             #-----------------------------------------------------------------------------#
385              
386             sub outlines
387             {
388             my @outline;
389             my $item = '';
390              
391             # Setup the data into the array required for the Outlines object
392              
393             $objcount++;
394              
395             $outline[0] = "$objcount 0 obj";
396             $outline[1] = "<<";
397             $outline[2] = "/Type /Outlines";
398             $outline[3] = ">>";
399             $outline[4] = "endobj";
400              
401             # Set the offset for this object using the offset hash
402              
403             $tmpoffs = $objcount;
404              
405             while (length($tmpoffs) < 4)
406             {
407             $tmpoffs = "0" . $tmpoffs;
408             }
409             #(length($objcount) < 2) ? ($tmpoffs = '0' . $objcount) : ($tmpoffs = $objcount);
410             $pdoffs{$tmpoffs} = $offset;
411              
412             # Write out the data to the PDF file check the return code and throw error if failure
413              
414             foreach $item (@outline)
415             {
416             $rc = print PDFFILE "$item\015\012";
417              
418             $offset = $offset + length($item) + 2;
419              
420             if (!$rc)
421             {
422             return 0;
423             }
424             }
425             return 1;
426             }
427              
428             #-----------------------------------------------------------------------------#
429             # SUB FONTSET #
430             # #
431             # This sub is where the font will be set during page creation. Hopefully #
432             # this is will sort out all font changes within the text which is to be #
433             # printed. It accepts the font name from the calling program #
434             #-----------------------------------------------------------------------------#
435              
436             sub fontset
437             {
438             # Receive the passed variables
439             # $callpgm is always PDFREP set by using the Package information
440             # $fontnam is the internal name of the font
441             # $fonttyp is the physical font used
442             # @rubbish is a catchall filed used incase additional parameters are entered - this is not used
443              
444             my ($callpgm, $fontnam, $fonttyp, @rubbish) = @_;
445              
446             # Now need to store these values until after the pages have been created into a global hash
447             # storing the font name as the key and adding 1 to the total font counter
448              
449             $fontstr{$fontnam} = $fonttyp;
450             $fontcnt++;
451              
452             # Return a succesful code
453              
454             return ('1', 'PDFREP Font Set Succesful');
455             }
456              
457             #-----------------------------------------------------------------------------#
458             # SUB PAGEDATA #
459             # #
460             # This sub is where the page data is set it is run after the page head has #
461             # been run and it produces a line of data at a time to enable the page to be #
462             # built as opposed to constructed. It receives various parameters prior to #
463             # the text. #
464             # Type of Info #
465             # np = new page #
466             # nl = new line #
467             # nc = new column #
468             #-----------------------------------------------------------------------------#
469              
470             sub pagedata
471             {
472             # Receive the passed variables
473             # $callpgm is always PDFREP set by using the Package information
474             # $ltype this is the type of data either new page (np) or new line (nl)
475             # $lcol this is the column offset from the left hand side of the page
476             # $lfont this is the size of the font
477             # $nfont this is the internal name of the font
478             # $ldata this is the actual text data to be used
479             # $psize this is the page size
480             # $porin This is the page orientation
481             # @rubbish is a catchall filed used incase additional parameters are entered - this is not used
482              
483             my ($callpgm, $ltype, $lcol, $lfont, $nfont, $nextf, $ital, $red, $green, $blue, $ldata, $psize, $porin, @rubbish) = @_;
484              
485             # Keep a check on the line count per page current maximum is 38 if over blow away files return error
486              
487             # Version 1.03 duplicate all backslashes to remove errors when passed.
488             # Also allow for octal characters to be passed by using a space either end of a three number field
489              
490             $ldata =~ s/\\/\\\\/gis;
491             $ldata =~ s/ \\\\(\d\d\d) /\\$1/gis;
492              
493             # End of version 1.03 update
494              
495             # Version 1.02 setup the correct values for escaped characters
496              
497             $ldata =~ s/\(/\\\(/gis;
498             $ldata =~ s/\)/\\\)/gis;
499              
500             # End of version 1.02 update
501              
502             # Version 2.00 update
503              
504             # $ldata =~ s/([\(\)])/\\$1/gis;
505              
506             if ($ltype eq 'nl')
507             {
508             $lcnt = $lcnt - $lfont;
509             $rc = print TMPFILE "$red $green $blue rg $lcol $nextf Td ($ldata) Tj\n";
510              
511             if (!$rc)
512             {
513             return ('0', 'PDFCGI Write TMP File Failure - New Line');
514             }
515             $rc = print TMPFILE "/$nfont $lfont Tf 1 0 $ital 1 10 $lcnt Tm\n";
516              
517             if (!$rc)
518             {
519             return ('0', 'PDFCGI Write TMP File Failure - New Line');
520             }
521             if ($lcnt <= 10)
522             {
523             &crashed();
524              
525             return ('0', 'PDFCGI Write Page over Max Lines - Files Deleted');
526             }
527             }
528             if ($ltype eq 'nc')
529             {
530             $lcnt = $lcnt;
531             $rc = print TMPFILE "$red $green $blue rg $lcol $nextf Td ($ldata) Tj\n";
532              
533             if (!$rc)
534             {
535             return ('0', 'PDFCGI Write TMP File Failure - New Line');
536             }
537             $rc = print TMPFILE "/$nfont $lfont Tf 1 0 $ital 1 10 $lcnt Tm\n";
538              
539             if (!$rc)
540             {
541             return ('0', 'PDFCGI Write TMP File Failure - New Line');
542             }
543             if ($lcnt <= 10)
544             {
545             &crashed();
546              
547             return ('0', 'PDFCGI Write Page over Max Lines - Files Deleted');
548             }
549             }
550             if ($ltype eq 'np')
551             {
552             $lcnt = '760';
553             $lcnt = '760' if ($psize eq 'LE' && $porin eq 'PO');
554             $lcnt = '582' if ($psize eq 'LE' && $porin eq 'LA');
555             $lcnt = '810' if ($psize eq 'A4' && $porin eq 'PO');
556             $lcnt = '565' if ($psize eq 'A4' && $porin eq 'LA');
557              
558             $pagecnt++;
559              
560             # After reseting line count and incrementing page count output unique line for identification
561             # to tmp file
562              
563             $rc = print TMPFILE "XXXXXXXXXXNEW PAGE - $pagecnt\n";
564              
565             if (!$rc)
566             {
567             return ('0', 'PDFCGI Write TMP File Failure - New Page');
568             }
569             $rc = print TMPFILE "$red $green $blue rg $lcol $nextf Td($ldata) Tj\n";
570              
571             if (!$rc)
572             {
573             return ('0', 'PDFCGI Write TMP File Failure - New Line');
574             }
575             $rc = print TMPFILE "/$nfont $lfont Tf 1 0 $ital 1 10 $lcnt Tm\n";
576              
577             if (!$rc)
578             {
579             return ('0', 'PDFCGI Write TMP File Failure - New Line');
580             }
581             }
582             if ($ltype eq 'im')
583             {
584             my ($pt1,$pt2,$pt3) = split (/\s/, $ldata);
585              
586             $lcnt = $lcnt - $pt3 - 5;
587             $rc = print TMPFILE "IMAGEXXXXXXXXX $ldata $lcnt $lcol\n";
588             $lcnt = $lcnt - 20;
589             }
590             # 1.04 Added columns for images type CM.
591             if ($ltype eq 'cm')
592             {
593             my ($pt1,$pt2,$pt3) = split (/\s/, $ldata);
594              
595             $rc = print TMPFILE "IMAGEXXXXXXXXX $ldata $lcnt $lcol\n";
596             }
597             return ('1', "PDFREP Page Data Succesful");
598             }
599              
600             #-----------------------------------------------------------------------------#
601             # SUB INCLUDE IMAGE #
602             # #
603             # This sub includes a png image file to enable the use of the chart module #
604             # to generate the required graphs and include them #
605             #-----------------------------------------------------------------------------#
606              
607             sub include_image
608             {
609             my ($pgmname, $iname, $image, $iwidth, $iheight, $type, $ipath) = @_;
610              
611             my $tmpdata = "$iname" . ":::" . "$image" . ":::" . "$iheight" . ":::" . "$iwidth" . ":::" .
612             "$type" . ":::". "$ipath";
613              
614             push(@image_name, $tmpdata);
615              
616             # Return a succesful code
617              
618             return ('1', 'PDFREP Include Image Succesful');
619             }
620              
621             #-----------------------------------------------------------------------------#
622             # SUB WRITEPDF #
623             # #
624             # This is the final subroutine called from the caling program. It writes the #
625             # PDF file from all the data input so far with all the references and so on #
626             # It is interesting in the fact that it has to be called but it also ends the #
627             # PDFREP program's output- Don't try adding anymore after this #
628             # ----------------------------------------------------------------------------#
629              
630             sub writepdf
631             {
632             # Lets start by closing and opening the TMPFILE which stores the page data.
633             # To get it back to the first record.
634              
635             my ($pgmname, $psize, $porin) = @_;
636              
637             print TMPFILE "XXXXXXXXXXNEW END - 0\n";
638              
639             close(TMPFILE) || warn return ('0' , "File Close failure A1 - $temptyp - $!");
640             open (TMPFILE, "< $temptyp") || warn return ('0' , "File open failure - $temptyp - $!");
641              
642             # Now it's time to initialise the variables which are used to output the data
643             # @pdprintline - this is used to store the data ready for printing. Local because not needed elsewhere
644              
645             my @pdprintline;
646             my $lcnt = '0';
647             my $item;
648             my $pobjcnt = '0';
649              
650             # read first line of page data file and split it down
651              
652             my $firstln = ;
653             chomp $firstln;
654              
655             my ($pt1, $pt2, $pt3, $pt4, $pt5, $pt6) = split(/\s/, $firstln);
656              
657             # Write the Pages Header Object Which calculates the total number of objects and the page objects
658             # It works on 2 objects per page and 1 object per font thus needing these object numbers
659             # OK Calculate the page and font object numbers.
660             # Use two hashes to store the data.
661             # Added include images
662              
663             my %pagenum;
664             my %fontnum;
665             my %imagnum;
666             my $procset;
667             my $tmpcnt = '0000';
668             my $tmpobj = $objcount + 2;
669              
670             while ($pagecnt > $tmpcnt)
671             {
672             $pagenum{$tmpcnt} = $tmpobj;
673             $tmpcnt++;
674             while (length($tmpcnt) < 4)
675             {
676             $tmpcnt = "0" . $tmpcnt;
677             }
678             $tmpobj = $tmpobj + 2;
679             }
680             foreach $item (@image_name)
681             {
682             my ($pta, @rest) = split (/:::/, $item);
683             $imagnum{$pta} = $tmpobj;
684             $tmpobj++;
685             }
686             # set the proset object number
687              
688             $procset = $tmpobj;
689             $tmpobj++;
690              
691             foreach $item (sort keys(%fontstr))
692             {
693             $fontnum{$item} = $tmpobj;
694             $tmpobj++;
695             }
696             # Start of new object add object count, should = 3 for this object.
697             # Update Offset for this object.
698              
699             $objcount++;
700             $tmpoffs = $objcount;
701              
702             while (length($tmpoffs) < 4)
703             {
704             $tmpoffs = "0" . $tmpoffs;
705             }
706             #(length($objcount) < 2) ? ($tmpoffs = '0' . $objcount) : ($tmpoffs = $objcount);
707             $pdoffs{$tmpoffs} = $offset;
708             $pobjcnt = $objcount;
709              
710             $pdprintline[$lcnt] = "$objcount 0 obj";
711             $lcnt++;
712             $pdprintline[$lcnt] = "<<";
713             $lcnt++;
714             $pdprintline[$lcnt] = "/Type /Pages";
715             $lcnt++;
716              
717             # Setup the kids info
718              
719             $pdprintline[$lcnt] = "/Kids [";
720              
721             $tmpcnt = 0;
722              
723             foreach $item (sort keys(%pagenum))
724             {
725             ($tmpcnt > 0) ? ($pdprintline[$lcnt] = $pdprintline[$lcnt] . " $pagenum{$item} 0 R")
726             : ($pdprintline[$lcnt] = $pdprintline[$lcnt] . " $pagenum{$item} 0 R");
727              
728             $tmpcnt++;
729             }
730             $pdprintline[$lcnt] = $pdprintline[$lcnt] . "]";
731             $lcnt++;
732             $pdprintline[$lcnt] = "/Count $pagecnt";
733             $lcnt++;
734             $pdprintline[$lcnt] = ">>";
735             $lcnt++;
736             $pdprintline[$lcnt] = "endobj";
737             $lcnt++;
738              
739             # Write the Pages object out
740              
741             foreach $item (@pdprintline)
742             {
743             $rc = print PDFFILE "$item\015\012";
744              
745             $offset = $offset + length($item) + 2;
746              
747             if (!$rc)
748             {
749             return ('0', 'PDFREP Write PDF File Failure - Pages Object');
750             }
751             }
752             # OK now it's time to produce the page data output which will use the font's defined within the
753             # Page heading and the temporary file to retrieve the actual page data.
754              
755             $tmpcnt = '0';
756              
757             while ($pagecnt > $tmpcnt)
758             {
759             $objcount++;
760             $tmpoffs = $objcount;
761              
762             while (length($tmpoffs) < 4)
763             {
764             $tmpoffs = "0" . $tmpoffs;
765             }
766             #(length($objcount) < 2) ? ($tmpoffs = '0' . $objcount) : ($tmpoffs = $objcount);
767             $pdoffs{$tmpoffs} = $offset;
768             $lcnt = '0';
769             undef @pdprintline;
770              
771             $pdprintline[$lcnt] = "$objcount 0 obj";
772             $lcnt++;
773             $pdprintline[$lcnt] = "<<";
774             $lcnt++;
775             $pdprintline[$lcnt] = "/Type /Page";
776             $lcnt++;
777             $pdprintline[$lcnt] = "/Parent $pobjcnt 0 R";
778             $lcnt++;
779             $pdprintline[$lcnt] = "/Resources << ";
780             $pdprintline[$lcnt] = $pdprintline[$lcnt] . "/ProcSet $procset 0 R";
781              
782             # Setup the font references for for the page
783              
784             my $tmpk = keys (%fontnum);
785             if ($tmpk > 0)
786             {
787             $pdprintline[$lcnt] = $pdprintline[$lcnt] . " /Font <<";
788              
789             foreach $item (sort keys(%fontnum))
790             {
791             $pdprintline[$lcnt] = $pdprintline[$lcnt] . " /$item $fontnum{$item} 0 R";
792             }
793             $pdprintline[$lcnt] = $pdprintline[$lcnt] . " >>";
794             }
795             # Setup the image references for for the page
796              
797             $tmpk = keys (%imagnum);
798             if ($tmpk > 0)
799             {
800             $pdprintline[$lcnt] = $pdprintline[$lcnt] . "/XObject <<";
801              
802             foreach $item (sort keys(%imagnum))
803             {
804             $pdprintline[$lcnt] = $pdprintline[$lcnt] . " /$item $imagnum{$item} 0 R";
805             }
806              
807             $pdprintline[$lcnt] = $pdprintline[$lcnt] . " >>";
808             }
809             $pdprintline[$lcnt] = $pdprintline[$lcnt] . " >>";
810             $lcnt++;
811             my $ncnt = $objcount + 1;
812              
813             if ($psize eq 'LE' && $porin eq 'PO')
814             {
815             $pdprintline[$lcnt] = "/MediaBox [0 0 612 792]";
816             }
817             if ($psize eq 'LE' && $porin eq 'LA')
818             {
819             $pdprintline[$lcnt] = "/MediaBox [0 0 792 612]";
820             }
821             if ($psize eq 'A4' && $porin eq 'PO')
822             {
823             $pdprintline[$lcnt] = "/MediaBox [0 0 595 842]";
824             }
825             if ($psize eq 'A4' && $porin eq 'LA')
826             {
827             $pdprintline[$lcnt] = "/MediaBox [0 0 842 595]";
828             }
829             $lcnt++;
830             $pdprintline[$lcnt] = "/Contents $ncnt 0 R";
831             $lcnt++;
832             $pdprintline[$lcnt] = ">>";
833             $lcnt++;
834             $pdprintline[$lcnt] = "endobj";
835             $lcnt++;
836              
837             # Write the Page object out
838              
839             foreach $item (@pdprintline)
840             {
841             $rc = print PDFFILE "$item\015\012";
842              
843             $offset = $offset + length($item) + 2;
844              
845             if (!$rc)
846             {
847             return ('0', 'PDFREP Write PDF File Failure - Page $objcount Object');
848             }
849             }
850             undef @pdprintline;
851             $lcnt = '0';
852              
853             # So now it's time to write out the page data.
854             # Lets get the page data for the current page.
855              
856             $ncnt = $tmpcnt + 1;
857              
858             if ($pt1 eq 'XXXXXXXXXXNEW' && $pt4 eq $ncnt)
859             {
860             $objcount++;
861             $pdlgth = 0;
862             $tmpoffs = $objcount;
863              
864             while (length($tmpoffs) < 4)
865             {
866             $tmpoffs = "0" . $tmpoffs;
867             }
868             #(length($objcount) < 2) ? ($tmpoffs = '0' . $objcount) : ($tmpoffs = $objcount);
869             $pdoffs{$tmpoffs} = $offset;
870             $pdprintline[$lcnt] = "endobj";
871             $lcnt++;
872             $pdprintline[$lcnt] = "endstream";
873             $lcnt++;
874             $pdprintline[$lcnt] = "ET";
875             $pdlgth = $pdlgth + length($pdprintline[$lcnt]) + 2;
876             $lcnt++;
877             while ()
878             {
879             chomp $_;
880             my $ldata = $_;
881              
882             ($pt1, $pt2, $pt3, $pt4, $pt5, $pt6) = split (/\s/, $ldata);
883             $ncnt = $tmpcnt + 1;
884              
885             if ($pt1 =~ m/IMAGEXXXXXXXXX/)
886             {
887             $pdprintline[$lcnt] = "BT";
888             $pdlgth = $pdlgth + length($pdprintline[$lcnt]) + 2;
889             $lcnt++;
890              
891             $pdprintline[$lcnt] = "q $pt3 0 0 $pt4 $pt6 $pt5 cm /$pt2 Do Q";
892             $pdlgth = $pdlgth + length($pdprintline[$lcnt]) + 2;
893             $lcnt++;
894             $pdprintline[$lcnt] = "ET";
895             $pdlgth = $pdlgth + length($pdprintline[$lcnt]) + 2;
896             $lcnt++;
897             next;
898             }
899             elsif ($pt1 eq 'XXXXXXXXXXNEW' && $pt4 ne $ncnt)
900             {
901             $pdprintline[$lcnt] = "BT";
902             $pdlgth = $pdlgth + length($pdprintline[$lcnt]) + 2;
903             $lcnt++;
904             $pdprintline[$lcnt] = "stream";
905             $lcnt++;
906             $pdprintline[$lcnt] = "<< /Length $pdlgth >>";
907             $lcnt++;
908             $pdprintline[$lcnt] = "$objcount 0 obj";
909             $lcnt++;
910              
911             my $tmplgth = @pdprintline;
912             $tmplgth--;
913             my $tmplgt1 = 0;
914             my @pdprintlin1;
915              
916             while ($tmplgth >= 0)
917             {
918             $pdprintlin1[$tmplgt1] = $pdprintline[$tmplgth];
919             $tmplgth--;
920             $tmplgt1++;
921             }
922             foreach $item (@pdprintlin1)
923             {
924             $rc = print PDFFILE "$item\015\012";
925              
926             $offset = $offset + length($item) + 2;
927              
928             if (!$rc)
929             {
930             return ('0', 'PDFREP Write PDF File Failure - Page $objcount Data');
931             }
932             }
933             last;
934             }
935             else
936             {
937             $pdprintline[$lcnt] = $ldata . "";
938              
939             $pdlgth = $pdlgth + length($pdprintline[$lcnt]) + 2;
940             $lcnt++;
941             }
942             }
943             }
944             $tmpcnt++;
945             }
946             # Include image definitions go here after pages and before fonts
947              
948             foreach $item (@image_name)
949             {
950             my ($pt1, $pt2, $pt3, $pt4, $pt5, $i_path) = split(/:::/, $item);
951              
952             undef @pdprintline;
953             $lcnt = '0';
954             $objcount++;
955             $tmpoffs = $objcount;
956              
957             while (length($tmpoffs) < 4)
958             {
959             $tmpoffs = "0" . $tmpoffs;
960             }
961             #(length($objcount) < 2) ? ($tmpoffs = '0' . $objcount) : ($tmpoffs = $objcount);
962             $pdoffs{$tmpoffs} = $offset;
963              
964             $pdprintline[$lcnt] = "$objcount 0 obj";
965             $lcnt++;
966             $pdprintline[$lcnt] = "<<";
967             $lcnt++;
968             $pdprintline[$lcnt] = "/Type /XObject";
969             $lcnt++;
970             $pdprintline[$lcnt] = "/Subtype /Image";
971             $lcnt++;
972             $pdprintline[$lcnt] = "/Name /$pt1";
973             $lcnt++;
974             $pdprintline[$lcnt] = "/Width $pt4";
975             $lcnt++;
976             $pdprintline[$lcnt] = "/Height $pt3";
977             $lcnt++;
978              
979             my $iname = "$i_path". "$pt2";
980             my $myImage;
981             my $imout;
982             my $imlgth = 0;
983              
984             open (INIMAGE, "< $iname");
985              
986             $pdprintline[$lcnt] = "/BitsPerComponent 8";
987             $lcnt++;
988             $pdprintline[$lcnt] = "/ColorSpace /DeviceRGB";
989             $lcnt++;
990             $pdprintline[$lcnt] = "/Filter /DCTDecode";
991             $lcnt++;
992              
993             if ($pt5 eq 'jpg')
994             {
995             $myImage = newFromJpeg GD::Image(\*INIMAGE) || die;
996             }
997             elsif ($pt5 eq 'png')
998             {
999             $myImage = newFromPng GD::Image(\*INIMAGE) || die;
1000             }
1001             $imout = $myImage->jpeg(600);
1002             $imlgth = length($imout);
1003              
1004             close (INIMAGE);
1005              
1006             $pdprintline[$lcnt] = "/Length $imlgth";
1007             $lcnt++;
1008             $pdprintline[$lcnt] = ">>";
1009             $lcnt++;
1010             $pdprintline[$lcnt] = "stream";
1011             $lcnt++;
1012             $pdprintline[$lcnt] = "$imout";
1013             $lcnt++;
1014             $pdprintline[$lcnt] = "endstream";
1015             $lcnt++;
1016             $pdprintline[$lcnt] = "endobj";
1017             $lcnt++;
1018              
1019             foreach $item (@pdprintline)
1020             {
1021             $rc = print PDFFILE "$item\015\012";
1022              
1023             $offset = $offset + length($item) + 2;
1024              
1025             if (!$rc)
1026             {
1027             return ('0', 'PDFREP Write PDF File Failure - Font $objcount Object');
1028             }
1029             }
1030             }
1031             # set the procset area
1032              
1033             undef @pdprintline;
1034             $lcnt = '0';
1035             $objcount++;
1036              
1037             $tmpoffs = $objcount;
1038              
1039             while (length($tmpoffs) < 4)
1040             {
1041             $tmpoffs = "0" . $tmpoffs;
1042             }
1043             #(length($objcount) < 2) ? ($tmpoffs = '0' . $objcount) : ($tmpoffs = $objcount);
1044             $pdoffs{$tmpoffs} = $offset;
1045              
1046             $pdprintline[$lcnt] = "$objcount 0 obj";
1047             $lcnt++;
1048             $pdprintline[$lcnt] = "[/PDF]";
1049             $lcnt++;
1050             $pdprintline[$lcnt] = "endobj";
1051             $lcnt++;
1052              
1053             foreach $item (@pdprintline)
1054             {
1055             $rc = print PDFFILE "$item\015\012";
1056              
1057             $offset = $offset + length($item) + 2;
1058              
1059             if (!$rc)
1060             {
1061             return ('0', 'PDFREP Write PDF File Failure - ProcSet $objcount Object');
1062             }
1063             }
1064             # Well were getting there guess what comes now
1065             # Your right it's the font definitions.
1066              
1067             foreach $item (sort keys(%fontstr))
1068             {
1069             undef @pdprintline;
1070             $lcnt = '0';
1071             $objcount++;
1072             $tmpoffs = $objcount;
1073              
1074             while (length($tmpoffs) < 4)
1075             {
1076             $tmpoffs = "0" . $tmpoffs;
1077             }
1078             #(length($objcount) < 2) ? ($tmpoffs = '0' . $objcount) : ($tmpoffs = $objcount);
1079             $pdoffs{$tmpoffs} = $offset;
1080              
1081             $pdprintline[$lcnt] = "$objcount 0 obj";
1082             $lcnt++;
1083             $pdprintline[$lcnt] = "<<";
1084             $lcnt++;
1085             $pdprintline[$lcnt] = "/Type /Font";
1086             $lcnt++;
1087             $pdprintline[$lcnt] = "/Subtype /Type1";
1088             $lcnt++;
1089             $pdprintline[$lcnt] = "/Name /$item";
1090             $lcnt++;
1091             $pdprintline[$lcnt] = "/BaseFont /$fontstr{$item}";
1092             $lcnt++;
1093              
1094             # Version 2 make more usable Encoding.
1095             # $pdprintline[$lcnt] = "/Encoding /MacRomanEncoding";
1096             $pdprintline[$lcnt] = "/Encoding /WinAnsiEncoding";
1097             $lcnt++;
1098             $pdprintline[$lcnt] = ">>";
1099             $lcnt++;
1100             $pdprintline[$lcnt] = "endobj";
1101             $lcnt++;
1102              
1103             foreach $item (@pdprintline)
1104             {
1105             $rc = print PDFFILE "$item\015\012";
1106              
1107             $offset = $offset + length($item) + 2;
1108              
1109             if (!$rc)
1110             {
1111             return ('0', 'PDFREP Write PDF File Failure - Font $objcount Object');
1112             }
1113             }
1114             }
1115             # Now lets do the cross reference and trailer data bits
1116              
1117             &xreftrl();
1118             &trailer();
1119              
1120             close(PDFFILE) || warn return ('0' , "File close failure - $filetyp - $!");
1121             close(TMPFILE) || warn return ('0' , "File close failure - $temptyp - $!");
1122              
1123             return ("1", "PDFREP Write PDF Data Succesful");
1124             }
1125              
1126             #-----------------------------------------------------------------------------#
1127             # SUB XREFTRL #
1128             # #
1129             # This sub is the cross reference creation sub. It takes all the input and #
1130             # places the required cross reference into the PDF file no parameters are #
1131             # passed or required. #
1132             #-----------------------------------------------------------------------------#
1133              
1134             sub xreftrl
1135             {
1136             my @xrefdata;
1137             my $item = '';
1138             my $xcnt = '0';
1139             my $tlcnt = 0;
1140             $objcount++;
1141             $xrefdata[0] = "xref";
1142             $tlcnt++;
1143             $xrefdata[1] = "0 $objcount";
1144             $tlcnt++;
1145             $startxref = $offset;
1146             $xrefdata[2] = "0000000000 65535 f";
1147             $tlcnt++;
1148              
1149             # Version 2 resolve aany number of pages.
1150              
1151             # foreach $item (sort keys(%pdoffs))
1152             foreach $item (sort {$a <=> $b} keys(%pdoffs))
1153             {
1154             my $tdata = $pdoffs{$item};
1155             my $tlgth = length($tdata);
1156              
1157             while ($tlgth < 10)
1158             {
1159             $tdata = "0$tdata";
1160             $tlgth++;
1161             }
1162             $xrefdata[$tlcnt] = "$tdata 00000 n";
1163             $offset = $offset + length($xrefdata[$tlcnt]);
1164             $tlcnt++;
1165             }
1166             foreach $item (@xrefdata)
1167             {
1168             $rc = print PDFFILE "$item\015\012";
1169              
1170             # Calculate the new offset afer calculating the amount of characters written.
1171              
1172             if (!$rc)
1173             {
1174             return ('0', 'PDFREP Write PDF File Failure - Cross Reference');
1175             }
1176             }
1177             return ('1', "PDFREP Cross Reference Succesful");
1178             }
1179              
1180             #-----------------------------------------------------------------------------#
1181             # SUB TRAILER #
1182             # #
1183             # This receives the appropriate information from the calling program and #
1184             # uses the already opened pdf file to add the trailer record of the file #
1185             # It is the final part of the PDF file and contains all the required number #
1186             # of objects etc. It returns the required messages and status before closing #
1187             # The PDF File #
1188             #-----------------------------------------------------------------------------#
1189              
1190             sub trailer
1191             {
1192             my ($callpgm, @rubbish) = @_;
1193              
1194             print PDFFILE "trailer\015\012";
1195             print PDFFILE "<<\015\012";
1196             print PDFFILE "/Size $objcount\015\012";
1197             print PDFFILE "/Root $rootobj 0 R\015\012";
1198             if ($infoobj)
1199             {
1200             print PDFFILE "/Info $infoobj 0 R\015\012";
1201             }
1202             print PDFFILE ">>\015\012";
1203             print PDFFILE "startxref\015\012";
1204             print PDFFILE "$startxref\015\012";
1205             print PDFFILE "%%EOF\015\012";
1206              
1207             return ('1', 'PDFREP Trailer Succesful');
1208             }
1209              
1210             #-----------------------------------------------------------------------------#
1211             # SUB CRASHED #
1212             # #
1213             # This does not receive any parameters all it does is an unlink on the open #
1214             # files and then closes the said files which should release any links and #
1215             # physical disc space used. It is called from either the PDFREP package or #
1216             # can be called from the controlling program in case of ending required #
1217             #-----------------------------------------------------------------------------#
1218              
1219             sub crashed
1220             {
1221             close(PDFFILE) || warn return ('0' , "File close failure - $filetyp - $!");
1222             close(TMPFILE) || warn return ('0' , "File close failure - $temptyp - $!");
1223              
1224             $rc = unlink $filetyp;
1225              
1226             if (!$rc)
1227             {
1228             return ('0', "CANNOT DELETE - $filetyp");
1229             }
1230             $rc = unlink $temptyp;
1231              
1232             if (!$rc)
1233             {
1234             return ('0', "CANNOT DELETE - $temptyp");
1235             }
1236             return ('1', "FILE DELETION AND CLOSE WORKED SUCCESFULLY");
1237             }
1238             1;