File Coverage

blib/lib/PDF/Reuse.pm
Criterion Covered Total %
statement 840 3369 24.9
branch 215 1474 14.5
condition 84 550 15.2
subroutine 72 154 46.7
pod 36 82 43.9
total 1247 5629 22.1


line stmt bran cond sub pod time code
1             package PDF::Reuse;
2              
3 3     3   312080 use 5.006;
  3         16  
4 3     3   25 use strict;
  3         6  
  3         83  
5 3     3   48 use warnings;
  3         7  
  3         276  
6              
7             require Exporter;
8             require Digest::MD5;
9 3         20 use autouse 'Carp' => qw(carp
10             cluck
11 3     3   1601 croak);
  3         2895  
12              
13 3     3   2324 use Compress::Zlib qw(compress inflateInit);
  3         230134  
  3         380  
14              
15 3     3   25 use autouse 'Data::Dumper' => qw(Dumper);
  3         7  
  3         18  
16             #use AutoLoader qw(AUTOLOAD);
17              
18             our $VERSION = '0.43';
19             our @ISA = qw(Exporter);
20             our @EXPORT = qw(prFile
21             prPage
22             prId
23             prIdType
24             prInitVars
25             prEnd
26             prExtract
27             prForm
28             prImage
29             prAltJpeg
30             prJpeg
31             prDoc
32             prDocForm
33             prFont
34             prFontSize
35             prGraphState
36             prGetLogBuffer
37             prAdd
38             prBar
39             prText
40             prDocDir
41             prLogDir
42             prLog
43             prVers
44             prCid
45             prJs
46             prInit
47             prField
48             prTouchUp
49             prCompress
50             prMbox
51             prBookmark
52             prStrWidth
53             prLink
54             prTTFont
55             prSinglePage);
56              
57             our ($utfil, $slutNod, $formCont, $imSeq, $duplicateInits, $page, $sidObjNr, $sida,
58             $interActive, $NamesSaved, $AARootSaved, $AAPageSaved, $root,
59             $AcroFormSaved, $id, $ldir, $checkId, $formNr, $imageNr,
60             $filnamn, $interAktivSida, $taInterAkt, $type, $runfil, $checkCs,
61             $confuseObj, $compress, $pos, $fontNr, $objNr, $docProxy,
62             $defGState, $gSNr, $pattern, $shading, $colorSpace, $totalCount);
63              
64             our (@kids, @counts, @formBox, @objekt, @parents, @aktuellFont, @skapa,
65             @jsfiler, @inits, @bookmarks, @annots);
66              
67             our ( %old, %oldObject, %resurser, %form, %image, %objRef, %nyaFunk, %fontSource,
68             %sidFont, %sidXObject, %sidExtGState, %font, %intAct, %fields, %script,
69             %initScript, %sidPattern, %sidShading, %sidColorSpace, %knownToFile,
70             %processed, %embedded, %dummy, %behandlad, %unZipped, %links, %prefs);
71              
72             our $stream = '';
73             our $idTyp = '';
74             our $ddir = '';
75             our $log = '';
76              
77             #########################
78             # Konstanter för objekt
79             #########################
80              
81 3     3   1894 use constant oNR => 0;
  3         11  
  3         231  
82 3     3   46 use constant oPOS => 1;
  3         6  
  3         212  
83 3     3   20 use constant oSTREAMP => 2;
  3         15  
  3         147  
84 3     3   22 use constant oKIDS => 3;
  3         5  
  3         148  
85 3     3   15 use constant oFORM => 4;
  3         4  
  3         130  
86 3     3   14 use constant oIMAGENR => 5;
  3         5  
  3         179  
87 3     3   17 use constant oWIDTH => 6;
  3         6  
  3         158  
88 3     3   16 use constant oHEIGHT => 7;
  3         5  
  3         154  
89 3     3   35 use constant oTYPE => 8;
  3         10  
  3         205  
90 3     3   14 use constant oNAME => 9;
  3         5  
  3         140  
91              
92             ###################################
93             # Konstanter för formulär
94             ###################################
95              
96 3     3   15 use constant fOBJ => 0;
  3         5  
  3         193  
97 3     3   30 use constant fRESOURCE => 1;
  3         6  
  3         135  
98 3     3   14 use constant fBBOX => 2;
  3         5  
  3         147  
99 3     3   13 use constant fIMAGES => 3;
  3         5  
  3         120  
100 3     3   13 use constant fMAIN => 4;
  3         5  
  3         142  
101 3     3   15 use constant fKIDS => 5;
  3         4  
  3         129  
102 3     3   14 use constant fNOKIDS => 6;
  3         4  
  3         164  
103 3     3   14 use constant fID => 7;
  3         5  
  3         160  
104 3     3   14 use constant fVALID => 8;
  3         6  
  3         168  
105              
106             ####################################
107             # Konstanter för images
108             ####################################
109              
110 3     3   14 use constant imWIDTH => 0;
  3         6  
  3         141  
111 3     3   16 use constant imHEIGHT => 1;
  3         4  
  3         145  
112 3     3   15 use constant imXPOS => 2;
  3         13  
  3         113  
113 3     3   13 use constant imYPOS => 3;
  3         26  
  3         263  
114 3     3   16 use constant imXSCALE => 4;
  3         25  
  3         160  
115 3     3   15 use constant imYSCALE => 5;
  3         5  
  3         140  
116 3     3   15 use constant imIMAGENO => 6;
  3         15  
  3         170  
117              
118             #####################################
119             # Konstanter för interaktiva objekt
120             #####################################
121              
122 3     3   17 use constant iNAMES => 1;
  3         4  
  3         238  
123 3     3   16 use constant iACROFORM => 2;
  3         24  
  3         168  
124 3     3   15 use constant iAAROOT => 3;
  3         6  
  3         127  
125 3     3   14 use constant iANNOTS => 4;
  3         5  
  3         134  
126 3     3   13 use constant iSTARTSIDA => 5;
  3         4  
  3         166  
127 3     3   23 use constant iAAPAGE => 6;
  3         7  
  3         230  
128              
129             #####################################
130             # Konstanter för fonter
131             #####################################
132              
133 3     3   17 use constant foREFOBJ => 0;
  3         5  
  3         173  
134 3     3   15 use constant foINTNAMN => 1;
  3         6  
  3         149  
135 3     3   17 use constant foEXTNAMN => 2;
  3         5  
  3         136  
136 3     3   15 use constant foORIGINALNR => 3;
  3         5  
  3         212  
137 3     3   17 use constant foSOURCE => 4;
  3         5  
  3         143  
138 3     3   13 use constant foTYP => 5;
  3         5  
  3         150  
139 3     3   15 use constant foFONTOBJ => 6;
  3         5  
  3         198  
140              
141             ##########
142             # Övrigt
143             ##########
144              
145 3     3   15 use constant IS_MODPERL => $ENV{MOD_PERL}; # For mod_perl 1.
  3         6  
  3         3664  
146             # For mod_perl 2 pass $r to prFile()
147             our $touchUp = 1;
148              
149             our %stdFont =
150             ('Times-Roman' => 'Times-Roman',
151             'Times-Bold' => 'Times-Bold',
152             'Times-Italic' => 'Times-Italic',
153             'Times-BoldItalic' => 'Times-BoldItalic',
154             'Courier' => 'Courier',
155             'Courier-Bold' => 'Courier-Bold',
156             'Courier-Oblique' => 'Courier-Oblique',
157             'Courier-BoldOblique' => 'Courier-BoldOblique',
158             'Helvetica' => 'Helvetica',
159             'Helvetica-Bold' => 'Helvetica-Bold',
160             'Helvetica-Oblique' => 'Helvetica-Oblique',
161             'Helvetica-BoldOblique' => 'Helvetica-BoldOblique',
162             'Symbol' => 'Symbol',
163             'ZapfDingbats' => 'ZapfDingbats',
164             'TR' => 'Times-Roman',
165             'TB' => 'Times-Bold',
166             'TI' => 'Times-Italic',
167             'TBI' => 'Times-BoldItalic',
168             'C' => 'Courier',
169             'CB' => 'Courier-Bold',
170             'CO' => 'Courier-Oblique',
171             'CBO' => 'Courier-BoldOblique',
172             'H' => 'Helvetica',
173             'HB' => 'Helvetica-Bold',
174             'HO' => 'Helvetica-Oblique',
175             'HBO' => 'Helvetica-BoldOblique',
176             'S' => 'Symbol',
177             'Z' => 'ZapfDingbats');
178              
179             our $ws = '\s';#'(?:[ \0\n\r\t\f]|%[^\r\n]*[\r\n])';
180              
181             our $genLowerX = 0;
182             our $genLowerY = 0;
183             our $genUpperX = 595,
184             our $genUpperY = 842;
185             our $genFont = 'Helvetica';
186             our $fontSize = 12;
187              
188             keys(%resurser) = 10;
189              
190             sub prFont
191 1     1 1 569 { my $nyFont = shift;
192 1         2 my ($intnamn, $extnamn, $objektnr, $oldIntNamn, $oldExtNamn);
193              
194 1 50       4 if (! $pos)
195 0         0 { errLog("No output file, you have to call prFile first");
196             }
197 1         2 $oldIntNamn = $aktuellFont[foINTNAMN];
198 1         2 $oldExtNamn = $aktuellFont[foEXTNAMN];
199 1 50       3 if ($nyFont)
200 1         4 { ($intnamn, $extnamn, $objektnr) = findFont($nyFont);
201             }
202             else
203 0         0 { $intnamn = $aktuellFont[foINTNAMN];
204 0         0 $extnamn = $aktuellFont[foEXTNAMN];
205             }
206 1 50       4 if ($runfil)
207 0         0 { $log .= "Font~$nyFont\n";
208             }
209 1 50       3 if (wantarray)
210 0         0 { return ($intnamn, $extnamn, $oldIntNamn, $oldExtNamn, \%font);
211             }
212             else
213 1         6 { return $intnamn;
214             }
215             }
216              
217             sub prFontSize
218 0   0 0 1 0 { my $fSize = shift || 12;
219 0         0 my $oldFontSize = $fontSize;
220 0 0       0 if ($fSize =~ m'\d+\.?\d*'o)
221 0         0 { $fontSize = $fSize;
222 0 0       0 if ($runfil)
223 0         0 { $log .= "FontSize~$fontSize\n";
224             }
225             }
226 0 0       0 if (! $pos)
227 0         0 { errLog("No output file, you have to call prFile first");
228             }
229              
230 0         0 return ($fontSize, $oldFontSize);
231             }
232              
233             sub prFile
234 9 50   9 1 461637 { if ($pos)
235 0         0 { prEnd();
236 0         0 close UTFIL;
237             }
238 9         22 %prefs = ();
239 9         19 my $param = shift;
240 9 50       31 if (ref($param) eq 'HASH')
241 0         0 { $filnamn = '-';
242 0         0 for (keys %{$param})
  0         0  
243 0         0 { my $key = lc($_);
244 0 0 0     0 if ($key eq 'name')
    0 0        
      0        
      0        
245 0         0 { $filnamn = $param->{$_}; }
246             elsif (($key eq 'hidetoolbar')
247             || ($key eq 'hidemenubar')
248             || ($key eq 'hidewindowui')
249             || ($key eq 'fitwindow')
250             || ($key eq 'centerwindow'))
251 0         0 { $prefs{$key} = $param->{$_};
252             }
253             }
254             }
255             else
256 9   50     28 { $filnamn = $param || '-';
257 9 50       24 $prefs{hidetoolbar} = $_[1] if defined $_[1];
258 9 50       25 $prefs{hidemenubar} = $_[2] if defined $_[2];
259 9 50       23 $prefs{hidewindowui} = $_[3] if defined $_[3];
260 9 50       18 $prefs{fitwindow} = $_[4] if defined $_[4];
261 9 50       22 $prefs{centerwindow} = $_[5] if defined $_[5];
262             }
263 9         15 my $kortNamn;
264 9 50       21 if ($filnamn ne '-')
265 9         20 { my $ri = rindex($filnamn,'/');
266 9 100       19 if ($ri > 0)
267 8         19 { $kortNamn = substr($filnamn, ($ri + 1));
268 8 50       24 $utfil = $ddir ? $ddir . $kortNamn : $filnamn;
269             }
270             else
271 1 50       4 { $utfil = $ddir ? $ddir . $filnamn : $filnamn;
272             }
273 9         16 $ri = rindex($utfil,'/');
274 9 100       19 if ($ri > 0)
275 8         18 { my $dirdel = substr($utfil,0,$ri);
276 8 50       120 if (! -e $dirdel)
277 0   0     0 { mkdir $dirdel || errLog("Couldn't create dir $dirdel, $!");
278             }
279             }
280             else
281 1         2 { $ri = rindex($utfil,'\\');
282 1 50       5 if ($ri > 0)
283 0         0 { my $dirdel = substr($utfil,0,$ri);
284 0 0       0 if (! -e $dirdel)
285 0   0     0 { mkdir $dirdel || errLog("Couldn't create dir $dirdel, $!");
286             }
287             }
288             }
289             }
290             else
291 0         0 { $utfil = $filnamn;
292             }
293              
294 9         19 my $utfil_ref = ref $utfil;
295 3     3   23 { no warnings; untie *UTFIL; } # Clear any previous tie (e.g., from IO::String)
  3         7  
  3         12950  
  9         13  
  9         20  
296 9 50 66     67 if ($utfil_ref and ($utfil_ref eq 'Apache2::RequestRec') or
    100 33        
      66        
297             ($utfil_ref eq 'Apache::RequestRec') ) # mod_perl 2
298 0         0 { tie *UTFIL, $utfil;
299             }
300             elsif (IS_MODPERL && $utfil eq '-') # mod_perl 1
301             { tie *UTFIL, 'Apache';
302             }
303             elsif ($utfil_ref and $utfil_ref eq 'IO::String')
304 1         4 { tie *UTFIL, $utfil;
305             }
306             else
307 8 50       552 { open (UTFIL, ">$utfil") || errLog("Couldn't open file $utfil, $!");
308             }
309 9         36 binmode UTFIL;
310 9         24 my $utrad = "\%PDF-1.4\n\%\â\ã\Ï\Ó\n";
311              
312 9         244 $pos = syswrite UTFIL, $utrad;
313              
314 9 50       50 if (defined $ldir)
315 0 0       0 { if ($utfil eq '-')
316 0         0 { $kortNamn = 'stdout';
317             }
318 0 0       0 if ($kortNamn)
319 0         0 { $runfil = $ldir . $kortNamn . '.dat';
320             }
321             else
322 0         0 { $runfil = $ldir . $filnamn . '.dat';
323             }
324 0 0       0 open (RUNFIL, ">>$runfil") || errLog("Couldn't open logfile $runfil, $!");
325 0         0 $log .= "Vers~$VERSION\n";
326             }
327              
328              
329 9         21 @parents = ();
330 9         21 @kids = ();
331 9         17 @counts = ();
332 9         20 @objekt = ();
333 9         15 $objNr = 2; # Reserverat objekt 1 för root och 2 för initial sidnod
334 9         15 $parents[0] = 2;
335 9         12 $page = 0;
336 9         15 $formNr = 0;
337 9         14 $imageNr = 0;
338 9         13 $fontNr = 0;
339 9         22 $gSNr = 0;
340 9         14 $pattern = 0;
341 9         32 $shading = 0;
342 9         13 $colorSpace = 0;
343 9         16 $sida = 0;
344 9         21 %font = ();
345 9         22 %resurser = ();
346 9         15 %fields = ();
347 9         30 @jsfiler = ();
348 9         16 @inits = ();
349 9         14 %nyaFunk = ();
350 9         17 %objRef = ();
351 9         15 %knownToFile = ();
352 9         18 @aktuellFont = ();
353 9         16 %old = ();
354 9         18 %behandlad = ();
355 9         14 @bookmarks = ();
356 9         15 %links = ();
357 9         15 undef $defGState;
358 9         13 undef $interActive;
359 9         15 undef $NamesSaved;
360 9         10 undef $AARootSaved;
361 9         12 undef $AcroFormSaved;
362 9         16 $checkId = '';
363 9         12 undef $duplicateInits;
364 9         21 undef $confuseObj;
365 9         12 $fontSize = 12;
366 9         15 $genLowerX = 0;
367 9         13 $genLowerY = 0;
368 9         19 $genUpperX = 595,
369             $genUpperY = 842;
370              
371 9         28 prPage(1);
372 9         14 $stream = ' ';
373 9 50       18 if ($runfil)
374 0         0 { $filnamn = prep($filnamn);
375 0         0 $log .= "File~$filnamn";
376 0 0       0 $log .= (exists $prefs{hidetoolbar}) ? "~$prefs{hidetoolbar}" : '~';
377 0 0       0 $log .= (exists $prefs{hidemenubar}) ? "~$prefs{hidemenubar}" : '~';
378 0 0       0 $log .= (exists $prefs{hidewindowui}) ? "~$prefs{hidewindowui}" : '~';
379 0 0       0 $log .= (exists $prefs{fitwindow}) ? "~$prefs{fitwindow}" : '~';
380 0 0       0 $log .= (exists $prefs{centerwindow}) ? "~$prefs{centerwindow}" : "~\n";
381             }
382 9         46 1;
383             }
384              
385              
386             sub prPage
387 9     9 1 14 { my $noLogg = shift;
388 9 50 33     47 if ((defined $stream) && (length($stream) > 0))
389 0         0 { skrivSida();
390             }
391              
392 9         12 $page++;
393 9         10 $objNr++;
394 9         20 $sidObjNr = $objNr;
395              
396             #
397             # Resurserna nollställs
398             #
399              
400 9         13 %sidXObject = ();
401 9         13 %sidExtGState = ();
402 9         18 %sidFont = ();
403 9         17 %sidPattern = ();
404 9         10 %sidShading = ();
405 9         13 %sidColorSpace = ();
406 9         13 @annots = ();
407              
408 9         14 undef $interAktivSida;
409 9         11 undef $checkCs;
410 9 50 33     22 if (($runfil) && (! $noLogg))
411 0         0 { $log .= "Page~\n";
412 0         0 print RUNFIL $log;
413 0         0 $log = '';
414             }
415 9 50       19 if (! $pos)
416 0         0 { errLog("No output file, you have to call prFile first");
417             }
418 9         14 1;
419              
420             }
421              
422             sub prText
423 7     7 1 5437 { my $xPos = shift;
424 7         12 my $yPos = shift;
425 7         15 my $TxT = shift;
426 7   50     59 my $align = shift || 'left';
427 7   50     24 my $rot = shift || '0';
428              
429 7         12 my $width = 0;
430 7         10 my $x_align_offset = 0;
431              
432 7 50       28 if (! defined $TxT)
433 0         0 { $TxT = '';
434             }
435              
436 7 50 33     56 if (($xPos !~ m'\-?[\d\.]+'o) || (! defined $xPos))
437 0         0 { errLog("Illegal x-position for text: $xPos");
438             }
439 7 50 33     35 if (($yPos !~ m'\-?[\d\.]+'o) || (! defined $yPos))
440 0         0 { errLog("Illegal y-position for text: $yPos");
441             }
442              
443 7 50       20 if ($runfil)
444 0         0 { my $Texten = prep($TxT);
445 0         0 $log .= "Text~$xPos~$yPos~$Texten~$align~$rot\n";
446             }
447              
448 7 50       76 if (length($stream) < 3)
449 7         15 { $stream = "0 0 0 rg\n 0 g\nf\n";
450             }
451              
452              
453 7 100       13 if (! $aktuellFont[foINTNAMN])
454 6         16 { findFont();
455             }
456 7         13 my $Font = $aktuellFont[foINTNAMN]; # Namn i strömmen
457 7         14 $sidFont{$Font} = $aktuellFont[foREFOBJ];
458 7         10 my $fontname = $aktuellFont[foEXTNAMN];
459 7 50       19 my $ttfont = $font{$fontname} ? $font{$fontname}[foFONTOBJ] : undef;
460              
461              
462             # define what the offset for alignment is
463              
464 7 50 33     27 if ((wantarray)
465             || ($align ne 'left'))
466 0         0 { $width = prStrWidth($TxT, $aktuellFont[foEXTNAMN], $fontSize);
467 0 0       0 if($align eq 'right')
    0          
468 0         0 { $x_align_offset = - $width;
469             }
470             elsif ($align eq 'center')
471 0         0 { $x_align_offset = -$width / 2;
472             }
473             }
474              
475 7         18 $TxT =~ s|\(|\\(|gos;
476 7         11 $TxT =~ s|\)|\\)|gos;
477              
478              
479 7 50       17 unless($rot)
480 7         18 { $stream .= "\nBT /$Font $fontSize Tf ";
481 7 50       19 if($ttfont)
    50          
482 0         0 { $TxT = $ttfont->encode_text($TxT);
483 0         0 $stream .= $xPos+$x_align_offset . " $yPos Td $TxT Tj ET\n";
484             }
485             elsif (!$aktuellFont[foTYP])
486 7         21 { $stream .= $xPos+$x_align_offset . " $yPos Td \($TxT\) Tj ET\n";
487             }
488             else
489 0         0 { my $text;
490 0         0 $TxT =~ s/\\(\d\d\d)/chr(oct($1))/eg;
  0         0  
491 0         0 for (unpack ('C*', $TxT))
492 0         0 { $text .= sprintf("%04x", ($_ - 29));
493             }
494 0         0 $stream .= $xPos+$x_align_offset . " $yPos Td \<$text\> Tj ET\n";
495             }
496             }
497             else
498 0 0       0 { if ($rot =~ m'q(\d)'oi)
499 0 0       0 { if ($1 eq '1')
    0          
500 0         0 { $rot = 270;
501             }
502             elsif ($1 eq '2')
503 0         0 { $rot = 180;
504             }
505             else
506 0         0 { $rot = 90;
507             }
508             }
509              
510 0         0 my $radian = sprintf("%.6f", $rot / 57.2957795); # approx.
511 0         0 my $Cos = sprintf("%.6f", cos($radian));
512 0         0 my $Sin = sprintf("%.6f", sin($radian));
513 0         0 my $negSin = $Sin * -1;
514              
515 0 0       0 my $encText = $ttfont ? $ttfont->encode_text($TxT) : "\($TxT\)";
516 0         0 $stream .= "\nq\n" # enter a new stack frame
517             # . "/Gs0 gs\n" # reset graphic mode
518             . "$Cos $Sin $negSin $Cos $xPos $yPos cm\n" # rotation/translation in the CM
519             . "\nBT /$Font $fontSize Tf "
520             . "$x_align_offset 0 Td $encText Tj ET\n" # text @ 0,0
521             . "Q\n"; # close the stack frame
522             }
523 7 50       20 if (! $pos)
524 0         0 { errLog("No output file, you have to call prFile first");
525             }
526              
527              
528 7 50       13 if (wantarray)
529             { # return a new "cursor" position...
530              
531 0 0       0 if($rot==0)
532 0 0       0 { if($align eq 'left')
    0          
    0          
533 0         0 { return ($xPos, $xPos + $width);
534             }
535             elsif($align eq 'center')
536 0         0 { return ($xPos - $x_align_offset, $xPos + $x_align_offset);
537             }
538             elsif($align eq 'right')
539 0         0 { return ($xPos - $width, $xPos);
540             }
541              
542             }
543             else
544             { # todo
545             # we could some trigonometry to return an x/y point
546 0         0 return 1;
547             }
548             }
549             else
550 7         22 { return 1;
551             }
552              
553             }
554              
555              
556             sub prAdd
557 0     0 1 0 { my $contents = shift;
558 0         0 $stream .= "\n$contents\n";
559 0 0       0 if ($runfil)
560 0         0 { $contents = prep($contents);
561 0         0 $log .= "Add~$contents\n";
562             }
563 0         0 $checkCs = 1;
564 0 0       0 if (! $pos)
565 0         0 { errLog("No output file, you have to call prFile first");
566             }
567 0         0 1;
568             }
569              
570             ##########################
571             # Ett grafiskt "formulär"
572             ##########################
573              
574             sub prForm
575 1     1 1 9 { my ($sidnr, $adjust, $effect, $tolerant, $infil, $x, $y, $size, $xsize,
576             $ysize, $rotate);
577 1         3 my $param = shift;
578 1 50       4 if (ref($param) eq 'HASH')
579 1         3 { $infil = $param->{'file'};
580 1   50     7 $sidnr = $param->{'page'} || 1;
581 1   50     6 $adjust = $param->{'adjust'} || '';
582 1   50     5 $effect = $param->{'effect'} || 'print';
583 1   50     4 $tolerant = $param->{'tolerant'} || '';
584 1   50     5 $x = $param->{'x'} || 0;
585 1   50     4 $y = $param->{'y'} || 0;
586 1   50     5 $rotate = $param->{'rotate'} || 0;
587 1   50     4 $size = $param->{'size'} || 1;
588 1   50     4 $xsize = $param->{'xsize'} || 1;
589 1   50     6 $ysize = $param->{'ysize'} || 1;
590             }
591             else
592 0         0 { $infil = $param;
593 0   0     0 $sidnr = shift || 1;
594 0   0     0 $adjust = shift || '';
595 0   0     0 $effect = shift || 'print';
596 0   0     0 $tolerant = shift || '';
597 0   0     0 $x = shift || 0;
598 0   0     0 $y = shift || 0;
599 0   0     0 $rotate = shift || 0;
600 0   0     0 $size = shift || 1;
601 0   0     0 $xsize = shift || 1;
602 0   0     0 $ysize = shift || 1;
603             }
604              
605             # Support IO::String and other IO handles as input (RT #168975)
606 1 50       3 if (ref($infil)) {
607 1         9 require File::Temp;
608 1         1 my $data;
609 1 50       3 if (ref($infil) eq "SCALAR") {
610 0         0 $data = $$infil;
611             } else {
612 1         4 local $/;
613 1         8 $data = <$infil>;
614 1 50       38 seek($infil, 0, 0) if $infil->can("seek");
615             }
616 1         31 my ($tmpfh, $tmpfile) = File::Temp::tempfile(SUFFIX => ".pdf", UNLINK => 1);
617 1         454 binmode $tmpfh;
618 1         15 print $tmpfh $data;
619 1         36 close $tmpfh;
620 1         5 $infil = $tmpfile;
621             }
622              
623 1         3 my $refNr;
624             my $namn;
625 1         3 $type = 'form';
626 1         3 my $fSource = $infil . '_' . $sidnr;
627 1 50       6 if (! exists $form{$fSource})
628 1         2 { $formNr++;
629 1         2 $namn = 'Fm' . $formNr;
630 1         3 $knownToFile{$fSource} = $namn;
631 1         1 my $action;
632 1 50       3 if ($effect eq 'load')
633 0         0 { $action = 'load'
634             }
635             else
636 1         2 { $action = 'print'
637             }
638 1         4 $refNr = getPage($infil, $sidnr, $action);
639 1 50       4 if ($refNr)
640 1         4 { $objRef{$namn} = $refNr;
641             }
642             else
643 0 0       0 { if ($tolerant)
    0          
644 0 0 0     0 { if ((defined $refNr) && ($refNr eq '0')) # Sidnumret existerar inte, men ok
645 0         0 { $namn = '0';
646             }
647             else
648 0         0 { undef $namn; # Sidan kan inte användas som form
649             }
650             }
651             elsif (! defined $refNr)
652 0         0 { my $mess = "$fSource can't be used as a form. See the documentation\n"
653             . "under prForm how to concatenate streams\n";
654 0         0 errLog($mess);
655             }
656             else
657 0         0 { errLog("File : $infil Page: $sidnr doesn't exist");
658             }
659             }
660             }
661             else
662 0 0       0 { if (exists $knownToFile{$fSource})
663 0         0 { $namn = $knownToFile{$fSource};
664             }
665             else
666 0         0 { $formNr++;
667 0         0 $namn = 'Fm' . $formNr;
668 0         0 $knownToFile{$fSource} = $namn;
669             }
670 0 0       0 if (exists $objRef{$namn})
671 0         0 { $refNr = $objRef{$namn};
672             }
673             else
674 0 0       0 { if (! $form{$fSource}[fVALID])
    0          
675 0         0 { my $mess = "$fSource can't be used as a form. See the documentation\n"
676             . "under prForm how to concatenate streams\n";
677 0 0       0 if ($tolerant)
678 0         0 { cluck $mess;
679 0         0 undef $namn;
680             }
681             else
682 0         0 { errLog($mess);
683             }
684             }
685             elsif ($effect ne 'load')
686 0         0 { $refNr = byggForm($infil, $sidnr);
687 0         0 $objRef{$namn} = $refNr;
688             }
689             }
690             }
691 1 50       4 my @BBox = @{$form{$fSource}[fBBOX]} if ($refNr);
  1         4  
692 1 50 33     8 if (($effect eq 'print') && ($form{$fSource}[fVALID]) && ($refNr))
      33        
693 1 50       4 { if (! defined $defGState)
694 1         14 { prDefaultGrState();
695             }
696              
697 1 50 33     22 if ($adjust)
    50 33        
      33        
      33        
      33        
698 0         0 { $stream .= "q\n";
699 0         0 $stream .= fillTheForm(@BBox, $adjust);
700 0         0 $stream .= "\n/Gs0 gs\n";
701 0         0 $stream .= "/$namn Do\n";
702 0         0 $stream .= "Q\n";
703             }
704             elsif (($x) || ($y) || ($rotate) || ($size != 1)
705             || ($xsize != 1) || ($ysize != 1))
706 0         0 { $stream .= "q\n";
707 0         0 $stream .= calcMatrix($x, $y, $rotate, $size,
708             $xsize, $ysize, $BBox[2], $BBox[3]);
709 0         0 $stream .= "\n/Gs0 gs\n";
710 0         0 $stream .= "/$namn Do\n";
711 0         0 $stream .= "Q\n";
712             }
713             else
714 1         3 { $stream .= "\n/Gs0 gs\n";
715 1         2 $stream .= "/$namn Do\n";
716              
717             }
718 1         7 $sidXObject{$namn} = $refNr;
719 1         2 $sidExtGState{'Gs0'} = $defGState;
720             }
721 1 50       4 if ($runfil)
722 0         0 { $infil = prep($infil);
723 0         0 $log .= "Form~$infil~$sidnr~$adjust~$effect~$tolerant";
724 0         0 $log .= "~$x~$y~$rotate~$size~$xsize~$ysize\n";
725             }
726 1 50       3 if (! $pos)
727 0         0 { errLog("No output file, you have to call prFile first");
728             }
729 1 50 33     5 if (($effect ne 'print') && ($effect ne 'add'))
730 0         0 { undef $namn;
731             }
732 1 50       3 if (wantarray)
733 0         0 { my $images = 0;
734 0 0       0 if (exists $form{$fSource}[fIMAGES])
735 0         0 { $images = scalar(@{$form{$fSource}[fIMAGES]});
  0         0  
736             }
737 0         0 return ($namn, $BBox[0], $BBox[1], $BBox[2],
738             $BBox[3], $images);
739             }
740             else
741 1         4 { return $namn;
742             }
743             }
744              
745              
746              
747             ##########################################################
748             sub prDefaultGrState
749             ##########################################################
750 2     2 0 4 { $objNr++;
751 2         5 $defGState = $objNr;
752 2 50       5 if (! $pos)
753 0         0 { errLog("No output file, you have to call prFile first");
754             }
755              
756 2         4 $objekt[$objNr] = $pos;
757 2         6 my $utrad = "$objNr 0 obj" . '<
758             . ">>endobj\n";
759 2         36 $pos += syswrite UTFIL, $utrad;
760 2         6 $objRef{'Gs0'} = $objNr;
761 2         4 return ('Gs0', $defGState);
762             }
763              
764             ######################################################
765             # En font lokaliseras och fontobjektet skrivs ev. ut
766             ######################################################
767              
768             sub findFont
769 3     3   25 { no warnings;
  3         6  
  3         11393  
770 8   100 8 0 1066 my $Font = shift || '';
771              
772 8 50       27 if (! (exists $fontSource{$Font})) # Fonten måste skapas
773 8 100       22 { if (exists $stdFont{$Font})
774 1         2 { $Font = $stdFont{$Font};}
775             else
776 7         13 { $Font = $genFont; } # Helvetica sätts om inget annat finns
777 8 50       21 if (! (exists $font{$Font}))
778 8         13 { $objNr++;
779 8         33 $fontNr++;
780 8         18 my $fontAbbr = 'Ft' . $fontNr;
781 8         21 my $fontObjekt = "$objNr 0 obj<
782             "/BaseFont/$Font/Encoding/WinAnsiEncoding>>endobj\n";
783 8         25 $font{$Font}[foINTNAMN] = $fontAbbr;
784 8         19 $font{$Font}[foREFOBJ] = $objNr;
785 8         17 $objRef{$fontAbbr} = $objNr;
786 8         12 $fontSource{$Font}[foSOURCE] = 'Standard';
787 8         18 $objekt[$objNr] = $pos;
788 8         239 $pos += syswrite UTFIL, $fontObjekt;
789             }
790             }
791             else
792 0 0       0 { if (defined $font{$Font}[foREFOBJ]) # Finns redan i filen
793             { ; }
794             else
795 0 0       0 { if ($fontSource{$Font}[foSOURCE] eq 'Standard')
796 0         0 { $objNr++;
797 0         0 $fontNr++;
798 0         0 my $fontAbbr = 'Ft' . $fontNr;
799 0         0 my $fontObjekt = "$objNr 0 obj<
800             "/BaseFont/$Font/Encoding/WinAnsiEncoding>>endobj\n";
801 0         0 $font{$Font}[foINTNAMN] = $fontAbbr;
802 0         0 $font{$Font}[foREFOBJ] = $objNr;
803 0         0 $objRef{$fontAbbr} = $objNr;
804 0         0 $objekt[$objNr] = $pos;
805 0         0 $pos += syswrite UTFIL, $fontObjekt;
806             }
807             else
808 0         0 { my $fSource = $fontSource{$Font}[foSOURCE];
809 0         0 my $ri = rindex($fSource, '_');
810 0         0 my $Source = substr($fSource, 0, $ri);
811 0         0 my $Page = substr($fSource, ($ri + 1));
812              
813 0 0       0 if (! $fontSource{$Font}[foORIGINALNR])
814 0         0 { errLog("Couldn't find $Font, aborts");
815             }
816             else
817             { my $namn = extractObject($Source, $Page,
818 0         0 $fontSource{$Font}[foORIGINALNR], 'Font');
819             }
820             }
821             }
822             }
823              
824 8         36 $aktuellFont[foEXTNAMN] = $Font;
825 8         15 $aktuellFont[foREFOBJ] = $font{$Font}[foREFOBJ];
826 8         56 $aktuellFont[foINTNAMN] = $font{$Font}[foINTNAMN];
827 8         15 $aktuellFont[foTYP] = $font{$Font}[foTYP];
828              
829 8         22 $sidFont{$aktuellFont[foINTNAMN]} = $aktuellFont[foREFOBJ];
830 8 50       17 if (! $pos)
831 0         0 { errLog("No output file, you have to call prFile first");
832             }
833              
834 8         18 return ($aktuellFont[foINTNAMN], $aktuellFont[foEXTNAMN], $aktuellFont[foREFOBJ]);
835             }
836              
837             sub skrivSida
838 9     9 0 15 { my ($compressFlag, $streamObjekt, @extObj);
839 9 50       23 if ($checkCs)
840 0         0 { @extObj = ($stream =~ m'/(\S+)\s*'gso);
841 0         0 checkContentStream(@extObj);
842             }
843 9 50 33     25 if (( $compress ) && ( length($stream) > 99 ))
844 0         0 { my $output = compress($stream);
845 0 0 0     0 if ((length($output) > 25) && (length($output) < (length($stream))))
846 0         0 { $stream = $output;
847 0         0 $compressFlag = 1;
848             }
849             }
850              
851 9 50       24 if (! $parents[0])
852 0         0 { $objNr++;
853 0         0 $parents[0] = $objNr;
854             }
855 9         30 my $parent = $parents[0];
856              
857             ##########################################
858             # Interaktiva funktioner läggs ev. till
859             ##########################################
860              
861 9 50       18 if ($interAktivSida)
862 0         0 { my ($infil, $sidnr) = split(/\s+/, $interActive);
863 0         0 ($NamesSaved, $AARootSaved, $AAPageSaved, $AcroFormSaved)
864             = AcroFormsEtc($infil, $sidnr);
865             }
866              
867             ##########################
868             # Skapa resursdictionary
869             ##########################
870 9         16 my $resursDict = "/ProcSet[/PDF/Text]";
871 9 100       22 if (scalar %sidFont)
872 7         10 { $resursDict .= '/Font << ';
873 7         10 my $i = 0;
874 7         31 for (sort keys %sidFont)
875 8         55 { $resursDict .= "/$_ $sidFont{$_} 0 R";
876             }
877              
878 7         17 $resursDict .= " >>";
879             }
880 9 100       20 if (scalar %sidXObject)
881 2         3 { $resursDict .= '/XObject<<';
882 2         18 for (sort keys %sidXObject)
883 2         7 { $resursDict .= "/$_ $sidXObject{$_} 0 R";
884             }
885 2         4 $resursDict .= ">>";
886             }
887 9 100       18 if (scalar %sidExtGState)
888 2         3 { $resursDict .= '/ExtGState<<';
889 2         6 for (sort keys %sidExtGState)
890 2         4 { $resursDict .= "\/$_ $sidExtGState{$_} 0 R";
891             }
892 2         5 $resursDict .= ">>";
893             }
894 9 50       18 if (scalar %sidPattern)
895 0         0 { $resursDict .= '/Pattern<<';
896 0         0 for (sort keys %sidPattern)
897 0         0 { $resursDict .= "/$_ $sidPattern{$_} 0 R";
898             }
899 0         0 $resursDict .= ">>";
900             }
901 9 50       68 if (scalar %sidShading)
902 0         0 { $resursDict .= '/Shading<<';
903 0         0 for (sort keys %sidShading)
904 0         0 { $resursDict .= "/$_ $sidShading{$_} 0 R";
905             }
906 0         0 $resursDict .= ">>";
907             }
908 9 50       22 if (scalar %sidColorSpace)
909 0         0 { $resursDict .= '/ColorSpace<<';
910 0         0 for (sort keys %sidColorSpace)
911 0         0 { $resursDict .= "/$_ $sidColorSpace{$_} 0 R";
912             }
913 0         0 $resursDict .= ">>";
914             }
915              
916              
917 9         13 my $resursObjekt;
918              
919 9 50       21 if (exists $resurser{$resursDict})
920 0         0 { $resursObjekt = $resurser{$resursDict}; # Fanns ett identiskt,
921             } # använd det
922             else
923 9         14 { $objNr++;
924 9 50       20 if ( keys(%resurser) < 10)
925 9         24 { $resurser{$resursDict} = $objNr; # Spara 10 första resursobjekten
926             }
927 9         10 $resursObjekt = $objNr;
928 9         18 $objekt[$objNr] = $pos;
929 9         18 $resursDict = "$objNr 0 obj<<$resursDict>>endobj\n";
930 9         152 $pos += syswrite UTFIL, $resursDict ;
931             }
932 9         31 my $sidObjekt;
933              
934 9 50       19 if (! $touchUp)
935             { #
936             # Contents objektet skapas
937             #
938              
939 0         0 my $devX = "900";
940 0         0 my $devY = "900";
941              
942 0         0 my $mellanObjekt = '<
943 0 0       0 if (defined $resursObjekt)
944 0         0 { $mellanObjekt .= "/Resources $resursObjekt 0 R";
945             }
946 0         0 $mellanObjekt .= "/BBox \[$genLowerX $genLowerY $genUpperX $genUpperY\]" .
947             "/Matrix \[ 1 0 0 1 -$devX -$devY \]";
948              
949 0         0 my $langd = length($stream);
950              
951 0         0 $objNr++;
952 0         0 $objekt[$objNr] = $pos;
953 0 0       0 if (! $compressFlag)
954 0         0 { $mellanObjekt = "$objNr 0 obj\n$mellanObjekt/Length $langd>>stream\n"
955             . $stream;
956 0         0 $mellanObjekt .= "endstream\nendobj\n";
957             }
958             else
959 0         0 { $stream = "\n" . $stream . "\n";
960 0         0 $langd++;
961 0         0 $mellanObjekt = "$objNr 0 obj\n$mellanObjekt/Filter/FlateDecode"
962             . "/Length $langd>>stream" . $stream;
963 0         0 $mellanObjekt .= "endstream\nendobj\n";
964             }
965              
966 0         0 $pos += syswrite UTFIL, $mellanObjekt;
967 0         0 $mellanObjekt = $objNr;
968              
969 0 0       0 if (! defined $confuseObj)
970 0         0 { $objNr++;
971 0         0 $objekt[$objNr] = $pos;
972              
973 0         0 $stream = "\nq\n1 0 0 1 $devX $devY cm\n/Xwq Do\nQ\n";
974 0         0 $langd = length($stream);
975 0         0 $confuseObj = $objNr;
976 0         0 $stream = "$objNr 0 obj<>stream\n" . "$stream";
977 0         0 $stream .= "\nendstream\nendobj\n";
978 0         0 $pos += syswrite UTFIL, $stream;
979             }
980 0         0 $sidObjekt = "$sidObjNr 0 obj\n<
981             . "/MediaBox \[$genLowerX $genLowerY $genUpperX $genUpperY\]"
982             . "/Resources <>>>";
983             }
984             else
985 9         15 { my $langd = length($stream);
986              
987 9         13 $objNr++;
988 9         14 $objekt[$objNr] = $pos;
989 9 50       16 if (! $compressFlag)
990 9         29 { $streamObjekt = "$objNr 0 obj<>stream\n" . $stream;
991 9         26 $streamObjekt .= "\nendstream\nendobj\n";
992             }
993             else
994 0         0 { $stream = "\n" . $stream . "\n";
995 0         0 $langd++;
996              
997 0         0 $streamObjekt = "$objNr 0 obj<
998             . "/Length $langd>>stream" . $stream;
999 0         0 $streamObjekt .= "endstream\nendobj\n";
1000             }
1001              
1002 9         78 $pos += syswrite UTFIL, $streamObjekt;
1003 9         31 $streamObjekt = $objNr;
1004             ##################################
1005             # Så skapas och skrivs sidobjektet
1006             ##################################
1007              
1008 9         35 $sidObjekt = "$sidObjNr 0 obj<
1009             . "/MediaBox \[$genLowerX $genLowerY $genUpperX $genUpperY\]"
1010             . "/Resources $resursObjekt 0 R";
1011             }
1012              
1013 9         16 $stream = '';
1014              
1015 9         14 my $tSida = $sida + 1;
1016 9 0 33     57 if ((@annots)
      0        
      33        
      33        
      0        
      33        
1017 0         0 || (%links && $links{'-1'} && @{$links{'-1'}})
1018 0         0 || (%links && $links{$tSida} && @{$links{$tSida}}))
1019 0         0 { $sidObjekt .= '/Annots ' . mergeLinks() . ' 0 R';
1020             }
1021 9 50       20 if (defined $AAPageSaved)
1022 0         0 { $sidObjekt .= "/AA $AAPageSaved";
1023 0         0 undef $AAPageSaved;
1024             }
1025 9         15 $sidObjekt .= ">>endobj\n";
1026 9         13 $objekt[$sidObjNr] = $pos;
1027 9         76 $pos += syswrite UTFIL, $sidObjekt;
1028 9         27 push @{$kids[0]}, $sidObjNr;
  9         26  
1029 9         12 $sida++;
1030 9         16 $counts[0]++;
1031 9 50       25 if ($counts[0] > 9)
1032 0         0 { ordnaNoder(8); }
1033             }
1034              
1035              
1036             sub prEnd
1037 9 50   9 1 43 { if (! $pos)
1038 0         0 { return;
1039             }
1040 9 50       20 if ($stream)
1041 9         22 { skrivSida(); }
1042 9         26 skrivUtNoder();
1043              
1044 9 50       37 if($docProxy)
1045 0         0 { $docProxy->write_objects;
1046             # Release Font::TTF data and TTFont0 objects now that they are written
1047 0         0 for my $obj (values %{ $docProxy->{' objcache'} })
  0         0  
1048 0 0       0 { if ($obj->isa('Text::PDF::TTFont0'))
1049 0 0       0 { if (my $font = delete $obj->{' font'})
1050 0         0 { $font->release();
1051             }
1052 0         0 $obj->release();
1053             }
1054             }
1055 0         0 undef $docProxy; # Break circular refs
1056             }
1057              
1058             ###################
1059             # Skriv root
1060             ###################
1061              
1062 9 50       23 if (! defined $objekt[$objNr])
1063 0         0 { $objNr--; # reserverat sidobjektnr utnyttjades aldrig
1064             }
1065              
1066 9         16 my $utrad = "1 0 obj<
1067 9 50 50     60 if (defined $NamesSaved)
    50          
1068 0         0 { $utrad .= "\/Names $NamesSaved 0 R\n";
1069             }
1070             elsif ((scalar %fields) || (scalar @jsfiler))
1071 0         0 { $utrad .= "\/Names " . behandlaNames() . " 0 R\n";
1072             }
1073 9 50       17 if (defined $AARootSaved)
1074 0         0 { $utrad .= "/AA $AARootSaved\n";
1075             }
1076 9 50 50     63 if ((scalar @inits) || (scalar %fields))
1077 0         0 { my $nyttANr = skrivKedja();
1078 0         0 $utrad .= "/OpenAction $nyttANr 0 R";
1079             }
1080              
1081 9 50       21 if (defined $AcroFormSaved)
1082 0         0 { $utrad .= "/AcroForm $AcroFormSaved\n";
1083             }
1084              
1085 9 50       23 if (scalar @bookmarks)
1086 0         0 { my $outLine = ordnaBookmarks();
1087 0         0 $utrad .= "/Outlines $outLine 0 R/PageMode /UseOutlines\n";
1088             }
1089 9 50       19 if (scalar %prefs)
1090 0         0 { $utrad .= '/ViewerPreferences << ';
1091 0 0       0 if (exists $prefs{hidetoolbar})
1092 0 0       0 { $utrad .= ($prefs{hidetoolbar}) ? '/HideToolbar true'
1093             : '/HideToolbar false';
1094             }
1095 0 0       0 if (exists $prefs{hidemenubar})
1096 0 0       0 { $utrad .= ($prefs{hidemenubar}) ? '/HideMenubar true'
1097             : '/HideMenubar false';
1098             }
1099 0 0       0 if (exists $prefs{hidewindowui})
1100 0 0       0 { $utrad .= ($prefs{hidewindowui}) ? '/HideWindowUI true'
1101             : '/HideWindowUI false';
1102             }
1103 0 0       0 if (exists $prefs{fitwindow})
1104 0 0       0 { $utrad .= ($prefs{fitwindow}) ? '/FitWindow true'
1105             : '/FitWindow false';
1106             }
1107 0 0       0 if (exists $prefs{centerwindow})
1108 0 0       0 { $utrad .= ($prefs{centerwindow}) ? '/CenterWindow true'
1109             : '/CenterWindow false';
1110             }
1111 0         0 $utrad .= '>> ';
1112             }
1113              
1114 9         18 $utrad .= ">>endobj\n";
1115              
1116 9         33 $objekt[1] = $pos;
1117 9         91 $pos += syswrite UTFIL, $utrad;
1118 9         34 my $antal = $#objekt;
1119 9         13 my $startxref = $pos;
1120 9         16 my $xrefAntal = $antal + 1;
1121 9         77 $pos += syswrite UTFIL, "xref\n";
1122 9         106 $pos += syswrite UTFIL, "0 $xrefAntal\n";
1123 9         91 $pos += syswrite UTFIL, "0000000000 65535 f \n";
1124              
1125 9         63 for (my $i = 1; $i <= $antal; $i++)
1126 61   50     248 { $utrad = sprintf "%.10d 00000 n \n", $objekt[$i] // 0;
1127 61         597 $pos += syswrite UTFIL, $utrad;
1128             }
1129              
1130 9         32 $utrad = "trailer\n<<\n/Size $xrefAntal\n/Root 1 0 R\n";
1131 9 50       25 if ($idTyp ne 'None')
1132 9         24 { my ($id1, $id2) = definieraId();
1133 9         19 $utrad .= "/ID [<$id1><$id2>]\n";
1134 9         14 $log .= "IdType~rep\n";
1135 9         17 $log .= "Id~$id1\n";
1136             }
1137 9         22 $utrad .= ">>\nstartxref\n$startxref\n";
1138 9         86 $pos += syswrite UTFIL, $utrad;
1139 9         85 $pos += syswrite UTFIL, "%%EOF\n";
1140 9         986 close UTFIL;
1141 3     3   27 { no warnings; untie *UTFIL; }
  3         5  
  3         1950  
  9         34  
  9         24  
1142              
1143 9 50       25 if ($runfil)
1144 0 0       0 { if ($log)
1145 0         0 { print RUNFIL $log;
1146             }
1147 0         0 close RUNFIL;
1148             }
1149 9         17 $log = '';
1150 9         15 $runfil = '';
1151 9         14 $pos = 0;
1152 9         27 1;
1153             }
1154              
1155             sub ordnaNoder
1156 0     0 0 0 { my $antBarn = shift;
1157 0         0 my $i = 0;
1158 0         0 my $j = 1;
1159 0         0 my $vektor;
1160              
1161 0         0 while ($antBarn < $#{$kids[$i]})
  0         0  
1162             { #
1163             # Skriv ut aktuell förälder
1164             # flytta till nästa nivå
1165             #
1166 0         0 $vektor = '[';
1167              
1168 0         0 for (@{$kids[$i]})
  0         0  
1169 0         0 { $vektor .= "$_ 0 R "; }
1170 0         0 $vektor .= ']';
1171              
1172 0 0       0 if (! $parents[$j])
1173 0         0 { $objNr++;
1174 0         0 $parents[$j] = $objNr;
1175             }
1176              
1177 0         0 my $nodObjekt;
1178 0         0 $nodObjekt = "$parents[$i] 0 obj<>endobj\n";
1179              
1180 0         0 $objekt[$parents[$i]] = $pos;
1181 0         0 $pos += syswrite UTFIL, $nodObjekt;
1182 0         0 $counts[$j] += $counts[$i];
1183 0         0 $counts[$i] = 0;
1184 0         0 $kids[$i] = [];
1185 0         0 push @{$kids[$j]}, $parents[$i];
  0         0  
1186 0         0 undef $parents[$i];
1187 0         0 $i++;
1188 0         0 $j++;
1189             }
1190             }
1191              
1192             sub skrivUtNoder
1193 3     3   26 { no warnings;
  3         21  
  3         107174  
1194 9     9 0 16 my ($i, $j, $vektor, $nodObjekt);
1195 9         14 my $si = -1;
1196             #
1197             # Hitta slutnoden
1198             #
1199 9         19 for (@parents)
1200 9         13 { $slutNod = $_;
1201 9         17 $si++;
1202             }
1203              
1204 9         31 for ($i = 0; $parents[$i] ne $slutNod; $i++)
1205 0 0       0 { if (defined $parents[$i]) # Bara definierat om det finns kids
1206 0         0 { $vektor = '[';
1207 0         0 for (@{$kids[$i]})
  0         0  
1208 0         0 { $vektor .= "$_ 0 R "; }
1209 0         0 $vektor .= ']';
1210             ########################################
1211             # Hitta förälder till aktuell förälder
1212             ########################################
1213 0         0 my $nod;
1214 0         0 for ($j = $i + 1; (! $nod); $j++)
1215 0 0       0 { if ($parents[$j])
1216 0         0 { $nod = $parents[$j];
1217 0         0 $counts[$j] += $counts[$i];
1218 0         0 push @{$kids[$j]}, $parents[$i];
  0         0  
1219             }
1220             }
1221              
1222 0         0 $nodObjekt = "$parents[$i] 0 obj<>endobj\n";
1223              
1224 0         0 $objekt[$parents[$i]] = $pos;
1225 0         0 $pos += syswrite UTFIL, $nodObjekt;
1226             }
1227             }
1228             #####################################
1229             # Så ordnas och skrivs slutnoden ut
1230             #####################################
1231 9         17 $vektor = '[';
1232 9         13 for (@{$kids[$si]})
  9         19  
1233 9         23 { $vektor .= "$_ 0 R "; }
1234 9         16 $vektor .= ']';
1235 9         20 $nodObjekt = "$slutNod 0 obj<
1236             # $nodObjekt .= "/MediaBox \[$genLowerX $genLowerY $genUpperX $genUpperY\]";
1237 9         15 $nodObjekt .= " >>endobj\n";
1238 9         16 $objekt[$slutNod] = $pos;
1239 9         93 $pos += syswrite UTFIL, $nodObjekt;
1240              
1241             }
1242              
1243             sub findGet
1244 2     2 0 5 { my ($fil, $cid) = @_;
1245 2         8 $fil =~ s|\s+$||o;
1246 2         3 my ($req, $extFil, $tempFil, $fil2, $tStamp, $res);
1247              
1248 2 50       31 if (-e $fil)
1249 2         17 { $tStamp = (stat($fil))[9];
1250 2 50       6 if ($cid)
1251             {
1252 0 0       0 if ($cid eq $tStamp)
1253 0         0 { return ($fil, $cid);
1254             }
1255             }
1256             else
1257 2         8 { return ($fil, $tStamp);
1258             }
1259             }
1260 0 0       0 if ($cid)
1261 0         0 { $fil2 = $fil . $cid;
1262 0 0       0 if (-e $fil2)
1263 0         0 { return ($fil2, $cid);
1264             }
1265             }
1266 0         0 errLog("The file $fil can't be found, aborts");
1267             }
1268              
1269             sub definieraId
1270 9 50   9 0 31 { if ($idTyp eq 'rep')
    50          
1271 0 0       0 { if (! defined $id)
1272 0         0 { errLog("Can't replicate the id if is missing, aborting");
1273             }
1274 0         0 my $tempId = $id;
1275 0         0 undef $id;
1276 0         0 return ($tempId, $tempId);
1277             }
1278             elsif ($idTyp eq 'add')
1279 0         0 { $id++;
1280 0         0 return ($id, $id);
1281             }
1282             else
1283 9         14 { my $str = time();
1284 9         45 $str .= $filnamn . $pos;
1285 9         42 $str = Digest::MD5::md5_hex($str);
1286 9         33 return ($str, $str);
1287             }
1288             }
1289              
1290             sub prStrWidth
1291 0     0 1 0 { require PDF::Reuse::Util;
1292 0         0 my $string = shift;
1293 0         0 my $Font = shift;
1294 0   0     0 my $FontSize = shift || $fontSize;
1295 0         0 my $w = 0;
1296              
1297             # there's no use continuing if no string is passed in
1298 0 0       0 if (! defined($string))
1299 0         0 { errLog("undefined value passed to prStrWidth");
1300             }
1301              
1302 0 0       0 if (length($string) == 0)
1303 0         0 { return 0;
1304             }
1305              
1306 0 0       0 if(my($width) = ttfStrWidth($string, $Font, $FontSize))
1307 0         0 { return $width;
1308             }
1309              
1310 0 0       0 if (! $Font)
1311 0 0       0 { if (! $aktuellFont[foEXTNAMN])
1312 0         0 { findFont();
1313             }
1314 0         0 $Font = $aktuellFont[foEXTNAMN];
1315             }
1316              
1317 0 0       0 if (! exists $PDF::Reuse::Util::font_widths{$Font})
1318 0 0       0 { if (exists $stdFont{$Font})
1319 0         0 { $Font = $stdFont{$Font};
1320             }
1321 0 0       0 if (! exists $PDF::Reuse::Util::font_widths{$Font})
1322 0         0 { $Font = 'Helvetica';
1323             }
1324             }
1325              
1326 0 0       0 if (ref($PDF::Reuse::Util::font_widths{$Font}) eq 'ARRAY')
1327 0         0 { my @font_table = @{ $PDF::Reuse::Util::font_widths{$Font} };
  0         0  
1328 0         0 for (unpack ("C*", $string))
1329 0         0 { $w += $font_table[$_];
1330             }
1331             }
1332             else
1333 0         0 { $w = length($string) * $PDF::Reuse::Util::font_widths{$Font};
1334             }
1335 0         0 $w = $w / 1000 * $FontSize;
1336              
1337 0         0 return $w;
1338             }
1339              
1340             sub prTTFont
1341 0 0   0 1 0 { return prFont() if ! @_;
1342 0         0 my($selector, $fontname) = @_;
1343              
1344             # Have we loaded this font already?
1345 0         0 my $ttfont = findTTFont($selector);
1346 0 0 0     0 if (! $ttfont and $font{$selector} )
1347 0         0 { return prFont($selector);
1348             }
1349 0 0       0 $fontname = $ttfont->fontname if $ttfont;
1350              
1351             # Create a new TTFont object if we haven't loaded this one before
1352 0 0       0 if (! $ttfont)
1353             { $docProxy ||= PDF::Reuse::DocProxy->new(
1354 0     0   0 next_obj => sub { ++$objNr },
1355 0   0     0 prObj => \&prObj,
1356             );
1357              
1358 0         0 my $ttfont = PDF::Reuse::TTFont->new(
1359             filename => $selector,
1360             fontname => $fontname,
1361             fontAbbr => 'Ft' . ++$fontNr,
1362             docProxy => $docProxy,
1363             );
1364 0         0 $fontname = $ttfont->fontname;
1365              
1366 0         0 $font{$fontname}[foINTNAMN] = $ttfont->fontAbbr;
1367 0         0 $font{$fontname}[foREFOBJ] = $ttfont->obj_num;
1368 0         0 $font{$fontname}[foFONTOBJ] = $ttfont;
1369 0         0 $objRef{$ttfont->fontAbbr} = $ttfont->obj_num;
1370 0         0 $fontSource{$fontname}[foSOURCE] = 'Standard';
1371             }
1372              
1373 0         0 my $oldIntNamn = $aktuellFont[foINTNAMN];
1374 0         0 my $oldExtNamn = $aktuellFont[foEXTNAMN];
1375              
1376 0         0 $aktuellFont[foEXTNAMN] = $fontname;
1377 0         0 $aktuellFont[foREFOBJ] = $font{$fontname}[foREFOBJ];
1378 0         0 $aktuellFont[foINTNAMN] = $font{$fontname}[foINTNAMN];
1379 0         0 $aktuellFont[foTYP] = $font{$fontname}[foTYP];
1380              
1381 0         0 $sidFont{$aktuellFont[foINTNAMN]} = $aktuellFont[foREFOBJ];
1382              
1383 0 0       0 if (wantarray)
1384 0         0 { return ($aktuellFont[foINTNAMN], $aktuellFont[foEXTNAMN], $oldIntNamn, $oldExtNamn, \%font);
1385             }
1386             else
1387 0         0 { return $aktuellFont[foINTNAMN];
1388             }
1389             }
1390              
1391              
1392             sub prObj
1393 0     0 0 0 { my($objNr, $data) = @_;
1394              
1395 0         0 $objekt[$objNr] = $pos;
1396 0         0 $pos += syswrite UTFIL, $data;
1397             }
1398              
1399              
1400             sub findTTFont
1401 0   0 0 0 0 { my $selector = shift || $aktuellFont[foEXTNAMN];
1402              
1403 0 0       0 return $font{$selector}[foFONTOBJ] if $font{$selector};
1404 0         0 foreach my $name (keys %font)
1405 0 0 0     0 { if ( $font{$name}[foINTNAMN] eq $selector
      0        
1406             or $font{$name}[foFONTOBJ] && $font{$name}[foFONTOBJ]->filename eq $selector
1407             )
1408 0         0 { return $font{$name}[foFONTOBJ];
1409             }
1410             }
1411 0         0 return;
1412             }
1413              
1414              
1415             sub ttfStrWidth
1416 0     0 0 0 { my($string, $selector, $fontsize) = @_;
1417              
1418 0 0       0 my $ttfont = findTTFont($selector) or return;
1419 0         0 return $ttfont->text_width($string, $fontsize);
1420             }
1421              
1422              
1423             # This 'glue' package emulates the bits of the Text::PDF::File API that are
1424             # needed by Text::PDF::TTFont0 (below) and ties them in to the PDF::Reuse API.
1425              
1426             package PDF::Reuse::DocProxy;
1427              
1428             sub new
1429 0     0   0 { my $class = shift;
1430              
1431 0         0 my $self = bless { ' version' => 3, @_, '>buffer' => '', }, $class;
1432             }
1433              
1434              
1435             sub new_obj
1436 0     0   0 { my $self = shift;
1437 0 0       0 my $obj = shift or die 'No base for new_obj';
1438              
1439 0         0 my $num = $self->{next_obj}->();
1440 0         0 my $gen = 0;
1441              
1442 0         0 $self->{' objcache'}{$num, $gen} = $obj;
1443 0         0 $self->{' objects'}{$obj->uid} = [ $num, $gen ];
1444 0         0 return $obj;
1445             }
1446              
1447              
1448             sub object_number
1449 0     0   0 { my($self, $obj) = @_;
1450 0   0     0 my $num = $self->{' objects'}{$obj->uid} || return;
1451 0         0 return $num->[0];
1452             }
1453              
1454              
1455             sub print
1456 0     0   0 { my($self, $data) = @_;
1457              
1458 0 0       0 if(my($tail, $rest) = $data =~ m{\A(.*?\nendobj\n)(.*)\z}s)
1459 0         0 { my($obj_num) = $self->{'>buffer'} =~ /(\d+)/;
1460             # Pass serialised object back to PDF::Reuse
1461 0         0 $self->{prObj}->($obj_num, $self->{'>buffer'} . $tail);
1462 0         0 $self->{'>buffer'} = $rest;
1463             }
1464             else
1465 0         0 { $self->{'>buffer'} .= $data;
1466             }
1467             }
1468              
1469              
1470             sub printf
1471 0     0   0 { my($self, $format, @args) = @_;;
1472 0         0 $self->print(sprintf($format, @args));
1473             }
1474              
1475              
1476             sub out_obj
1477 0     0   0 { my($self, $obj) = @_;
1478 0 0       0 return $self->new_obj($obj) unless defined $self->{' objects'}{$obj->uid};
1479 0         0 push @{ $self->{'>todo'} }, $obj->uid;
  0         0  
1480             }
1481              
1482              
1483             sub tell
1484 0     0   0 { return length shift->{'>buffer'};
1485             }
1486              
1487              
1488             sub write_objects
1489 0     0   0 { my($self) = @_;
1490              
1491 0         0 $self->{'>done'} = {};
1492 0         0 $self->{'>todo'} = [ sort map { $_->uid } values %{ $self->{' objcache'} } ];
  0         0  
  0         0  
1493 0         0 while(my $id = shift @{ $self->{'>todo'} }) {
  0         0  
1494 0 0       0 next if $self->{'>done'}{$id};
1495 0         0 my($num, $gen) = @{ $self->{' objects'}{$id} };
  0         0  
1496 0         0 $self->printf("%d %d obj\n", $num, $gen);
1497 0         0 $self->{' objcache'}{$num, $gen}->outobjdeep($self, $self);
1498 0         0 $self->print("\nendobj\n");
1499 0         0 $self->{'>done'}{$id}++;
1500             }
1501             }
1502              
1503              
1504             # This is a wrapper around Text::PDF::TTFont0, which provides support for
1505             # embedding TrueType fonts
1506              
1507             package PDF::Reuse::TTFont;
1508              
1509             sub new
1510 0     0   0 { my $class = shift;
1511              
1512 0         0 require Text::PDF::TTFont0;
1513              
1514 0         0 my $self = bless { 'subset' => 1, @_, }, $class;
1515              
1516             $self->{ttfont} = Text::PDF::TTFont0->new(
1517             $self->{docProxy},
1518             $self->{filename},
1519             $self->{fontAbbr},
1520             -subset => $self->{subset},
1521 0         0 );
1522 0         0 $self->{ttfont}->{' subvec'} = '';
1523              
1524 0         0 $self->{obj_num} = $self->{docProxy}->object_number($self->{ttfont});
1525              
1526 0   0     0 $self->{fontname} ||= $self->find_name();
1527              
1528 0         0 return $self;
1529             }
1530              
1531 0     0   0 sub filename { return $_[0]->{filename}; }
1532 0     0   0 sub fontname { return $_[0]->{fontname}; }
1533 0     0   0 sub obj_num { return $_[0]->{obj_num}; }
1534 0     0   0 sub fontAbbr { return $_[0]->{fontAbbr}; }
1535 0     0   0 sub docProxy { return $_[0]->{docProxy}; }
1536              
1537             sub find_name
1538 0     0   0 { my $self = shift;
1539 0         0 my($filebase) = $self->filename =~ m{.*[\\/](.*)\.};
1540 0 0       0 my $font = $self->{ttfont}->{' font'} or return $filebase;
1541 0 0       0 my $obj = $font->{'name'} or return $filebase;
1542 0 0       0 my $name = $obj->read->find_name(4) or return $filebase;
1543 0         0 $name =~ s{\W}{}g;
1544 0         0 return $name;
1545             }
1546              
1547             sub encode_text
1548 0     0   0 { my($self, $text) = @_;
1549 0         0 $text =~ s|\\\(|(|gos;
1550 0         0 $text =~ s|\\\)|)|gos;
1551 0         0 return $self->{ttfont}->out_text($text);
1552             }
1553              
1554             sub text_width
1555 0     0   0 { my($self, $text, $size) = @_;
1556 0         0 return $self->{ttfont}->width($text) * $size;
1557             }
1558              
1559             sub DESTROY
1560 0     0   0 { my $self = shift;
1561             # Do NOT release the ttfont (TTFont0) object here -- it is still
1562             # owned by the DocProxy's objcache and will be cleaned up in prEnd().
1563             # Releasing it here would wipe its ' uid' field causing write_objects
1564             # to crash (GitHub issue #24).
1565 0         0 %$self = ();
1566             }
1567              
1568              
1569             package PDF::Reuse; # Applies to the autoloaded methods below (?)
1570              
1571             1;
1572              
1573             ##__END__
1574              
1575             =head1 NAME
1576              
1577             PDF::Reuse - Reuse and mass produce PDF documents
1578              
1579             =head1 SYNOPSIS
1580              
1581             =for SYNOPSIS.pl begin
1582              
1583             use PDF::Reuse;
1584             prFile('myFile.pdf');
1585             prText(100, 500, 'Hello World !');
1586             prEnd();
1587              
1588             =for end
1589              
1590             =head1 DESCRIPTION
1591              
1592             This module could be used when you want to mass produce similar (but not identical)
1593             PDF documents and reuse templates, JavaScripts and some other components. It is
1594             functional to be fast, and to give your programs capacity to produce many pages
1595             per second and very big PDF documents if necessary.
1596              
1597             The module produces PDF-1.4 files. Some features of PDF-1.5, like "object streams"
1598             and "cross reference streams", are supported, but only at an experimental level. More
1599             testing is needed. (If you get problems with a new document from Acrobat 6 or higher, try to
1600             save it or recreate it as a PDF-1.4 document first, before using it together with
1601             this module.)
1602              
1603             =over 2
1604              
1605             =item Templates
1606              
1607             Use your favorite program, probably a commercial visual tool, to produce single
1608             PDF-files to be used as templates, and then use this module to B files
1609             from them.
1610              
1611             (If you want small PDF-files or want special graphics, you can use this module also,
1612             but visual tools are often most practical.)
1613              
1614             =item Lists
1615              
1616             The module uses "XObjects" extensively. This is a format that makes it possible
1617             create big lists, which are compact at the same time.
1618              
1619              
1620             =item PDF-operators
1621              
1622             The module gives you a good possibility to program at a "low level" with the basic
1623             graphic operators of PDF, if that is what you want to do. You can build your
1624             own libraries of low level routines, with PDF-directives "controlled" by Perl.
1625              
1626             =item Archive-format
1627              
1628             If you want, you get your new documents logged in a format suitable for archiving
1629             or transfer.
1630              
1631              
1632             PDF::Reuse::Tutorial might show you best what you can do with this module.
1633              
1634             =item JavaScript
1635              
1636             You can attach JavaScripts to your PDF-files.
1637              
1638             You can have libraries of JavaScripts. No cutting or pasting, and those who include
1639             the scripts in documents only need to know how to initiate them. (Of course those
1640             who write the scripts have to know Acrobat JavaScript well.)
1641              
1642             =back
1643              
1644             =head2 Remarks about JavaScript
1645              
1646             Some of the functions handling JavaScript have to be rewritten for Acrobat 7.
1647              
1648             There are many limitations with Acrobat JavaScript, and the rules often change.
1649             So what works for one version of Acrobat/Reader, might not work for another.
1650             Another complication is this:
1651             When documents are downloaded via the net by Acrobat, they are most often
1652             converted (!) and necessary JavaScripts are lost.
1653              
1654              
1655             =head1 FUNCTIONS
1656              
1657             All functions which are successful return specified values or 1.
1658              
1659             The module doesn't make any attempt to import anything from encrypted files.
1660              
1661             =head1 Overview
1662              
1663             To write a program with PDF::Reuse, you need these components:
1664              
1665             =begin html
1666              
1667            
1673              
1674              
1675            
1676            
1677             First
1678             Perhaps*
1679             Always
1680             Any or None
1681             Probably**
1682             Finally
1683            
1684            
1685             use PDF::Reuse
1686            
1687             prFile
1688             prInitVars
1689             prExtract
1690             prForm
1691             prInit
1692             prField
1693             prImage
1694             prAltJpeg
1695             prJpeg
1696             prFont
1697             prFontSize
1698             prTTFont
1699             prGraphState
1700             prAdd
1701             prText
1702             prJs
1703             prCompress
1704             prMbox
1705             prBookmark
1706             prStrWidth
1707             prLink
1708             prDoc
1709             prPage
1710             prSinglePage
1711             prEnd
1712            
1713            
1714             prDocDir*
1715             prLogDir*
1716            
1717             prDocForm*
1718             prGetLogBuffer*
1719             prBar*
1720             prLog*
1721             prTouchUp*
1722             prVers*
1723             prCid*
1724             prId*
1725             prIdType*
1726            
1727            
1728            
1729            
1730             * = internal/ deprecated function
1731            
1732            
1733             ** = not needed before prEnd or a new prFile
1734             In those cases prPage is automatically inserted
1735            
1736            
1737              
1738              
1739              
1740             =end html
1741              
1742             =head1 Mandatory Functions
1743              
1744             =head2 prFile - define output
1745              
1746             Alternative 1:
1747              
1748             prFile ( $fileName );
1749              
1750             Alternative 2 with parameters in an anonymous hash:
1751              
1752             prFile ( { Name => $fileName,
1753             HideToolbar => 1, # 1 or 0
1754             HideMenubar => 1, # 1 or 0
1755             HideWindowUI => 1, # 1 or 0
1756             FitWindow => 1, # 1 or 0
1757             CenterWindow => 1 } ); # 1 or 0
1758              
1759             Alternative 3:
1760              
1761             prFile ( $r ); # For mod_perl 2 pass the request object
1762              
1763             $fileName is optional, just like the rest of the parameters.
1764             File to create. If another file is current when this function is called, the first
1765             one is written and closed. Only one file is processed at a single moment. If
1766             $fileName is undefined, output is written to STDOUT.
1767              
1768             HideToolbar, HideMenubar, HideWindowUI, FitWindow and CenterWindow control the
1769             way the document is initially displayed.
1770              
1771             Look at any program in this documentation for examples. prInitVars() shows how
1772             this function could be used together with a web server.
1773              
1774             =head2 prEnd - end/flush buffers
1775              
1776             prEnd ()
1777              
1778             When the processing is going to end, the buffers of the B file has to be written to the disc.
1779             If this function is not called, the page structure, xref part and so on will be
1780             lost.
1781              
1782             Look at any program in this documentation for an example.
1783              
1784             =head1 Optional Functions
1785              
1786             =head2 prAdd - add "low level" instructions
1787              
1788             prAdd ( $string )
1789              
1790             With this command you can add whatever you want to the current content stream.
1791             No syntactical checks are made, but if you use an internal name, the module tries
1792             to add the resource of the "name object" to the "Resources" of current page.
1793             "Name objects" always begin with a '/'.
1794              
1795             (In this documentation I often use talk about an "internal name". It denotes a
1796             "name object". When PDF::Reuse creates these objects, it assigns Ft1, Ft2, Ft3 ...
1797             for fonts, Ig1, Ig2, Ig3 for images, Fo1 .. for forms, Cs1 .. for Color spaces,
1798             Pt1 .. for patterns, Sh1 .. for shading directories, Gs0 .. for graphic state
1799             parameter dictionaries. These names are kept until the program finishes,
1800             and my ambition is also to keep the resources available in internal tables.)
1801              
1802             This is a simple and very powerful function. You should study the examples and
1803             the "PDF-reference manual", if you want to use it.(When this text is written,
1804             a possible link to download it is:
1805             http://partners.adobe.com/asn/developer/acrosdk/docs.html)
1806              
1807             This function is intended to give you detail control at a low level.
1808              
1809             use PDF::Reuse;
1810             use strict;
1811              
1812             prFile('myFile.pdf');
1813             my $string = "150 600 100 50 re\n"; # a rectangle
1814             $string .= "0 0 1 rg\n"; # blue (to fill)
1815             $string .= "b\n"; # fill and stroke
1816             prAdd($string);
1817             prEnd();
1818              
1819              
1820             =head2 prBookmark - define bookmarks
1821              
1822             prBookmark($reference)
1823              
1824             Defines a "bookmark". $reference refers to a hash or array of hashes which looks
1825             something like this:
1826              
1827             { text => 'Document',
1828             act => 'this.pageNum = 0; this.scroll(40, 500);',
1829             kids => [ { text => 'Chapter 1',
1830             act => '1, 40, 600'
1831             },
1832             { text => 'Chapter 2',
1833             act => '10, 40, 600'
1834             }
1835             ]
1836             }
1837              
1838             Each hash can have these components:
1839              
1840             text the text shown beside the bookmark
1841             act the action to be triggered. Has to be a JavaScript action.
1842             (Three simple numbers are translated to page, x and y in the
1843             sentences: this.pageNum = page; this.scroll(x, y); )
1844             kids will have a reference to another hash or array of hashes
1845             close if this component is present, the bookmark will be closed
1846             when the document is opened
1847             color 3 numbers, RGB-colors e.g. '0.5 0.5 1' for light blue
1848             style 0, 1, 2, or 3. 0 = Normal, 1 = Italic, 2 = Bold, 3 = Bold Italic
1849              
1850             Creating bookmarks for a document:
1851              
1852             use PDF::Reuse;
1853             use strict;
1854              
1855             my @pageMarks;
1856              
1857             prFile('myDoc.pdf');
1858              
1859             for (my $i = 0; $i < 100; $i++)
1860             { prText(40, 600, 'Something is written');
1861             # ...
1862             my $page = $i + 1;
1863             my $bookMark = { text => "Page $page",
1864             act => "$i, 40, 700" };
1865             push @pageMarks, $bookMark;
1866             prPage();
1867             }
1868             prBookmark( { text => 'Document',
1869             close => 1,
1870             kids => \@pageMarks } );
1871             prEnd();
1872              
1873              
1874             Traditionally bookmarks have mainly been used for navigation within a document,
1875             but they can be used for many more things. You can e.g. use them to navigate within
1876             your data. You can let your users go to external links also, so they can "drill down"
1877             to other documents.
1878              
1879             B
1880              
1881             =head2 prCompress - compress/zip added streams
1882              
1883             prCompress (1)
1884              
1885             '1' here is a directive to compress all B streams of the current file. Streams
1886             which are included with prForm, prDocForm, prDoc or prSinglePage are not changed. New
1887             JavaScripts are also created as streams and compressed, if they are at least 100
1888             bytes long. The streams are compressed in memory, so probably there is a limit of
1889             how big they can be.
1890              
1891             prCompress(); is a directive not to compress. This is default.
1892              
1893             See e.g. "Starting to reuse" in the tutorial for an example.
1894              
1895             =head2 prDoc - include pages from a document
1896              
1897             prDoc ( $documentName, $firstPage, $lastPage )
1898              
1899             or with the parameters in an anonymous hash:
1900              
1901             prDoc ( { file => $documentName,
1902             first => $firstPage,
1903             last => $lastPage } );
1904              
1905             Returns number of extracted pages.
1906              
1907             If "first" is not given, 1 is assumed. If "last" is not given, you don't have any upper
1908             limit. N.B. The numbering of the pages differs from Acrobat JavaScript. In JavaScript
1909             the first page has index 0.
1910              
1911             Adds pages from a document to the one you are creating.
1912             N.B. From version 0.32 of this module:
1913             If there are contents created with with prText, prImage,prAdd, prForm and so on,
1914             prDoc tries to put the contents on the first extracted page
1915             from the old document.
1916              
1917              
1918             If it is the first interactive
1919             component ( prDoc() or prDocForm() ) the interactive functions are kept and also merged
1920             with JavaScripts you have added, if any. But, if you specify a first page different than 1
1921             or a last page, no JavaScript are extracted from the document, because then there is a
1922             risk that an included JavaScript function might refer to something not included.
1923              
1924             use PDF::Reuse;
1925             use strict;
1926              
1927             prFile('myFile.pdf'); # file to make
1928             prJs('customerResponse.js'); # include a JavaScript file
1929             prInit('nameAddress(12, 150, 600);'); # init a JavaScript function
1930             prForm('best.pdf'); # page 1 from best.pdf
1931             prPage();
1932             prDoc('long.pdf'); # a document with 11 pages
1933             prForm('best.pdf'); # page 1 from best.pdf
1934             prText(150, 700, 'Customer Data'); # a line of text
1935             prEnd();
1936              
1937             To extract pages 2-3 and 5-7 from a document and create a new document:
1938              
1939             use PDF::Reuse;
1940             use strict;
1941              
1942             prFile('new.pdf');
1943             prDoc( { file => 'old.pdf',
1944             first => 2,
1945             last => 3 });
1946             prDoc( { file => 'old.pdf',
1947             first => 5,
1948             last => 7 });
1949             prEnd();
1950              
1951              
1952             To add a form, image and page number to each page of an 16 pages long document
1953             (The document Battery.pdf is cropped so each page is fairly small) You could also have
1954             used prSinglePage, look at a very similar example under that function.
1955              
1956             use PDF::Reuse;
1957             use PDF::Reuse::Util;
1958             use strict;
1959              
1960             prFile('test.pdf');
1961              
1962             my $pageNumber = 0;
1963              
1964             for (my $page = 1; $page < 17; $page++)
1965             { $pageNumber++;
1966             prForm( { file =>'Words.pdf',
1967             page => 5,
1968             x => 150,
1969             y => 150} );
1970              
1971             prImage( { file =>'Media.pdf',
1972             page => 6,
1973             imageNo => 1,
1974             x => 450,
1975             y => 450 } );
1976             blackText();
1977             prText( 360, 250, $pageNumber);
1978             prDoc('Battery.pdf', $pageNumber, $pageNumber);
1979             }
1980             prEnd;
1981              
1982              
1983             =head2 prDocDir - set directory for produced documents
1984              
1985             prDocDir ( $directoryName )
1986              
1987             Sets directory for produced documents
1988              
1989             use PDF::Reuse;
1990             use strict;
1991              
1992             prDocDir('C:/temp/doc');
1993             prFile('myFile.pdf'); # writes to C:\temp\doc\myFile.pdf
1994             prForm('myFile.pdf'); # page 1 from ..\myFile.pdf
1995             prText(200, 600, 'New text');
1996             prEnd();
1997              
1998             =head2 prDocForm - use an interactive page as a form
1999              
2000             Alternative 1) You put your parameters in an anonymous hash (only B is really
2001             necessary, the others get default values if not given).
2002              
2003             prDocForm ( { file => $pdfFile, # template file
2004             page => $page, # page number (of imported template)
2005             adjust => $adjust, # try to fill the media box
2006             effect => $effect, # action to be taken
2007             tolerant => $tolerant, # continue even with an invalid form
2008             x => $x, # $x points from the left
2009             y => $y, # $y points from the bottom
2010             rotate => $degree, # rotate
2011             size => $size, # multiply everything by $size
2012             xsize => $xsize, # multiply horizontally by $xsize
2013             ysize => $ysize } ) # multiply vertically by $ysize
2014             Ex.:
2015             my $internalName = prDocForm ( {file => 'myFile.pdf',
2016             page => 2 } );
2017              
2018             Alternative 2) You put your parameters in this order
2019              
2020             prDocForm ( $pdfFile, [$page, $adjust, $effect, $tolerant, $x, $y, $degree,
2021             $size, $xsize, $ysize] )
2022              
2023              
2024             Anyway the function returns in list context: B<$intName, @BoundingBox,
2025             $numberOfImages>, in scalar context: B<$internalName> of the form.
2026              
2027             Look at prForm() for an explanation of the parameters.
2028              
2029             N.B. Usually you shouldn't adjust or change size and proportions of an interactive
2030             page. The graphic and interactive components are independent of each other and there
2031             is a great risk that any coordination is lost.
2032              
2033             This function redefines a page to an "XObject" (the graphic parts), then the
2034             page can be reused in a much better way. Unfortunately there is an important
2035             limitation here. "XObjects" can only have single streams. If the page consists
2036             of many streams, you should concatenate them first. Adobe Acrobat can do that.
2037             (If it is an important file, take a copy of it first. Sometimes the procedure fails.)
2038             Open the document with Acrobat. Then choose the the "TouchUp Text" tool (icon or
2039             from the tools menu). Select a line of text somewhere on the page. Right-click the
2040             mouse. Choose "Attributes".Change font size or anything else, and then you change
2041             it back to the old value. Save the document.
2042             If there was no text on the page, use some other "Touch Up" tool.
2043             Alternatively, use GhostScript to convert multi-stream PDFs (see prForm documentation
2044             for the command).
2045              
2046              
2047             use PDF::Reuse;
2048             use strict;
2049              
2050             prDocDir('C:/temp/doc');
2051             prFile('newForm.pdf');
2052             prField('Mr/Ms', 'Mr');
2053             prField('First_Name', 'Lars');
2054             prDocForm('myFile.pdf');
2055             prFontSize(24);
2056             prText(75, 790, 'This text is added');
2057             prEnd();
2058              
2059             (You can use the output from the example in prJs() as input to this example.
2060             Remember to save that file before closing it.)
2061              
2062             B
2063              
2064             =head2 prExtract - extract an object group
2065              
2066             prExtract ( $pdfFile, $pageNo, $oldInternalName )
2067              
2068             B, a "name"-object. This is the internal name you find in the original file.
2069             Returns a B<$newInternalName> which can be used for "low level" programming. You
2070             have better look at graphObj_pl and modules it has generated for the tutorial,
2071             e.g. thermometer.pm, to see how this function can be used.
2072              
2073             When you call this function, the necessary objects will be copied to your new
2074             PDF-file, and you can refer to them with the new name you receive.
2075              
2076              
2077             =head2 prField - assign a value to an interactive field
2078              
2079             prField ( $fieldName, $value )
2080              
2081             B<$fieldName> is an interactive field in the document you are creating.
2082             It has to be spelled exactly the same way here as it spelled in the document.
2083             B<$value> is what you want to assigned to the field.
2084             Put all your sentences with prField early in your script. After prFile and B
2085             prDoc or prDocForm and of course before prEnd. Each sentence with prField is
2086             translated to JavaScript and merged with old JavaScript
2087              
2088             See prDocForm() for an example
2089              
2090             If you are going to assign a value to a field consisting of several lines, you
2091             can write like this:
2092              
2093             my $string = "This is the first line \r second line \n 3:rd line";
2094             prField('fieldName', $string);
2095              
2096             You can also let '$value' be a snippet of JavaScript-code that assigns something
2097             to the field. Then you have to put 'js:' first in "$value" like this:
2098              
2099             my $sentence = encrypt('This will be decrypted by "unPack"(JavaScript) ');
2100             prField('Interest_9', "js: unPack('$sentence')");
2101              
2102             If you refer to a JavaScript function, it has to be included with prJs first. (The
2103             JavaScript interpreter will simply not be aware of old functions in the PDF-document,
2104             when the initiation is done.)
2105              
2106              
2107             =head2 prFont - set current font
2108              
2109             prFont ( $fontName )
2110              
2111             $fontName is an "external" font name. The parameter is optional.
2112             In list context returns B<$internalName, $externalName, $oldInternalName,
2113             $oldExternalname> The first two variables refer to the current font, the two later
2114             to the font before the change. In scalar context returns b<$internalName>
2115              
2116             If a font wasn't found, Helvetica will be set.
2117             These names are always recognized:
2118             B
2119             Courier-Oblique, Courier-BoldOblique, Helvetica, Helvetica-Bold, Helvetica-Oblique,
2120             Helvetica-BoldOblique> or abbreviated
2121             B.
2122             (B or abbreviated B, also belong to the predefined
2123             fonts, but there is something with them that I really don't understand. You should
2124             print them first on a page, and then use other fonts, otherwise they are not displayed.)
2125              
2126             You can also use a font name from an included page. It has to be spelled exactly as
2127             it is done there. Look in the file and search for "/BaseFont" and the font
2128             name. But take care, e.g. the PDFMaker which converts to PDF from different
2129             Microsoft programs, only defines exactly those letters you can see on the page. You
2130             can use the font, but perhaps some of your letters were not defined.
2131              
2132             In the distribution there is an utility program, 'reuseComponent_pl', which displays
2133             included fonts in a PDF-file and prints some letters. Run it to see the name of the
2134             font and if it is worth extracting.
2135              
2136             use PDF::Reuse;
2137             use strict;
2138             prFile('myFile.pdf');
2139              
2140             ####### One possibility #########
2141              
2142             prFont('Times-Roman'); # Just setting a font
2143             prFontSize(20);
2144             prText(180, 790, "This is a heading");
2145              
2146             ####### Another possibility #######
2147              
2148             my $font = prFont('C'); # Setting a font, getting an
2149             # internal name
2150             prAdd("BT /$font 12 Tf 25 760 Td (This is some other text)Tj ET");
2151             prEnd();
2152              
2153             The example above shows you two ways of setting and using a font. One simple, and
2154             one complicated with a possibility to detail control.
2155              
2156              
2157             =head2 prFontSize - set current font size
2158              
2159             prFontSize ( $size )
2160              
2161             Returns B<$actualSize, $fontSizeBeforetheChange>. Without parameters
2162             prFontSize() sets the size to 12 points, which is default.
2163              
2164             =head2 prForm - use a page from an old document as a form/background
2165              
2166             Alternative 1) You put your parameters in an anonymous hash (only B is really
2167             necessary, the others get default values if not given).
2168              
2169             prForm ( { file => $pdfFile, # template file
2170             page => $page, # page number (of imported template)
2171             adjust => $adjust, # try to fill the media box
2172             effect => $effect, # action to be taken
2173             tolerant => $tolerant, # continue even with an invalid form
2174             x => $x, # $x points from the left
2175             y => $y, # $y points from the bottom
2176             rotate => $degree, # rotate
2177             size => $size, # multiply everything by $size
2178             xsize => $xsize, # multiply horizontally by $xsize
2179             ysize => $ysize } ) # multiply vertically by $ysize
2180             Ex.:
2181             my $internalName = prForm ( {file => 'myFile.pdf',
2182             page => 2 } );
2183              
2184             Alternative 2) You put your parameters in this order
2185              
2186             prForm ( $pdfFile, $page, $adjust, $effect, $tolerant, $x, $y, $degree,
2187             $size, $xsize, $ysize )
2188              
2189              
2190             Anyway the function returns in list context: B<$intName, @BoundingBox,
2191             $numberOfImages>, in scalar context: B<$internalName> of the form.
2192              
2193             B can be a filename, an IO::String object, a filehandle, or a scalar
2194             reference to PDF data in memory.
2195              
2196             if B is excluded 1 is assumed.
2197              
2198             B, could be 1, 2 or 0/nothing. If it is 1, the program tries to adjust the
2199             form to the current media box (paper size) and keeps the proportions unchanged.
2200             If it is 2, the program tries to fill as much of the media box as possible, without
2201             regards to the original proportions.
2202             If this parameter is given, "x", "y", "rotate", "size", "xsize" and "ysize"
2203             will be ignored.
2204              
2205             B can have 3 values: B<'print'>, which is default, loads the page in an internal
2206             table, adds it to the document and prints it to the current page. B<'add'>, loads the
2207             page and adds it to the document. (Now you can "manually" manage the way you want to
2208             print it to different pages within the document.) B<'load'> just loads the page in an
2209             internal table. (You can now take I of a page like fonts and objects and manage
2210             them, without adding all the page to the document.)You don't get any defined
2211             internal name of the form, if you let this parameter be 'load'.
2212              
2213             B can be nothing or something. If it is undefined, you will get an error if your program tries to load
2214             a page which the system cannot really handle, if it e.g. consists of many streams.
2215             If it is set to something, you have to test the first return value $internalName to
2216             know if the function was successful. Look at the program 'reuseComponent_pl' for an
2217             example of usage.
2218              
2219             B where to start along the x-axis (cannot be combined with "adjust")
2220              
2221             B where to start along the y-axis (cannot be combined with "adjust")
2222              
2223             B A degree 0-360 to rotate the form counter-clockwise. (cannot be combined
2224             with "adjust") Often the form disappears out of the media box if degree >= 90.
2225             Then you can move it back with the x and y-parameters. If degree == 90, you can
2226             add the width of the form to x, If degree == 180 add both width and height to x
2227             and y, and if degree == 270 you can add the height to y.
2228              
2229             B can also by one of 'q1', 'q2' or 'q3'. Then the system rotates the form
2230             clockwise 90, 180 or 270 degrees and tries to keep the form within the media box.
2231              
2232             The rotation takes place after the form has been resized or moved.
2233              
2234             Ex. To rotate from portrait (595 x 842 pt) to landscape (842 x 595 pt)
2235              
2236             use PDF::Reuse;
2237             use strict;
2238              
2239             prFile('New_Report.pdf');
2240             prMbox(0, 0, 842, 595);
2241              
2242             prForm({file => 'cert1.pdf',
2243             rotate => 'q1' } );
2244             prEnd();
2245              
2246             The same rotation can be achieved like this:
2247              
2248             use PDF::Reuse;
2249             use strict;
2250              
2251             prFile('New_Report.pdf');
2252             prMbox(0, 0, 842, 595);
2253              
2254             prForm({file => 'cert1.pdf',
2255             rotate => 270,
2256             y => 595 } );
2257             prEnd();
2258              
2259             B multiply every measure by this value (cannot be combined with "adjust")
2260              
2261             B multiply horizontally by this value (cannot be combined with "adjust")
2262              
2263             B multiply vertically by $ysize (cannot be combined with "adjust")
2264              
2265             This function redefines a page to an "XObject" (the graphic parts), then the
2266             page can be reused and referred to as a unit. Unfortunately there is an important
2267             limitation here. "XObjects" can only have single streams. If the page consists
2268             of many streams, you should concatenate them first. Adobe Acrobat can do that.
2269             (If it is an important file, take a copy of it first. Sometimes the procedure fails.)
2270             Open the document with Acrobat. Then choose the "TouchUp Text" tool.
2271             Select a line of text somewhere. Right-click the mouse. Choose "Attributes".
2272             Change font size or anything else, and then you change it back to the old value.
2273             Save the document. You could alternatively save the file as Postscript and redistill
2274             it with the distiller or with Ghost script, but this is a little more risky. You
2275             might loose fonts or something else. Another alternative could be to use prSinglePage().
2276              
2277             Alternatively, GhostScript can be used to convert multi-stream PDFs into
2278             single-stream format compatible with prForm:
2279              
2280             gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/default \
2281             -dNOPAUSE -dQUIET -dBATCH -dDetectDuplicateImages \
2282             -dCompressFonts=true -r150 -sOutputFile=output.pdf input.pdf
2283              
2284              
2285             use PDF::Reuse;
2286             use strict;
2287              
2288             prFile('myFile.pdf');
2289             prForm('best.pdf'); # Takes page No 1
2290             prText(75, 790, 'Dear Mr Gates');
2291             # ...
2292             prPage();
2293             prMbox(0, 0, 900, 960);
2294             my @vec = prForm( { file => 'EUSA.pdf',
2295             adjust => 1 } );
2296             prPage();
2297             prMbox();
2298             prText(35, 760, 'This is the final page');
2299              
2300             # More text ..
2301              
2302             #################################################################
2303             # We want to put a miniature of EUSA.pdf, 35 points from the left
2304             # 85 points up, and in the format 250 X 200 points
2305             #################################################################
2306              
2307             my $xScale = 250 / ($vec[3] - $vec[1]);
2308             my $yScale = 200 / ($vec[4] - $vec[2]);
2309              
2310             prForm ({ file => 'EUSA.pdf',
2311             xsize => $xScale,
2312             ysize => $yScale,
2313             x => 35,
2314             y => 85 });
2315              
2316             prEnd();
2317              
2318             The first prForm(), in the code, is a simple and "normal" way of using the
2319             the function. The second time it is used, the size of the imported page is
2320             changed. It is adjusted to the media box which is current at that moment.
2321             Also data about the form is taken, so you can control more in detail how it
2322             will be displayed.
2323              
2324             =head2 prGetLogBuffer - get the log buffer.
2325              
2326             prGetLogBuffer ()
2327              
2328             returns a B<$buffer> of the log of the current page. (It could be used
2329             e.g. to calculate a MD5-digest of what has been registered that far, instead of
2330             accumulating the single values) A log has to be active, see prLogDir() below
2331              
2332             Look at "Using the template" and "Restoring a document from the log" in the
2333             tutorial for examples of usage.
2334              
2335             =head2 prGraphState - define a graphic state parameter dictionary
2336              
2337             prGraphState ( $string )
2338              
2339             This is a "low level" function. Returns B<$internalName>. The B<$string> has to
2340             be a complete dictionary with initial "<<" and terminating ">>". No syntactical
2341             checks are made. Perhaps you will never have to use this function.
2342              
2343             use PDF::Reuse;
2344             use strict;
2345              
2346             prFile('myFile.pdf');
2347              
2348             ###################################################
2349             # Draw a triangle with Gs0 (automatically defined)
2350             ###################################################
2351              
2352             my $str = "q\n";
2353             $str .= "/Gs0 gs\n";
2354             $str .= "150 700 m\n";
2355             $str .= "225 800 l\n";
2356             $str .= "300 700 l\n";
2357             $str .= "150 700 l\n";
2358             $str .= "S\n";
2359             $str .= "Q\n";
2360             prAdd($str);
2361              
2362             ########################################################
2363             # Define a new graph. state param. dic. and draw a new
2364             # triangle further down
2365             ########################################################
2366              
2367             $str = '<
2368             . '/LW 15/LJ 1/ML 1>>';
2369             my $gState = prGraphState($str);
2370             $str = "q\n";
2371             $str .= "/$gState gs\n";
2372             $str .= "150 500 m\n";
2373             $str .= "225 600 l\n";
2374             $str .= "300 500 l\n";
2375             $str .= "150 500 l\n";
2376             $str .= "S\n";
2377             $str .= "Q\n";
2378             prAdd($str);
2379              
2380             prEnd();
2381              
2382              
2383             =head2 prImage - reuse an image from an old PDF document
2384              
2385             Alternative 1) You put your parameters in an anonymous hash (only B is really
2386             necessary, the others get default values if not given).
2387              
2388             prImage( { file => $pdfFile, # template file
2389             page => $page, # page number
2390             imageNo => $imageNo # image number
2391             adjust => $adjust, # try to fill the media box
2392             effect => $effect, # action to be taken
2393             x => $x, # $x points from the left
2394             y => $y, # $y points from the bottom
2395             rotate => $degree, # rotate
2396             size => $size, # multiply everything by $size
2397             xsize => $xsize, # multiply horizontally by $xsize
2398             ysize => $ysize } ) # multiply vertically by $ysize
2399             Ex.:
2400             prImage( { file => 'myFile.pdf',
2401             page => 10,
2402             imageNo => 2 } );
2403              
2404             Alternative 2) You put your parameters in this order
2405              
2406             prImage ( $pdfFile, [$page, $imageNo, $effect, $adjust, $x, $y, $degree,
2407             $size, $xsize, $ysize] )
2408              
2409             Returns in scalar context B<$internalName> As a list B<$internalName, $width,
2410             $height>
2411              
2412             Assumes that $pageNo and $imageNo are 1, if not specified. If $effect is given and
2413             anything else then 'print', the image will be defined in the document,
2414             but not shown at this moment.
2415              
2416             For all other parameters, look at prForm().
2417              
2418             use PDF::Reuse;
2419             use strict;
2420              
2421             prFile('myFile.pdf');
2422             my @vec = prImage({ file => 'best.pdf',
2423             x => 10,
2424             y => 400,
2425             xsize => 0.9,
2426             ysize => 0.8 } );
2427             prText(35, 760, 'This is some text');
2428             # ...
2429             prPage();
2430             my @vec2 = prImage( { file => 'destiny.pdf',
2431             page => 1,
2432             imageNo => 1,
2433             effect => 'add' } );
2434             prText(25, 760, "There shouldn't be any image on this page");
2435             prPage();
2436             ########################################################
2437             # Now we make both images so that they could fit into
2438             # a box 300 X 300 points, and they are displayed
2439             ########################################################
2440              
2441             prText(25, 800, 'This is the first image :');
2442              
2443             my $xScale = 300 / $vec[1];
2444             my $yScale = 300 / $vec[2];
2445             if ($xScale < $yScale)
2446             { $yScale = $xScale;
2447             }
2448             else
2449             { $xScale = $yScale;
2450             }
2451             prImage({ file => 'best.pdf',
2452             x => 25,
2453             y => 450,
2454             xsize => $xScale,
2455             ysize => $yScale} );
2456              
2457             prText(25, 400, 'This is the second image :');
2458              
2459             $xScale = 300 / $vec2[1];
2460             $yScale = 300 / $vec2[2];
2461             if ($xScale < $yScale)
2462             { $yScale = $xScale;
2463             }
2464             else
2465             { $xScale = $yScale;
2466             }
2467             prImage({ file => 'destiny.pdf',
2468             x => 25,
2469             y => 25,
2470             xsize => $xScale,
2471             ysize => $yScale} );
2472              
2473             prEnd();
2474              
2475             On the first page an image is displayed in a simple way. While the second page
2476             is processed, prImage(), loads an image, but it is not shown here. On the 3:rd
2477             page, the two images are scaled and shown.
2478              
2479             In the distribution there is an utility program, 'reuseComponent_pl', which displays
2480             included images in a PDF-file and their "names".
2481              
2482             =head2 prInit - add JavaScript to be executed at initiation
2483              
2484             prInit ( $string, $duplicateCode )
2485              
2486             B<$string> can be any JavaScript code, but you can only refer to functions included
2487             with prJs. The JavaScript interpreter will not know other functions in the document.
2488             Often you can add new things, but you can't remove or change interactive fields,
2489             because the interpreter hasn't come that far, when initiation is done.
2490              
2491             B<$duplicateCode> is undefined or anything. It duplicates the JavaScript code
2492             which has been used at initiation, so you can look at it from within Acrobat and
2493             debug it. It makes the document bigger. This parameter is B.
2494              
2495             use PDF::Reuse;
2496             use strict;
2497              
2498             prFile('myFile.pdf');
2499             prInit('app.alert("This is displayed when opening the document");');
2500              
2501             prEnd();
2502              
2503              
2504             Remark: Avoid to use "return" in the code you use at initiation. If your user has
2505             downloaded a page with Web Capture, and after that opens a PDF-document where a
2506             JavaScript is run at initiation and that JavaScript contains a return-statement,
2507             a bug occurs. The JavaScript interpreter "exits" instead of returning, the execution
2508             of the JavaScript might finish to early. This is a bug in Acrobat/Reader 5.
2509              
2510              
2511             =head2 prInitVars - initiate global variables and internal tables
2512              
2513             prInitVars(1)
2514              
2515             If you run programs with PDF::Reuse as persistent procedures, you probably need to
2516             initiate global variables. If you have '1' or anything as parameter, internal tables for forms, images, fonts
2517             and interactive functions are B initiated. The module "learns" offset and sizes of
2518             used objects, and can process them faster, but at the same time the size of the
2519             program grows.
2520              
2521             use PDF::Reuse;
2522             use strict;
2523             prInitVars(); # To initiate ALL global variables and tables
2524             # prInitVars(1); # To make it faster, but more memory consuming
2525              
2526             $| = 1;
2527             print STDOUT "Content-Type: application/pdf \n\n";
2528              
2529             prFile(); # To send the document uncatalogued to STDOUT
2530              
2531             prForm('best.pdf');
2532             prText(25, 790, 'Dear Mr. Anders Persson');
2533             # ...
2534             prEnd();
2535              
2536             If you call this function without parameters all global variables, including the
2537             internal tables, are initiated.
2538              
2539              
2540             =head2 prAltJpeg - import a low-res jpeg-image for display and a high-res jpeg-image for printing
2541              
2542             prAltJpeg ( $imageData, $width, $height, $format, $altImageData, $altWidth, $altHeight, $altFormat )
2543              
2544             B<$imageData> contains 1 single jpeg-image. B<$width> and B<$height>
2545             also have to be specified. B<$format> indicates the format the image
2546             data takes: 0 for file, 1 for binary string. B<$altImageData> etc.
2547             follows the same foramt. Returns the B<$internalName>
2548              
2549             use PDF::Reuse;
2550             use Image::Info qw(image_info dim);
2551             use strict;
2552              
2553             my $file = 'myImage.jpg';
2554             my $info = image_info($file);
2555             my ($width, $height) = dim($info); # Get the dimensions
2556             my $colortype = $info->{color_type}; # get color space
2557              
2558             my $alt_file = 'myImage.jpg';
2559             my $alt_info = image_info($alt_file);
2560             my ($alt_width, $alt_height) = dim($alt_info);
2561              
2562             prFile('myFile.pdf');
2563             my $intName = prAltJpeg("$file", # Define the image
2564             $width, # in the document
2565             $height,
2566             0,
2567             "$alt_file",
2568             $alt_width,
2569             $alt_height,
2570             0);
2571              
2572             my $str = "q\n";
2573             $str .= "$width 0 0 $height 10 10 cm\n";
2574             $str .= "/$intName Do\n";
2575             $str .= "Q\n";
2576             prAdd($str);
2577             prEnd();
2578              
2579              
2580             =head2 prJpeg - import a jpeg-image
2581              
2582             prJpeg ( $imageData, $width, $height, $format )
2583              
2584             B<$imageData> contains 1 single jpeg-image. B<$width> and B<$height>
2585             also have to be specified. B<$format> indicates the format the image
2586             data takes: 0 for file, 1 for binary string. Returns the B<$internalName>
2587              
2588             use PDF::Reuse;
2589             use Image::Info qw(image_info dim);
2590             use strict;
2591              
2592             my $file = 'myImage.jpg';
2593             my $info = image_info($file);
2594             my ($width, $height) = dim($info); # Get the dimensions
2595              
2596             prFile('myFile.pdf');
2597             my $intName = prJpeg("$file", # Define the image
2598             $width, # in the document
2599             $height,
2600             0);
2601              
2602             my $str = "q\n";
2603             $str .= "$width 0 0 $height 10 10 cm\n";
2604             $str .= "/$intName Do\n";
2605             $str .= "Q\n";
2606             prAdd($str);
2607             prEnd();
2608              
2609             This is a little like an extra or reserve routine to add images to the document.
2610             The most simple way is to use prImage()
2611              
2612             =head2 prJs - add JavaScript
2613              
2614             prJs ( $string|$fileName )
2615              
2616             To add JavaScript to your new document. B<$string> has to consist only of
2617             JavaScript functions: function a (..){ ... } function b (..) { ...} and so on
2618             If B<$string> doesn't contain '{', B<$string> is interpreted as a filename.
2619             In that case the file has to consist only of JavaScript functions.
2620              
2621             B
2622              
2623             =head2 prLink - add a hyper link
2624              
2625             prLink( { page => $pageNo, # Starting with 1 !
2626             x => $x,
2627             y => $y,
2628             width => $width,
2629             height => $height,
2630             URI => $URI } );
2631              
2632             You can also call prLink like this:
2633              
2634             prLink($page, $x, $y, $width, $height, $URI);
2635              
2636             You have to put prLink B
2637             is created>. The links are created at the page-breaks. If the page is already
2638             created, no new link will be inserted.
2639              
2640             Here is an example where the links of a 4 page document are preserved, and a link is
2641             added at the end of the document. We assume that there is some suitable text at that
2642             place (x = 400, y = 350):
2643              
2644             use strict;
2645             use PDF::Reuse;
2646              
2647             prFile('test.pdf');
2648              
2649             prLink( {page => 4,
2650             x => 400,
2651             y => 350,
2652             width => 105,
2653             height => 15,
2654             URI => 'http://www.purelyInvented.com/info.html' } );
2655              
2656             prDoc('fourPages.pdf');
2657              
2658             prEnd();
2659              
2660             ( If you are creating each page of a document separately, you can also use 'hyperLink'
2661             from PDF::Reuse::Util. Then you get an external text in Helvetica-Oblique, underlined
2662             and in blue.
2663              
2664             use strict;
2665             use PDF::Reuse;
2666             use PDF::Reuse::Util;
2667              
2668             prFile('test.pdf');
2669             prForm('template.pdf', 5);
2670             my ($from, $pos) = prText(25, 700, 'To get more information ');
2671              
2672             $pos = hyperLink( $pos, 700, 'Press this link',
2673             'http://www.purelyInvented.com/info.html' );
2674             ($from, $pos) = prText( $pos, 700, ' And get connected');
2675             prEnd();
2676              
2677             'hyperLink' has a few parameters: $x, $y, $textToBeShown, $hyperLink and
2678             $fontSize (not shown in the example). It returns current x-position. )
2679              
2680             =head2 prLog - add a string to the log
2681              
2682             prLog ( $string )
2683              
2684             Adds whatever you want to the current log (a reference No, a commentary, a tag ?)
2685             A log has to be active see prLogDir()
2686              
2687             Look at "Using the template" and "Restoring the document from the log" in
2688             the tutorial for an example.
2689              
2690             =head2 prLogDir - set directory for the log
2691              
2692             prLogDir ( $directory )
2693              
2694             Sets a directory for the logs and activates the logging.
2695             A little log file is created for each PDF-file. Normally it should be much, much
2696             more compact then the PDF-file, and it should be possible to restore or verify
2697             a document with the help of it. (Of course you could compress or store the logs in a
2698             database to save even more space.)
2699              
2700             use PDF::Reuse;
2701             use strict;
2702              
2703             prDocDir('C:/temp/doc');
2704             prLogDir('C:/run');
2705              
2706             prFile('myFile.pdf');
2707             prForm('best.pdf');
2708             prText(25, 790, 'Dear Mr. Anders Persson');
2709             # ...
2710             prEnd();
2711              
2712             In this example a log file with the name 'myFile.pdf.dat' is created in the
2713             directory 'C:\run'. If that directory doesn't exist, the system tries to create it.
2714             (But, just as mkdir does, it only creates the last level in a directory tree.)
2715              
2716             =head2 prMbox - define the format (MediaBox) for a new page.
2717              
2718             prMbox ( $lowerLeftX, $lowerLeftY, $upperRightX, $upperRightY )
2719              
2720             If the function or the parameters are missing, they are set to 0, 0, 595, 842 points respectively.
2721             Only for new pages. Pages created with prDoc and prSinglePage keep their media boxes unchanged.
2722              
2723             See prForm() for an example.
2724              
2725              
2726             =head2 prPage - create/insert a page
2727              
2728             prPage ($noLog)
2729              
2730             Don't use the optional parameter, it is only used internally, not to clutter the log,
2731             when automatic page breaks are made.
2732              
2733              
2734             See prForm() for an example.
2735              
2736             =head2 prSinglePage - take single pages, one by one, from an old document
2737              
2738             prSinglePage($file, $pageNumber)
2739              
2740             $pageNumber is optional. If not given, next page is assumed
2741             Returns number of remaining pages.
2742             This function is a variant of prDoc for single pages, with the addition that it
2743             has a counter of last page read, and total number of pages of the old document,
2744             so it can be used to loop through a document.
2745              
2746              
2747             To add a form, image and page number to each page of a document
2748             (The document Battery.pdf is cropped so each page is fairly small) You could also have
2749             used prDoc, but only if you knew in advance the number of pages of the old document
2750              
2751             use PDF::Reuse;
2752             use PDF::Reuse::Util;
2753             use strict;
2754              
2755             prFile('test.pdf');
2756              
2757             my $pageNumber = 0;
2758             my $left = 1; # Every valid PDF-document has at least 1 page,
2759             # so that can be assumed
2760              
2761             while ($left)
2762             { $pageNumber++;
2763             prForm( { file =>'Words.pdf',
2764             page => 5,
2765             x => 150,
2766             y => 150} );
2767              
2768             prImage( { file =>'Media.pdf',
2769             page => 6,
2770             imageNo => 1,
2771             x => 450,
2772             y => 450 } );
2773             blackText();
2774             prText( 360, 250, $pageNumber);
2775             $left = prSinglePage('Battery.pdf');
2776             }
2777              
2778             prEnd;
2779              
2780             prSinglePage creates a new page from an old document and adds new content (to the array of
2781             streams of that page). Most often you can add new contents to the page like the example above,
2782             and it works fine, but sometimes you get surprises. There can e.g. be instructions in the earlier
2783             contents to make filling color white, and then you will probably not see added new text. That
2784             is why PDF::Reuse::Util::blackText() is used in the example. There can be other instructions
2785             like moving or rotating the user space. Also new contents can end up outside the crop-box.
2786             Of course all new programs should be tested. If prSinglePage can't be used, try to use prForm
2787             followed by prPage instead.
2788              
2789              
2790             =head2 prStrWidth - calculate the string width
2791              
2792             prStrWidth($string, $font, $fontSize)
2793              
2794             Returns string width in points.
2795             Should be used in conjunction with one of these predefined fonts of Acrobat/Reader:
2796             Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic, Courier, Courier-Bold, Courier-Oblique,
2797             Courier-BoldOblique, Helvetica, Helvetica-Bold, Helvetica-Oblique,
2798             Helvetica-BoldOblique or with a TrueType font embedded with prTTFont. If some other font is
2799             given, Helvetica is used, and the returned value will at the best be approximate.
2800              
2801             =head2 prText - add a text-string
2802              
2803             prText ( $x, $y, $string, $align, $rotation )
2804              
2805             Puts B<$string> at position B<$x, $y>
2806             Returns 1 in scalar context. Returns ($xFrom, $xTo) in list context. $xTo will not
2807             be defined together with a rotation. prStrWidth() is used to calculate the length of the
2808             strings, so only the predefined fonts together with Acrobat/Reader, or embedded TrueType
2809             fonts will give reliable values for $xTo.
2810              
2811             $align can be 'left' (= default), 'center' or 'right'. The parameter is optional.
2812              
2813             $rotation can be a degree 0 - 360, 'q1', 'q2' or 'q3'. Also optional.
2814              
2815             Current font and font size are used. (If you use prAdd() before this function,
2816             many other things could also influence the text.)
2817              
2818             use strict;
2819             use PDF::Reuse;
2820              
2821             prFile('test.pdf');
2822              
2823             #####################################
2824             # Use a "curser" ($pos) along a line
2825             #####################################
2826              
2827             my ($from, $pos) = prText(25, 800, 'First write this. ');
2828             ($from, $pos) = prText($pos, 800, 'Then write this. ');
2829             prText($pos, 800, 'Finally write this.');
2830              
2831             #####################################
2832             # Right adjust and center sentences
2833             #####################################
2834              
2835             prText( 200, 750, 'A short sentence', 'right');
2836             prText( 200, 735, 'This is a longer sentence', 'right');
2837             prText( 200, 720, 'A word', 'right');
2838              
2839             prText( 200, 705, 'Centered around a point 200 points from the left', 'center');
2840             prText( 200, 690, 'The same center', 'center');
2841             prText( 200, 675, '->.<-', 'center');
2842              
2843             ############
2844             # Rotation
2845             ############
2846              
2847             prText( 200, 550, ' Rotate 0 degrees','', 0);
2848             prText( 200, 550, ' Rotate 60 degrees','', 60);
2849             prText( 200, 550, ' Rotate 120 degrees','', 120);
2850             prText( 200, 550, ' Rotate 180 degrees','', 180);
2851             prText( 200, 550, ' Rotate 240 degrees','', 240);
2852             prText( 200, 550, ' Rotate 300 degrees','', 300);
2853              
2854             prText( 400, 430, 'Rotate 90 degrees clock-wise','','q1');
2855             prText( 400, 430, 'Rotate 180 degrees clock-wise','', 'q2');
2856             prText( 400, 430, 'Rotate 270 degrees clock-wise','', 'q3');
2857              
2858             ##########################
2859             # Rotate and right adjust
2860             ##########################
2861              
2862             prText( 200, 230, 'Rotate 90 degrees clock-wise ra->','right','q1');
2863             prText( 200, 230, 'Rotate 180 degrees clock-wise ra->','right', 'q2');
2864             prText( 200, 230, 'Rotate 270 degrees clock-wise ra->','right', 'q3');
2865              
2866             prEnd();
2867              
2868             =head2 prTTFont - select and embed a TrueType font
2869              
2870             prTTFont ( "/path/to/font/file.ttf" )
2871              
2872             This function is equivalent to C except that rather than restricting
2873             you to the list of core built-in fonts, it allows you to select an external
2874             TrueType font file and have it embedded in your PDF document. Using TrueType
2875             fonts also enables the C function to accept UTF-8 strings, which allows
2876             you to use characters outside the Mac-Roman/Win-ANSI character sets used by the
2877             built-in fonts.
2878              
2879             You can specify the same font path multiple times in one document and only one
2880             copy will be embedded. Alternatively, C returns an identifier which
2881             can be used to select the same font again:
2882              
2883             my $arial = prTTFont('/path/to/Arial.ttf');
2884             prFontSize(20);
2885             prText(20, 700, 'Some text in Arial');
2886             #
2887             # ... later ...
2888             #
2889             prPage();
2890             prTTFont($arial);
2891             prFontSize(12);
2892             prText(20, 700, 'Some more text in Arial');
2893             #
2894             # to pass a UTF8 string to prText
2895             #
2896             prText(20, 675, "T\x{113}n\x{101} koutou"); # T?n? Koutou
2897              
2898             In list context this function returns C<$internalName>, C<$externalName>,
2899             C<$oldInternalName>, C<$oldExternalname>. The first two variables refer to the
2900             current font, the last two refer to the font before the change. In scalar
2901             context only C<$internalName> is returned.
2902              
2903             Note: To use this function, you must have the L and L
2904             modules installed.
2905              
2906              
2907             =head1 INTERNAL OR DEPRECATED FUNCTIONS
2908              
2909             =over 2
2910              
2911             =item prBar - define and paint bars for bar fonts
2912              
2913             prBar ($x, $y, $string)
2914              
2915             Prints a bar font pattern at the current page.
2916             Returns $internalName for the font.
2917             $x and $y are coordinates in points and $string should consist of the characters
2918             '0', '1' and '2' (or 'G'). '0' is a white bar, '1' is a dark bar. '2' and 'G' are
2919             dark, slightly longer bars, guard bars.
2920             You can use e.g. GD::Barcode or one module in that group to calculate the bar code
2921             pattern. prBar "translates" the pattern to white and black bars.
2922              
2923             use PDF::Reuse;
2924             use GD::Barcode::Code39;
2925             use strict;
2926              
2927             prFile('myFile.pdf');
2928             my $oGdB = GD::Barcode::Code39->new('JOHN DOE');
2929             my $sPtn = $oGdB->barcode();
2930             prBar(100, 600, $sPtn);
2931             prEnd();
2932              
2933             Internally the module uses a font for the bars, so you might want to change the font size before calling
2934             this function. In that case, use prFontSize() .
2935             If you call this function without arguments it defines the bar font but does
2936             not write anything to the current page.
2937              
2938             B
2939             Look at that module!
2940              
2941             =item prCid - define time stamp/check id
2942              
2943             prCid ( $timeStamp )
2944              
2945             An internal function. Don't bother about it. It is used in automatic
2946             routines when you want to restore a document. It gives modification time of
2947             the next PDF-file or JavaScript.
2948             See "Restoring a document from the log" in the tutorial for more about the
2949             time stamp
2950              
2951              
2952              
2953             =item prId - define id-string of a PDF document
2954              
2955             prId ( $string )
2956              
2957             An internal function. Don't bother about it. It is used e.g. when a document is
2958             restored and an id has to be set, not calculated.
2959              
2960             =item prIdType - define id-type
2961              
2962             prIdType ( $string )
2963              
2964             An internal function. Avoid using it. B<$string> could be "Rep" for replace or
2965             "None" to avoid calculating an id.
2966              
2967             Normally you don't use this function. Then an id is calculated with the help of
2968             Digest::MD5::md5_hex and some data from the run.
2969              
2970              
2971             =item prTouchUp - make changes and reuse more difficult
2972              
2973             prTouchUp (1);
2974              
2975             By default and after you have issued prTouchUp(1), you can change the document
2976             with the TouchUp tool from within Acrobat.
2977             If you want to switch off this possibility, you use prTouchUp() without any
2978             parameter. Then the user shouldn't be able to change anything graphic by mistake.
2979             He has to do something premeditated and perhaps with a little effort.
2980             He could still save it as Postscript and redistill, or he could remove or add single pages.
2981             (Here is a strong reason why the log files, and perhaps also check sums, are needed.
2982             It would be very difficult to forge a document unless the forger also has access to your
2983             computer and knows how the check sums are calculated.)
2984              
2985             B It creates an
2986             extra level within the PDF-documents . Use this function for your final documents.
2987              
2988             See "Using the template" in the tutorial for an example.
2989              
2990             This function works for pages created with prPage, but mot with prDoc and prSinglePage,
2991             So it is more or less deprecated as these function have developed.
2992              
2993             (To encrypt your documents: use the batch utility within Acrobat)
2994              
2995              
2996             =item prVers - check version of log and program
2997              
2998             prVers ( $versionNo )
2999              
3000             To check version of this module in case a document has to be
3001             restored.
3002              
3003             =back
3004              
3005             =head1 SEE ALSO
3006              
3007             PDF::Reuse::Tutorial
3008             PDF::Reuse::Barcode
3009             PDF::Reuse::OverlayChart
3010              
3011             To program with PDF-operators, look at "The PDF-reference Manual" which probably
3012             is possible to download from http://partners.adobe.com/asn/tech/pdf/specifications.jsp
3013             Look especially at chapter 4 and 5, Graphics and Text, and the Operator summary.
3014              
3015             Technical Note # 5186 contains the "Acrobat JavaScript Object Specification". I
3016             downloaded it from http://partners.adobe.com/asn/developer/technotes/acrobatpdf.html
3017              
3018             If you are serious about producing PDF-files, you probably need Adobe Acrobat sooner
3019             or later. It has a price tag. Other good programs are GhostScript and GSview.
3020             I got them via http://www.cs.wisc.edu/~ghost/index.html Sometimes they can replace Acrobat.
3021             A nice little detail is e.g. that GSview shows the x- and y-coordinates better then Acrobat. If you need to convert HTML-files to PDF, HTMLDOC is a possible tool. Download it from
3022             http://www.easysw.com . A simple tool for vector graphics is Mayura Draw 2.04, download
3023             it from http://www.mayura.com. It is free. I have used it to produce the graphic
3024             OO-code in the tutorial. It produces postscript which the Acrobat Distiller (you get it together with Acrobat)
3025             or Ghostscript can convert to PDF.(The commercial product, Mayura Draw 4.01 or something
3026             higher can produce PDF-files straight away)
3027              
3028             If you want to import jpeg-images, you might need
3029              
3030             Image::Info
3031              
3032             To get definitions for e.g. colors, take them from
3033              
3034             PDF::API2::Util
3035              
3036             =head1 LIMITATIONS
3037              
3038             Meta data, info and many other features of the PDF-format have not been
3039             implemented in this module.
3040              
3041             Many things can be added afterwards, after creating the files. If you e.g. need
3042             files to be encrypted, you can use a standard batch routine within Adobe Acrobat.
3043              
3044             =head1 THANKS TO
3045              
3046             Martin Langhoff, Matisse Enzer, Yunliang Yu and others who have contributed with code, suggestions and error
3047             reports.
3048              
3049             Grant McLean has implemented font embedding by grafting Font::TTF and
3050             Text::PDF::TTFont0 onto the PDF::Reuse API. He has written the embedded packages PDF::Reuse::DocProxy
3051             and PDF::Reuse::TTFont.
3052              
3053             The functionality of prDoc and prSinglePage to include new contents was developed for a
3054             specific task with support from the Electoral Enrolment Centre, Wellington, New Zealand
3055              
3056             =head1 MAILING LIST
3057              
3058             http://groups.google.com/group/PDF-Reuse
3059              
3060             =head1 AUTHOR
3061              
3062             Lars Lundberg larslund@cpan.org
3063             Chris Nighswonger cnighs@cpan.org
3064              
3065             =head1 COPYRIGHT
3066              
3067             Copyright (C) 2003 - 2004 Lars Lundberg, Solidez HB.
3068             Copyright (C) 2005 Karin Lundberg.
3069             Copyright (C) 2006 - 2010 Lars Lundberg, Solidez HB.
3070             Copyright (C) 2010 - 2019 Chris Nighswonger
3071             This program is free software; you can redistribute it and/or
3072             modify it under the same terms as Perl itself.
3073              
3074             =head1 DISCLAIMER
3075              
3076             You get this module free as it is, but nothing is guaranteed to work, whatever
3077             implicitly or explicitly stated in this document, and everything you do,
3078             you do at your own risk - I will not take responsibility
3079             for any damage, loss of money and/or health that may arise from the use of this module.
3080              
3081             =cut
3082              
3083             sub prSinglePage
3084 0     0 1 0 { my $infil = shift;
3085 0         0 my $pageNumber = shift;
3086              
3087 0 0       0 if (! defined $pageNumber)
3088             { $behandlad{$infil}->{pageNumber} = 0
3089 0 0       0 unless (defined $behandlad{$infil}->{pageNumber});
3090 0         0 $pageNumber = $behandlad{$infil}->{pageNumber} + 1;
3091             }
3092              
3093 0         0 my ($sida, $Names, $AARoot, $AcroForm) = analysera($infil, $pageNumber, $pageNumber, 1);
3094 0 0 0     0 if (($Names) || ($AARoot) || ($AcroForm))
      0        
3095 0         0 { $NamesSaved = $Names;
3096 0         0 $AARootSaved = $AARoot;
3097 0         0 $AcroFormSaved = $AcroForm;
3098 0         0 $interActive = 1;
3099             }
3100 0 0       0 if (defined $sida)
3101 0         0 { $behandlad{$infil}->{pageNumber} = $pageNumber;
3102             }
3103 0 0       0 if ($runfil)
3104 0         0 { $infil = prep($infil);
3105 0         0 $log .= "prSinglePage~$infil~$pageNumber\n";
3106             }
3107 0 0       0 if (! $pos)
3108 0         0 { errLog("No output file, you have to call prFile first");
3109             }
3110 0         0 return $sida;
3111              
3112             }
3113              
3114              
3115              
3116             sub prLink
3117 0     0 1 0 { my %link;
3118 0         0 my $param = shift;
3119 0 0       0 if (ref($param) eq 'HASH')
3120 0   0     0 { $link{page} = $param->{'page'} || -1;
3121 0   0     0 $link{x} = $param->{'x'} || 100;
3122 0   0     0 $link{y} = $param->{'y'} || 100;
3123 0   0     0 $link{width} = $param->{width} || 75;
3124 0   0     0 $link{height} = $param->{height} || 15;
3125 0         0 $link{v} = $param->{URI};
3126 0   0     0 $link{s} = $param->{s} || "URI";
3127             }
3128             else
3129 0   0     0 { $link{page} = $param || -1;
3130 0   0     0 $link{x} = shift || 100;
3131 0   0     0 $link{y} = shift || 100;
3132 0   0     0 $link{width} = shift || 75;
3133 0   0     0 $link{height} = shift || 15;
3134 0         0 $link{v} = shift;
3135 0   0     0 $link{s} = shift || "URI";
3136             }
3137              
3138 0 0       0 if (! $pos)
3139 0         0 { errLog("No output file, you have to call prFile first");
3140             }
3141              
3142 0 0       0 if ($runfil)
3143 0         0 { $log .= "Link~$link{page}~$link{x}~$link{y}~$link{width}~"
3144             . "$link{height}~$link{v}~$link{s}\n";
3145             }
3146              
3147 0 0       0 if ($link{v})
3148 0         0 { push @{$links{$link{page}}}, \%link;
  0         0  
3149             }
3150 0         0 1;
3151             }
3152              
3153             sub mergeLinks
3154 0     0 0 0 { my $tSida = $sida + 1;
3155 0         0 my $rad;
3156 0         0 my ($linkObject, $linkObjectNo);
3157 0         0 for my $link (@{$links{'-1'}}, @{$links{$tSida}} )
  0         0  
  0         0  
3158 0         0 { my $x2 = $link->{x} + $link->{width};
3159 0         0 my $y2 = $link->{y} + $link->{height};
3160 0 0       0 if (exists $links{$link->{v}})
3161 0         0 { $linkObjectNo = $links{$link->{v}};
3162             }
3163             else
3164 0         0 { $objNr++;
3165 0         0 $objekt[$objNr] = $pos;
3166 0         0 my $v_n;
3167 0         0 my $v_v = '('.$link->{v}.')';
3168 0 0       0 if ($link->{s} eq 'GoTo')
    0          
    0          
    0          
    0          
    0          
3169 0         0 { $v_n = "D";
3170             }
3171             elsif ($link->{s} eq 'GoToA')
3172 0         0 { $link->{s} = 'GoTo';
3173 0         0 $v_n = 'D';
3174 0         0 $v_v = $link->{v};
3175             }
3176 0         0 elsif ($link->{s} eq 'Launch') {$v_n = 'F';}
3177 0         0 elsif ($link->{s} eq 'SubmitForm') {$v_n = 'F';}
3178             elsif ($link->{s} eq 'Named')
3179 0         0 { $v_n = 'N';
3180 0         0 $v_v = $link->{v};
3181             }
3182 0         0 elsif ($link->{s} eq 'JavaScript') {$v_n = "JS";}
3183             else
3184 0         0 { $v_n = $link->{s};
3185             }
3186 0         0 $rad = "$objNr 0 obj<{s}/$v_n$v_v>>endobj\n";
3187 0         0 $linkObjectNo = $objNr;
3188 0         0 $links{$link->{v}} = $objNr;
3189 0         0 $pos += syswrite UTFIL, $rad;
3190             }
3191 0         0 $rad = "/Subtype/Link/Rect[$link->{x} $link->{y} "
3192             . "$x2 $y2]/A $linkObjectNo 0 R/Border[0 0 0]";
3193 0 0       0 if (exists $links{$rad})
3194 0         0 { push @annots, $links{$rad};
3195             }
3196             else
3197 0         0 { $objNr++;
3198 0         0 $objekt[$objNr] = $pos;
3199 0         0 $links{$rad} = $objNr;
3200 0         0 $rad = "$objNr 0 obj<<$rad>>endobj\n";
3201 0         0 $pos += syswrite UTFIL, $rad;
3202 0         0 push @annots, $objNr;
3203             }
3204             }
3205 0         0 @{$links{'-1'}} = ();
  0         0  
3206 0         0 @{$links{$tSida}} = ();
  0         0  
3207 0         0 $objNr++;
3208 0         0 $objekt[$objNr] = $pos;
3209 0         0 $rad = "$objNr 0 obj[\n";
3210 0         0 for (@annots)
3211 0         0 { $rad .= "$_ 0 R\n";
3212             }
3213 0         0 $rad .= "]endobj\n";
3214 0         0 $pos += syswrite UTFIL, $rad;
3215 0         0 @annots = ();
3216 0         0 return $objNr;
3217             }
3218              
3219              
3220             sub prBookmark
3221 0     0 1 0 { my $param = shift;
3222 0 0       0 if (! ref($param))
3223 0         0 { $param = eval ($param);
3224             }
3225 0 0       0 if (! ref($param))
3226 0         0 { return undef;
3227             }
3228 0 0       0 if (! $pos)
3229 0         0 { errLog("No output file, you have to call prFile first");
3230             }
3231 0 0       0 if (ref($param) eq 'HASH')
3232 0         0 { push @bookmarks, $param;
3233             }
3234             else
3235 0         0 { push @bookmarks, (@$param);
3236             }
3237 0 0       0 if ($runfil)
3238 0         0 { local $Data::Dumper::Indent = 0;
3239 0         0 $param = Dumper($param);
3240 0         0 $param =~ s/^\$VAR1 = //;
3241 0         0 $param = prep($param);
3242 0         0 $log .= "Bookmark~$param\n";
3243             }
3244 0         0 return 1;
3245             }
3246              
3247             sub ordnaBookmarks
3248 0     0 0 0 { my ($first, $last, $me, $entry, $rad);
3249 0         0 $totalCount = 0;
3250 0 0       0 if (defined $objekt[$objNr])
3251 0         0 { $objNr++;
3252             }
3253 0         0 $me = $objNr;
3254              
3255 0         0 my $number = $#bookmarks;
3256 0         0 for (my $i = 0; $i <= $number ; $i++)
3257 0         0 { my %hash = %{$bookmarks[$i]};
  0         0  
3258 0         0 $objNr++;
3259 0         0 $hash{'this'} = $objNr;
3260 0 0       0 if ($i == 0)
3261 0         0 { $first = $objNr;
3262             }
3263 0 0       0 if ($i == $number)
3264 0         0 { $last = $objNr;
3265             }
3266 0 0       0 if ($i < $number)
3267 0         0 { $hash{'next'} = $objNr + 1;
3268             }
3269 0 0       0 if ($i > 0)
3270 0         0 { $hash{'previous'} = $objNr - 1;
3271             }
3272 0         0 $bookmarks[$i] = \%hash;
3273             }
3274              
3275 0         0 for $entry (@bookmarks)
3276 0         0 { my %hash = %{$entry};
  0         0  
3277 0         0 descend ($me, %hash);
3278             }
3279              
3280 0         0 $objekt[$me] = $pos;
3281              
3282 0         0 $rad = "$me 0 obj<<";
3283 0         0 $rad .= "/Type/Outlines";
3284 0         0 $rad .= "/Count $totalCount";
3285 0 0       0 if (defined $first)
3286 0         0 { $rad .= "/First $first 0 R";
3287             }
3288 0 0       0 if (defined $last)
3289 0         0 { $rad .= "/Last $last 0 R";
3290             }
3291 0         0 $rad .= ">>endobj\n";
3292 0         0 $pos += syswrite UTFIL, $rad;
3293              
3294 0         0 return $me;
3295              
3296             }
3297              
3298             sub descend
3299 0     0 0 0 { my ($parent, %entry) = @_;
3300 0         0 my ($first, $last, $count, $me, $rad, $jsObj);
3301 0 0       0 if (! exists $entry{'close'})
3302 0         0 { $totalCount++; }
3303 0         0 $count = $totalCount;
3304 0         0 $me = $entry{'this'};
3305 0 0       0 if (exists $entry{'kids'})
3306 0 0       0 { if (ref($entry{'kids'}) eq 'ARRAY')
3307 0         0 { my @array = @{$entry{'kids'}};
  0         0  
3308 0         0 my $number = $#array;
3309 0         0 for (my $i = 0; $i <= $number ; $i++)
3310 0         0 { $objNr++;
3311 0         0 $array[$i]->{'this'} = $objNr;
3312 0 0       0 if ($i == 0)
3313 0         0 { $first = $objNr;
3314             }
3315 0 0       0 if ($i == $number)
3316 0         0 { $last = $objNr;
3317             }
3318              
3319 0 0       0 if ($i < $number)
3320 0         0 { $array[$i]->{'next'} = $objNr + 1;
3321             }
3322 0 0       0 if ($i > 0)
3323 0         0 { $array[$i]->{'previous'} = $objNr - 1;
3324             }
3325 0 0       0 if (exists $entry{'close'})
3326 0         0 { $array[$i]->{'close'} = 1;
3327             }
3328             }
3329              
3330 0         0 for my $element (@array)
3331 0         0 { descend($me, %{$element})
  0         0  
3332             }
3333             }
3334             else # a hash
3335 0         0 { my %hash = %{$entry{'kids'}};
  0         0  
3336 0         0 $objNr++;
3337 0         0 $hash{'this'} = $objNr;
3338 0         0 $first = $objNr;
3339 0         0 $last = $objNr;
3340 0         0 descend($me, %hash)
3341             }
3342             }
3343              
3344              
3345 0         0 $objekt[$me] = $pos;
3346 0         0 $rad = "$me 0 obj<<";
3347 0 0       0 if (exists $entry{'text'})
3348 0         0 { $rad .= "/Title ($entry{'text'})";
3349             }
3350 0         0 $rad .= "/Parent $parent 0 R";
3351 0 0       0 if (defined $jsObj)
3352 0         0 { $rad .= "/A $jsObj 0 R";
3353             }
3354 0 0       0 if (exists $entry{'act'})
3355 0         0 { my $code = $entry{'act'};
3356 0 0       0 if ($code =~ m/(\d+)/os)
3357             {
3358 0         0 $code = $1;
3359             }
3360 0         0 $rad .= "/Dest [$code /XYZ null null null] ";
3361             }
3362 0 0       0 if (exists $entry{'previous'})
3363 0         0 { $rad .= "/Prev $entry{'previous'} 0 R";
3364             }
3365 0 0       0 if (exists $entry{'next'})
3366 0         0 { $rad .= "/Next $entry{'next'} 0 R";
3367             }
3368 0 0       0 if (defined $first)
3369 0         0 { $rad .= "/First $first 0 R";
3370             }
3371 0 0       0 if (defined $last)
3372 0         0 { $rad .= "/Last $last 0 R";
3373             }
3374 0 0       0 if ($count != $totalCount)
3375 0         0 { $count = $totalCount - $count;
3376 0         0 $rad .= "/Count $count";
3377             }
3378 0 0       0 if (exists $entry{'color'})
3379 0         0 { $rad .= "/C [$entry{'color'}]";
3380             }
3381 0 0       0 if (exists $entry{'style'})
3382 0         0 { $rad .= "/F $entry{'style'}";
3383             }
3384              
3385 0         0 $rad .= ">>endobj\n";
3386 0         0 $pos += syswrite UTFIL, $rad;
3387             }
3388              
3389             sub prInitVars
3390 0     0 1 0 { my $exit = shift;
3391 0         0 $genLowerX = 0;
3392 0         0 $genLowerY = 0;
3393 0         0 $genUpperX = 595,
3394             $genUpperY = 842;
3395 0         0 $fontSize = 12;
3396 0         0 ($utfil, $slutNod, $formCont, $imSeq,
3397             $page, $sidObjNr, $interActive, $NamesSaved, $AARootSaved, $AAPageSaved,
3398             $root, $AcroFormSaved, $id, $ldir, $checkId, $formNr, $imageNr,
3399             $filnamn, $interAktivSida, $taInterAkt, $type, $runfil, $checkCs,
3400             $confuseObj, $compress,$pos, $fontNr, $objNr,
3401             $defGState, $gSNr, $pattern, $shading, $colorSpace) = '';
3402              
3403 0 0       0 if ($docProxy)
3404 0         0 { for my $obj (values %{ $docProxy->{' objcache'} })
  0         0  
3405 0 0       0 { if ($obj->isa('Text::PDF::TTFont0'))
3406 0 0       0 { if (my $font = delete $obj->{' font'})
3407 0         0 { $font->release();
3408             }
3409 0         0 $obj->release();
3410             }
3411             }
3412 0         0 undef $docProxy;
3413             }
3414              
3415 0         0 (@kids, @counts, @formBox, @objekt, @parents, @aktuellFont, @skapa,
3416             @jsfiler, @inits, @bookmarks, @annots) = ();
3417              
3418 0         0 ( %resurser, %objRef, %nyaFunk,%oldObject, %unZipped,
3419             %sidFont, %sidXObject, %sidExtGState, %font, %fields, %script,
3420             %initScript, %sidPattern, %sidShading, %sidColorSpace, %knownToFile,
3421             %processed, %dummy) = ();
3422              
3423 0         0 $stream = '';
3424 0         0 $idTyp = '';
3425 0         0 $ddir = '';
3426 0         0 $log = '';
3427              
3428 0 0       0 if ($exit)
3429 0         0 { return 1;
3430             }
3431              
3432 0         0 ( %form, %image, %fontSource, %intAct) = ();
3433              
3434 0         0 return 1;
3435             }
3436              
3437             ####################
3438             # Behandla en bild
3439             ####################
3440              
3441             sub prImage
3442 0     0 1 0 { my $param = shift;
3443 0         0 my ($infil, $sidnr, $bildnr, $effect, $adjust, $x, $y, $size, $xsize,
3444             $ysize, $rotate);
3445              
3446 0 0       0 if (ref($param) eq 'HASH')
3447 0         0 { $infil = $param->{'file'};
3448 0   0     0 $sidnr = $param->{'page'} || 1;
3449 0   0     0 $bildnr = $param->{'imageNo'} || 1;
3450 0   0     0 $effect = $param->{'effect'} || 'print';
3451 0   0     0 $adjust = $param->{'adjust'} || '';
3452 0   0     0 $x = $param->{'x'} || 0;
3453 0   0     0 $y = $param->{'y'} || 0;
3454 0   0     0 $rotate = $param->{'rotate'} || 0;
3455 0   0     0 $size = $param->{'size'} || 1;
3456 0   0     0 $xsize = $param->{'xsize'} || 1;
3457 0   0     0 $ysize = $param->{'ysize'} || 1;
3458             }
3459             else
3460 0         0 { $infil = $param;
3461 0   0     0 $sidnr = shift || 1;
3462 0   0     0 $bildnr = shift || 1;
3463 0   0     0 $effect = shift || 'print';
3464 0   0     0 $adjust = shift || '';
3465 0   0     0 $x = shift || 0;
3466 0   0     0 $y = shift || 0;
3467 0   0     0 $rotate = shift || 0;
3468 0   0     0 $size = shift || 1;
3469 0   0     0 $xsize = shift || 1;
3470 0   0     0 $ysize = shift || 1;
3471             }
3472              
3473 0         0 my ($refNr, $inamn, $bildIndex, $xc, $yc, $xs, $ys);
3474 0         0 $type = 'image';
3475              
3476 0         0 $bildIndex = $bildnr - 1;
3477 0         0 my $fSource = $infil . '_' . $sidnr;
3478 0         0 my $iSource = $fSource . '_' . $bildnr;
3479 0 0       0 if (! exists $image{$iSource})
3480 0         0 { $imageNr++;
3481 0         0 $inamn = 'Ig' . $imageNr;
3482 0         0 $knownToFile{'Ig:' . $iSource} = $inamn;
3483 0         0 $image{$iSource}[imXPOS] = 0;
3484 0         0 $image{$iSource}[imYPOS] = 0;
3485 0         0 $image{$iSource}[imXSCALE] = 1;
3486 0         0 $image{$iSource}[imYSCALE] = 1;
3487 0 0       0 if (! exists $form{$fSource} )
3488 0         0 { $refNr = getPage($infil, $sidnr, '');
3489 0 0 0     0 if ($refNr)
    0          
3490 0         0 { $formNr++;
3491 0         0 my $namn = 'Fm' . $formNr;
3492 0         0 $knownToFile{$fSource} = $namn;
3493             }
3494             elsif ((defined $refNr) && ($refNr eq '0'))
3495 0         0 { errLog("File: $infil Page: $sidnr can't be found");
3496             }
3497             }
3498 0         0 my $in = $form{$fSource}[fIMAGES][$bildIndex];
3499 0         0 $image{$iSource}[imWIDTH] = $form{$fSource}->[fOBJ]->{$in}->[oWIDTH];
3500 0         0 $image{$iSource}[imHEIGHT] = $form{$fSource}->[fOBJ]->{$in}->[oHEIGHT];
3501 0         0 $image{$iSource}[imIMAGENO] = $form{$fSource}[fIMAGES][$bildIndex];
3502             }
3503 0 0       0 if (exists $knownToFile{'Ig:' . $iSource})
3504 0         0 { $inamn = $knownToFile{'Ig:' . $iSource};
3505             }
3506             else
3507 0         0 { $imageNr++;
3508 0         0 $inamn = 'Ig' . $imageNr;
3509 0         0 $knownToFile{'Ig:' . $iSource} = $inamn;
3510             }
3511 0 0       0 if (! exists $objRef{$inamn})
3512             { $refNr = getImage($infil, $sidnr,
3513 0         0 $bildnr, $image{$iSource}[imIMAGENO]);
3514 0         0 $objRef{$inamn} = $refNr;
3515             }
3516             else
3517 0         0 { $refNr = $objRef{$inamn};
3518             }
3519              
3520 0         0 my @iData = @{$image{$iSource}};
  0         0  
3521              
3522 0 0 0     0 if (($effect eq 'print') && ($refNr))
3523 0 0       0 { if (! defined $defGState)
3524 0         0 { prDefaultGrState();}
3525 0         0 $stream .= "\n/Gs0 gs\n";
3526 0         0 $stream .= "q\n";
3527              
3528 0 0       0 if ($adjust)
3529 0         0 { $stream .= fillTheForm(0, 0, $iData[imWIDTH], $iData[imHEIGHT],$adjust);
3530             }
3531             else
3532 0         0 { my $tX = ($x + $iData[imXPOS]);
3533 0         0 my $tY = ($y + $iData[imYPOS]);
3534 0         0 $stream .= calcMatrix($tX, $tY, $rotate, $size,
3535             $xsize, $ysize, $iData[imWIDTH], $iData[imHEIGHT]);
3536             }
3537 0         0 $stream .= "$iData[imWIDTH] 0 0 $iData[imHEIGHT] 0 0 cm\n";
3538 0         0 $stream .= "/$inamn Do\n";
3539 0         0 $sidXObject{$inamn} = $refNr;
3540 0         0 $stream .= "Q\n";
3541 0         0 $sidExtGState{'Gs0'} = $defGState;
3542             }
3543 0 0       0 if ($runfil)
3544 0         0 { $infil = prep($infil);
3545 0         0 $log .= "Image~$infil~$sidnr~$bildnr~$effect~$adjust";
3546 0         0 $log .= "$x~$y~$size~$xsize~$ysize~$rotate\n";
3547             }
3548 0 0       0 if (! $pos)
3549 0         0 { errLog("No output file, you have to call prFile first");
3550             }
3551              
3552 0 0       0 if (wantarray)
3553 0         0 { return ($inamn, $iData[imWIDTH], $iData[imHEIGHT]);
3554             }
3555             else
3556 0         0 { return $inamn;
3557             }
3558             }
3559              
3560              
3561              
3562             sub prMbox
3563 0 0   0 1 0 { my $lx = defined($_[0]) ? shift : 0;
3564 0 0       0 my $ly = defined($_[0]) ? shift : 0;
3565 0 0       0 my $ux = defined($_[0]) ? shift : 595;
3566 0 0       0 my $uy = defined($_[0]) ? shift : 842;
3567              
3568 0 0 0     0 if ((defined $lx) && ($lx =~ m'^[\d\-\.]+$'o))
3569 0         0 { $genLowerX = $lx; }
3570 0 0 0     0 if ((defined $ly) && ($ly =~ m'^[\d\-\.]+$'o))
3571 0         0 { $genLowerY = $ly; }
3572 0 0 0     0 if ((defined $ux) && ($ux =~ m'^[\d\-\.]+$'o))
3573 0         0 { $genUpperX = $ux; }
3574 0 0 0     0 if ((defined $uy) && ($uy =~ m'^[\d\-\.]+$'o))
3575 0         0 { $genUpperY = $uy; }
3576 0 0       0 if ($runfil)
3577 0         0 { $log .= "Mbox~$lx~$ly~$ux~$uy\n";
3578             }
3579 0 0       0 if (! $pos)
3580 0         0 { errLog("No output file, you have to call prFile first");
3581             }
3582 0         0 1;
3583             }
3584              
3585             sub prField
3586 0     0 1 0 { my ($fieldName, $fieldValue) = @_;
3587 0 0 0     0 if (($interAktivSida) || ($interActive))
    0          
3588 0         0 { errLog("Too late, has already tried to INITIATE FIELDS within an interactive page");
3589             }
3590             elsif (! $pos)
3591 0         0 { errLog("Too early INITIATE FIELDS, create a file first");
3592             }
3593 0         0 $fields{$fieldName} = $fieldValue;
3594 0 0       0 if ($fieldValue =~ m'^\s*js\s*\:(.*)'oi)
3595 0         0 { my $code = $1;
3596 0         0 my @fall = ($code =~ m'([\w\d\_\$]+)\s*\(.*?\)'gs);
3597 0         0 for (@fall)
3598 0 0       0 { if (! exists $initScript{$_})
3599 0         0 { $initScript{$_} = 0;
3600             }
3601             }
3602             }
3603 0 0       0 if ($runfil)
3604 0         0 { $fieldName = prep($fieldName);
3605 0         0 $fieldValue = prep($fieldValue);
3606 0         0 $log .= "Field~$fieldName~$fieldValue\n";
3607             }
3608 0         0 1;
3609             }
3610             ############################################################
3611             sub prBar
3612 0     0 1 0 { my ($xPos, $yPos, $TxT) = @_;
3613              
3614 0         0 $TxT =~ tr/G/2/;
3615              
3616 0         0 my @fontSpar = @aktuellFont;
3617              
3618 0         0 findBarFont();
3619              
3620 0         0 my $Font = $aktuellFont[foINTNAMN]; # Namn i strömmen
3621              
3622 0 0 0     0 if (($xPos) && ($yPos))
3623 0         0 { $stream .= "\nBT /$Font $fontSize Tf ";
3624 0         0 $stream .= "$xPos $yPos Td \($TxT\) Tj ET\n";
3625             }
3626 0 0       0 if ($runfil)
3627 0         0 { $log .= "Bar~$xPos~$yPos~$TxT\n";
3628             }
3629 0 0       0 if (! $pos)
3630 0         0 { errLog("No output file, you have to call prFile first");
3631             }
3632 0         0 @aktuellFont = @fontSpar;
3633 0         0 return $Font;
3634              
3635             }
3636              
3637              
3638             sub prExtract
3639 0     0 1 0 { my $name = shift;
3640 0         0 my $form = shift;
3641 0   0     0 my $page = shift || 1;
3642 0 0       0 if ($name =~ m'^/(\w+)'o)
3643 0         0 { $name = $1;
3644             }
3645 0         0 my $fullName = "$name~$form~$page";
3646 0 0       0 if (exists $knownToFile{$fullName})
3647 0         0 { return $knownToFile{$fullName};
3648             }
3649             else
3650 0 0       0 { if ($runfil)
3651 0         0 { $log = "Extract~$fullName\n";
3652             }
3653 0 0       0 if (! $pos)
3654 0         0 { errLog("No output file, you have to call prFile first");
3655             }
3656              
3657 0 0       0 if (! exists $form{$form . '_' . $page})
3658 0         0 { prForm($form, $page, undef, 'load', 1);
3659             }
3660 0         0 $name = extractName($form, $page, $name);
3661 0 0       0 if ($name)
3662 0         0 { $knownToFile{$fullName} = $name;
3663             }
3664 0         0 return $name;
3665             }
3666             }
3667              
3668              
3669             ########## Extrahera ett dokument ####################
3670             sub prDoc
3671 0     0 1 0 { my ($infil, $first, $last);
3672 0         0 my $param = shift;
3673 0 0       0 if (ref($param) eq 'HASH')
3674 0         0 { $infil = $param->{'file'};
3675 0   0     0 $first = $param->{'first'} || 1;
3676 0   0     0 $last = $param->{'last'} || '';
3677             }
3678             else
3679 0         0 { $infil = $param;
3680 0   0     0 $first = shift || 1;
3681 0   0     0 $last = shift || '';
3682             }
3683              
3684              
3685 0         0 my ($sidor, $Names, $AARoot, $AcroForm) = analysera($infil, $first, $last);
3686 0 0 0     0 if (($Names) || ($AARoot) || ($AcroForm))
      0        
3687 0         0 { $NamesSaved = $Names;
3688 0         0 $AARootSaved = $AARoot;
3689 0         0 $AcroFormSaved = $AcroForm;
3690 0         0 $interActive = 1;
3691             }
3692 0 0       0 if ($runfil)
3693 0         0 { $infil = prep($infil);
3694 0         0 $log .= "Doc~$infil~$first~$last\n";
3695             }
3696 0 0       0 if (! $pos)
3697 0         0 { errLog("No output file, you have to call prFile first");
3698             }
3699 0         0 return $sidor;
3700             }
3701              
3702             ############# Ett interaktivt + grafiskt "formulär" ##########
3703              
3704             sub prDocForm
3705 1     1 1 8 {my ($sidnr, $adjust, $effect, $tolerant, $infil, $x, $y, $size, $xsize,
3706             $ysize, $rotate);
3707 1         2 my $param = shift;
3708 1 50       7 if (ref($param) eq 'HASH')
3709 0         0 { $infil = $param->{'file'};
3710 0   0     0 $sidnr = $param->{'page'} || 1;
3711 0   0     0 $adjust = $param->{'adjust'} || '';
3712 0   0     0 $effect = $param->{'effect'} || 'print';
3713 0   0     0 $tolerant = $param->{'tolerant'} || '';
3714 0   0     0 $x = $param->{'x'} || 0;
3715 0   0     0 $y = $param->{'y'} || 0;
3716 0   0     0 $rotate = $param->{'rotate'} || 0;
3717 0   0     0 $size = $param->{'size'} || 1;
3718 0   0     0 $xsize = $param->{'xsize'} || 1;
3719 0   0     0 $ysize = $param->{'ysize'} || 1;
3720             }
3721             else
3722 1         2 { $infil = $param;
3723 1   50     6 $sidnr = shift || 1;
3724 1   50     5 $adjust = shift || '';
3725 1   50     5 $effect = shift || 'print';
3726 1   50     5 $tolerant = shift || '';
3727 1   50     4 $x = shift || 0;
3728 1   50     3 $y = shift || 0;
3729 1   50     5 $rotate = shift || 0;
3730 1   50     4 $size = shift || 1;
3731 1   50     4 $xsize = shift || 1;
3732 1   50     4 $ysize = shift || 1;
3733             }
3734 1         2 my $namn;
3735             my $refNr;
3736 1         2 $type = 'docform';
3737 1         14 my $fSource = $infil . '_' . $sidnr;
3738 1         2 my $action;
3739 1 50       4 if (! exists $form{$fSource})
3740 1         1 { $formNr++;
3741 1         3 $namn = 'Fm' . $formNr;
3742 1         4 $knownToFile{$fSource} = $namn;
3743 1 50       3 if ($effect eq 'load')
3744 0         0 { $action = 'load'
3745             }
3746             else
3747 1         2 { $action = 'print'
3748             }
3749 1         5 $refNr = getPage($infil, $sidnr, $action);
3750 1 50       3 if ($refNr)
3751 1         3 { $objRef{$namn} = $refNr;
3752             }
3753             else
3754 0 0       0 { if ($tolerant)
    0          
3755 0 0 0     0 { if ((defined $refNr) && ($refNr eq '0')) # Sidnumret existerar inte, men ok
3756 0         0 { $namn = '0';
3757             }
3758             else
3759 0         0 { undef $namn; # Sidan kan inte användas som form
3760             }
3761             }
3762             elsif (! defined $refNr)
3763 0         0 { my $mess = "$fSource can't be used as a form. See the documentation\n"
3764             . "under prForm how to concatenate streams\n";
3765 0         0 errLog($mess);
3766             }
3767             else
3768 0         0 { errLog("File : $infil Page: $sidnr doesn't exist");
3769             }
3770             }
3771             }
3772             else
3773 0 0       0 { if (exists $knownToFile{$fSource})
3774 0         0 { $namn = $knownToFile{$fSource};
3775             }
3776             else
3777 0         0 { $formNr++;
3778 0         0 $namn = 'Fm' . $formNr;
3779 0         0 $knownToFile{$fSource} = $namn;
3780             }
3781 0 0       0 if (exists $objRef{$namn})
3782 0         0 { $refNr = $objRef{$namn};
3783             }
3784             else
3785 0 0       0 { if (! $form{$fSource}[fVALID])
    0          
3786 0         0 { my $mess = "$fSource can't be used as a form. See the documentation\n"
3787             . "under prForm how to concatenate streams\n";
3788 0 0       0 if ($tolerant)
3789 0         0 { cluck $mess;
3790 0         0 undef $namn;
3791             }
3792             else
3793 0         0 { errLog($mess);
3794             }
3795             }
3796             elsif ($effect ne 'load')
3797 0         0 { $refNr = byggForm($infil, $sidnr);
3798 0         0 $objRef{$namn} = $refNr;
3799             }
3800             }
3801             }
3802 1 50       3 my @BBox = @{$form{$fSource}[fBBOX]} if ($refNr);
  1         5  
3803 1 50 33     22 if (($effect eq 'print') && ($form{$fSource}[fVALID]) && ($refNr))
      33        
3804 1 50 33     31 { if ((! defined $interActive)
      33        
3805             && ($sidnr == 1)
3806 1         11 && (%{$intAct{$fSource}[0]}) )
3807 0         0 { $interActive = $infil . ' ' . $sidnr;
3808 0         0 $interAktivSida = 1;
3809             }
3810 1 50       3 if (! defined $defGState)
3811 1         3 { prDefaultGrState();
3812             }
3813 1 50 33     19 if ($adjust)
    50 33        
      33        
      33        
      33        
3814 0         0 { $stream .= "q\n";
3815 0         0 $stream .= fillTheForm(@BBox, $adjust);
3816 0         0 $stream .= "\n/Gs0 gs\n";
3817 0         0 $stream .= "/$namn Do\n";
3818 0         0 $stream .= "Q\n";
3819             }
3820             elsif (($x) || ($y) || ($rotate) || ($size != 1)
3821             || ($xsize != 1) || ($ysize != 1))
3822 0         0 { $stream .= "q\n";
3823 0         0 $stream .= calcMatrix($x, $y, $rotate, $size,
3824             $xsize, $ysize, $BBox[2], $BBox[3]);
3825 0         0 $stream .= "\n/Gs0 gs\n";
3826 0         0 $stream .= "/$namn Do\n";
3827 0         0 $stream .= "Q\n";
3828             }
3829             else
3830 1         3 { $stream .= "\n/Gs0 gs\n";
3831 1         2 $stream .= "/$namn Do\n";
3832             }
3833 1         3 $sidXObject{$namn} = $refNr;
3834 1         9 $sidExtGState{'Gs0'} = $defGState;
3835             }
3836 1 50       3 if ($runfil)
3837 0         0 { $infil = prep($infil);
3838 0         0 $log .= "Form~$infil~$sidnr~$adjust~$effect~$tolerant";
3839 0         0 $log .= "~$x~$y~$rotate~$size~$xsize~$ysize\n";
3840             }
3841 1 50       3 if (! $pos)
3842 0         0 { errLog("No output file, you have to call prFile first");
3843             }
3844 1 50 33     5 if (($effect ne 'print') && ($effect ne 'add'))
3845 0         0 { undef $namn;
3846             }
3847 1 50       3 if (wantarray)
3848 0         0 { my $images = 0;
3849 0 0       0 if (exists $form{$fSource}[fIMAGES])
3850 0         0 { $images = scalar(@{$form{$fSource}[fIMAGES]});
  0         0  
3851             }
3852 0         0 return ($namn, $BBox[0], $BBox[1], $BBox[2],
3853             $BBox[3], $images);
3854             }
3855             else
3856 1         5 { return $namn;
3857             }
3858             }
3859              
3860             sub calcMatrix
3861 0     0 0 0 { my ($x, $y, $rotate, $size, $xsize, $ysize, $upperX, $upperY) = @_;
3862 0         0 my ($str, $xSize, $ySize);
3863 0 0       0 $size = 1 if ($size == 0);
3864 0 0       0 $xsize = 1 if ($xsize == 0);
3865 0 0       0 $ysize = 1 if ($ysize == 0);
3866 0         0 $xSize = $xsize * $size;
3867 0         0 $ySize = $ysize * $size;
3868 0         0 $str = "$xSize 0 0 $ySize $x $y cm\n";
3869 0 0       0 if ($rotate)
3870 0 0       0 { if ($rotate =~ m'q(\d)'oi)
3871 0         0 { my $tal = $1;
3872 0 0       0 if ($tal == 1)
    0          
3873 0         0 { $upperY = $upperX;
3874 0         0 $upperX = 0;
3875 0         0 $rotate = 270;
3876             }
3877             elsif ($tal == 2)
3878 0         0 { $rotate = 180;
3879             }
3880             else
3881 0         0 { $rotate = 90;
3882 0         0 $upperX = $upperY;
3883 0         0 $upperY = 0;
3884             }
3885             }
3886             else
3887 0         0 { $upperX = 0;
3888 0         0 $upperY = 0;
3889             }
3890 0         0 my $radian = sprintf("%.6f", $rotate / 57.2957795); # approx.
3891 0         0 my $Cos = sprintf("%.6f", cos($radian));
3892 0         0 my $Sin = sprintf("%.6f", sin($radian));
3893 0         0 my $negSin = $Sin * -1;
3894 0         0 $str .= "$Cos $Sin $negSin $Cos $upperX $upperY cm\n";
3895             }
3896 0         0 return $str;
3897             }
3898              
3899             sub fillTheForm
3900 0   0 0 0 0 { my $left = shift || 0;
3901 0   0     0 my $bottom = shift || 0;
3902 0   0     0 my $right = shift || 0;
3903 0   0     0 my $top = shift || 0;
3904 0   0     0 my $how = shift || 1;
3905 0         0 my $image = shift;
3906 0         0 my $str;
3907 0         0 my $scaleX = 1;
3908 0         0 my $scaleY = 1;
3909              
3910 0         0 my $xDim = $genUpperX - $genLowerX;
3911 0         0 my $yDim = $genUpperY - $genLowerY;
3912 0         0 my $xNy = $right - $left;
3913 0         0 my $yNy = $top - $bottom;
3914 0         0 $scaleX = $xDim / $xNy;
3915 0         0 $scaleY = $yDim / $yNy;
3916 0 0       0 if ($how == 1)
3917 0 0       0 { if ($scaleX < $scaleY)
3918 0         0 { $scaleY = $scaleX;
3919             }
3920             else
3921 0         0 { $scaleX = $scaleY;
3922             }
3923             }
3924 0         0 $str = "$scaleX 0 0 $scaleY $left $bottom cm\n";
3925 0         0 return $str;
3926             }
3927              
3928             sub prAltJpeg
3929 0     0 1 0 { my ($iData, $iWidth, $iHeight, $iFormat,$aiData, $aiWidth, $aiHeight, $aiFormat) = @_;
3930 0 0       0 if (! $pos) # If no output is active, it is no use to continue
3931 0         0 { return undef;
3932             }
3933 0         0 prJpeg($aiData, $aiWidth, $aiHeight, $aiFormat);
3934 0         0 my $altObjNr = $objNr;
3935 0         0 $imageNr++;
3936 0         0 $objNr++;
3937 0         0 $objekt[$objNr] = $pos;
3938 0         0 my $utrad = "$objNr 0 obj\n" .
3939             "[ << /Image $altObjNr 0 R\n" .
3940             "/DefaultForPrinting true\n" .
3941             ">>\n" .
3942             "]\n" .
3943             "endobj\n";
3944 0         0 $pos += syswrite UTFIL, $utrad;
3945 0 0       0 if ($runfil)
3946 0         0 { $log .= "Jpeg~AltImage\n";
3947             }
3948 0         0 my $namnet = prJpeg($iData, $iWidth, $iHeight, $iFormat, $objNr);
3949 0         0 $objRef{$namnet} = $objNr;
3950 0 0       0 if (! $pos)
3951 0         0 { errLog("No output file, you have to call prFile first");
3952             }
3953 0         0 return $namnet;
3954             }
3955              
3956             sub prJpeg
3957 0     0 1 0 { my ($iData, $iWidth, $iHeight, $iFormat, $iColorType, $altArrayObjNr) = @_;
3958 0 0       0 if ($iColorType =~ /Gray/i)
3959 0         0 { $iColorType = 'DeviceGray';
3960             }
3961             else
3962 0         0 { $iColorType = 'DeviceRGB';
3963             }
3964 0         0 my ($iLangd, $namnet, $utrad, $iFile);
3965 0 0       0 if (! $pos) # If no output is active, it is no use to continue
3966 0         0 { return undef;
3967             }
3968 0         0 my $checkidOld = $checkId;
3969 0 0       0 if (!$iFormat)
    0          
3970 0         0 { ($iFile, $checkId) = findGet($iData, $checkidOld);
3971 0 0       0 if ($iFile)
3972 0         0 { $iLangd = (stat($iFile))[7];
3973 0         0 $imageNr++;
3974 0         0 $namnet = 'Ig' . $imageNr;
3975 0         0 $objNr++;
3976 0         0 $objekt[$objNr] = $pos;
3977 0 0       0 open (BILDFIL, "<$iFile") || errLog("Couldn't open $iFile, $!, aborts");
3978 0         0 binmode BILDFIL;
3979 0         0 my $iStream;
3980 0         0 sysread BILDFIL, $iStream, $iLangd;
3981 0 0       0 $utrad = "$objNr 0 obj\n<
3982             "/Width $iWidth /Height $iHeight /BitsPerComponent 8 " .
3983             ($altArrayObjNr ? "/Alternates $altArrayObjNr 0 R " : "") .
3984             "/Filter/DCTDecode/ColorSpace/$iColorType"
3985             . "/Length $iLangd >>stream\n$iStream\nendstream\nendobj\n";
3986 0         0 close BILDFIL;
3987 0         0 $pos += syswrite UTFIL, $utrad;
3988 0 0       0 if ($runfil)
3989 0         0 { $log .= "Cid~$checkId\n";
3990 0         0 $log .= "Jpeg~$iFile~$iWidth~$iHeight\n";
3991             }
3992 0         0 $objRef{$namnet} = $objNr;
3993             }
3994             }
3995             elsif ($iFormat == 1)
3996 0         0 { my $iBlob = $iData;
3997 0         0 $iLangd = length($iBlob);
3998 0         0 $imageNr++;
3999 0         0 $namnet = 'Ig' . $imageNr;
4000 0         0 $objNr++;
4001 0         0 $objekt[$objNr] = $pos;
4002 0 0       0 $utrad = "$objNr 0 obj\n<
4003             "/Width $iWidth /Height $iHeight /BitsPerComponent 8 " .
4004             ($altArrayObjNr ? "/Alternates $altArrayObjNr 0 R " : "") .
4005             "/Filter/DCTDecode/ColorSpace/$iColorType"
4006             . "/Length $iLangd >>stream\n$iBlob\nendstream\nendobj\n";
4007 0         0 $pos += syswrite UTFIL, $utrad;
4008 0 0       0 if ($runfil)
4009 0         0 { $log .= "Cid~$checkId\n";
4010 0 0       0 $log .= "Jpeg~$iFile~$iWidth~$iHeight\n" if !$iFormat;
4011 0 0       0 $log .= "Jpeg~Blob~$iWidth~$iHeight\n" if $iFormat == 1;
4012             }
4013 0         0 $objRef{$namnet} = $objNr;
4014             }
4015 0 0       0 if (! $pos)
4016 0         0 { errLog("No output file, you have to call prFile first");
4017             }
4018 0         0 undef $checkId;
4019 0         0 return $namnet;
4020             }
4021              
4022             sub checkContentStream
4023 0     0 0 0 { for (@_)
4024 0 0 0     0 { if (my $value = $objRef{$_})
    0          
4025 0         0 { my $typ = substr($_, 0, 2);
4026 0 0       0 if ($typ eq 'Ft')
    0          
    0          
    0          
    0          
4027 0         0 { $sidFont{$_} = $value;
4028             }
4029             elsif ($typ eq 'Gs')
4030 0         0 { $sidExtGState{$_} = $value;
4031             }
4032             elsif ($typ eq 'Pt')
4033 0         0 { $sidPattern{$_} = $value;
4034             }
4035             elsif ($typ eq 'Sh')
4036 0         0 { $sidShading{$_} = $value;
4037             }
4038             elsif ($typ eq 'Cs')
4039 0         0 { $sidColorSpace{$_} = $value;
4040             }
4041             else
4042 0         0 { $sidXObject{$_} = $value;
4043             }
4044             }
4045             elsif (($_ eq 'Gs0') && (! defined $defGState))
4046 0         0 { my ($dummy, $oNr) = prDefaultGrState();
4047 0         0 $sidExtGState{'Gs0'} = $oNr;
4048             }
4049             }
4050             }
4051              
4052             sub prGraphState
4053 0     0 1 0 { my $string = shift;
4054 0         0 $gSNr++;
4055 0         0 my $name = 'Gs' . $gSNr ;
4056 0         0 $objNr++;
4057 0         0 $objekt[$objNr] = $pos;
4058 0         0 my $utrad = "$objNr 0 obj\n" . $string . "\nendobj\n";
4059 0         0 $pos += syswrite UTFIL, $utrad;
4060 0         0 $objRef{$name} = $objNr;
4061 0 0       0 if ($runfil)
4062 0         0 { $log .= "GraphStat~$string\n";
4063             }
4064 0 0       0 if (! $pos)
4065 0         0 { errLog("No output file, you have to call prFile first");
4066             }
4067 0         0 return $name;
4068             }
4069              
4070             ##############################################################
4071             # Streckkods fonten lokaliseras och objekten skrivs ev. ut
4072             ##############################################################
4073              
4074             sub findBarFont()
4075 0     0 0 0 { my $Font = 'Bar';
4076              
4077 0 0       0 if (exists $font{$Font}) # Objekt är redan definierat
4078 0         0 { $aktuellFont[foEXTNAMN] = $Font;
4079 0         0 $aktuellFont[foREFOBJ] = $font{$Font}[foREFOBJ];
4080 0         0 $aktuellFont[foINTNAMN] = $font{$Font}[foINTNAMN];
4081             }
4082             else
4083 0         0 { $objNr++;
4084 0         0 $objekt[$objNr] = $pos;
4085 0         0 my $encodObj = $objNr;
4086 0         0 my $fontObjekt = "$objNr 0 obj\n<< /Type /Encoding\n" .
4087             '/Differences [48 /tomt /streck /lstreck]' . "\n>>\nendobj\n";
4088 0         0 $pos += syswrite UTFIL, $fontObjekt;
4089 0         0 my $charProcsObj = createCharProcs();
4090 0         0 $objNr++;
4091 0         0 $objekt[$objNr] = $pos;
4092 0         0 $fontNr++;
4093 0         0 my $fontAbbr = 'Ft' . $fontNr;
4094 0         0 $fontObjekt = "$objNr 0 obj\n<
4095             '/FontBBox [0 -250 75 2000]' . "\n" .
4096             '/FontMatrix [0.001 0 0 0.001 0 0]' . "\n" .
4097             "\/CharProcs $charProcsObj 0 R\n" .
4098             "\/Encoding $encodObj 0 R\n" .
4099             '/FirstChar 48' . "\n" .
4100             '/LastChar 50' . "\n" .
4101             '/Widths [75 75 75]' . "\n>>\nendobj\n";
4102              
4103 0         0 $font{$Font}[foINTNAMN] = $fontAbbr;
4104 0         0 $font{$Font}[foREFOBJ] = $objNr;
4105 0         0 $objRef{$fontAbbr} = $objNr;
4106 0         0 $objekt[$objNr] = $pos;
4107 0         0 $aktuellFont[foEXTNAMN] = $Font;
4108 0         0 $aktuellFont[foREFOBJ] = $objNr;
4109 0         0 $aktuellFont[foINTNAMN] = $fontAbbr;
4110 0         0 $pos += syswrite UTFIL, $fontObjekt;
4111             }
4112 0 0       0 if (! $pos)
4113 0         0 { errLog("No output file, you have to call prFile first");
4114             }
4115              
4116 0         0 $sidFont{$aktuellFont[foINTNAMN]} = $aktuellFont[foREFOBJ];
4117             }
4118              
4119             sub createCharProcs()
4120             { #################################
4121             # Fonten (objektet) för 0 skapas
4122             #################################
4123              
4124 0     0 0 0 $objNr++;
4125 0         0 $objekt[$objNr] = $pos;
4126 0         0 my $tomtObj = $objNr;
4127 0         0 my $str = "\n75 0 d0\n6 0 69 2000 re\n1.0 g\nf\n";
4128 0         0 my $strLength = length($str);
4129 0         0 my $obj = "$objNr 0 obj\n<< /Length $strLength >>\nstream" .
4130             $str . "\nendstream\nendobj\n";
4131 0         0 $pos += syswrite UTFIL, $obj;
4132              
4133             #################################
4134             # Fonten (objektet) för 1 skapas
4135             #################################
4136              
4137 0         0 $objNr++;
4138 0         0 $objekt[$objNr] = $pos;
4139 0         0 my $streckObj = $objNr;
4140 0         0 $str = "\n75 0 d0\n4 0 71 2000 re\n0.0 g\nf\n";
4141 0         0 $strLength = length($str);
4142 0         0 $obj = "$objNr 0 obj\n<< /Length $strLength >>\nstream" .
4143             $str . "\nendstream\nendobj\n";
4144 0         0 $pos += syswrite UTFIL, $obj;
4145              
4146             ###################################################
4147             # Fonten (objektet) för 2, ett långt streck skapas
4148             ###################################################
4149              
4150 0         0 $objNr++;
4151 0         0 $objekt[$objNr] = $pos;
4152 0         0 my $lStreckObj = $objNr;
4153 0         0 $str = "\n75 0 d0\n4 -250 71 2250 re\n0.0 g\nf\n";
4154 0         0 $strLength = length($str);
4155 0         0 $obj = "$objNr 0 obj\n<< /Length $strLength >>\nstream" .
4156             $str . "\nendstream\nendobj\n";
4157 0         0 $pos += syswrite UTFIL, $obj;
4158              
4159             #####################################################
4160             # Objektet för "CharProcs" skapas
4161             #####################################################
4162              
4163 0         0 $objNr++;
4164 0         0 $objekt[$objNr] = $pos;
4165 0         0 my $charProcsObj = $objNr;
4166 0         0 $obj = "$objNr 0 obj\n<
4167             "/lstreck $lStreckObj 0 R>>\nendobj\n";
4168 0         0 $pos += syswrite UTFIL, $obj;
4169 0         0 return $charProcsObj;
4170             }
4171              
4172              
4173              
4174             sub prCid
4175 0     0 1 0 { $checkId = shift;
4176 0 0       0 if ($runfil)
4177 0         0 { $log .= "Cid~$checkId\n";
4178             }
4179 0         0 1;
4180             }
4181              
4182             sub prIdType
4183 0     0 1 0 { $idTyp = shift;
4184 0 0       0 if ($runfil)
4185 0         0 { $log .= "IdType~rep\n";
4186             }
4187 0         0 1;
4188             }
4189              
4190              
4191             sub prId
4192 0     0 1 0 { $id = shift;
4193 0 0       0 if ($runfil)
4194 0         0 { $log .= "Id~$id\n";
4195             }
4196 0 0       0 if (! $pos)
4197 0         0 { errLog("No output file, you have to call prFile first");
4198             }
4199 0         0 1;
4200             }
4201              
4202             sub prJs
4203 0     0 1 0 { my $filNamnIn = shift;
4204 0         0 my $filNamn;
4205 0 0       0 if ($filNamnIn !~ m'\{'os)
4206 0         0 { my $checkIdOld = $checkId;
4207 0         0 ($filNamn, $checkId) = findGet($filNamnIn, $checkIdOld);
4208 0 0 0     0 if (($runfil) && ($checkId) && ($checkId ne $checkIdOld))
      0        
4209 0         0 { $log .= "Cid~$checkId\n";
4210             }
4211 0         0 $checkId = '';
4212             }
4213             else
4214 0         0 { $filNamn = $filNamnIn;
4215             }
4216 0 0       0 if ($runfil)
4217 0         0 { my $filnamn = prep($filNamn);
4218 0         0 $log .= "Js~$filnamn\n";
4219             }
4220 0 0 0     0 if (($interAktivSida) || ($interActive))
    0          
4221 0         0 { errLog("Too late, has already tried to merge JAVA SCRIPTS within an interactive page");
4222             }
4223             elsif (! $pos)
4224 0         0 { errLog("Too early for JAVA SCRIPTS, create a file first");
4225             }
4226 0         0 push @jsfiler, $filNamn;
4227 0         0 1;
4228             }
4229              
4230             sub prInit
4231 0     0 1 0 { my $initText = shift;
4232 0   0     0 my $duplicate = shift || '';
4233 0         0 my @fall = ($initText =~ m'([\w\d\_\$]+)\s*\(.*?\)'gs);
4234 0         0 for (@fall)
4235 0 0       0 { if (! exists $initScript{$_})
4236 0         0 { $initScript{$_} = 0;
4237             }
4238             }
4239 0 0       0 if ($duplicate)
4240 0         0 { $duplicateInits = 1;
4241             }
4242 0         0 push @inits, $initText;
4243 0 0       0 if ($runfil)
4244 0         0 { $initText = prep($initText);
4245 0         0 $log .= "Init~$initText~$duplicate\n";
4246             }
4247 0 0 0     0 if (($interAktivSida) || ($interActive))
    0          
4248 0         0 { errLog("Too late, has already tried to create INITIAL JAVA SCRIPTS within an interactive page");
4249             }
4250             elsif (! $pos)
4251 0         0 { errLog("Too early for INITIAL JAVA SCRIPTS, create a file first");
4252             }
4253 0         0 1;
4254              
4255             }
4256              
4257             sub prVers
4258 0     0 1 0 { my $vers = shift;
4259             ############################################################
4260             # Om programmet körs om så kontrolleras VERSION
4261             ############################################################
4262 0 0       0 if ($vers ne $VERSION)
4263 0         0 { warn "$vers \<\> $VERSION might give different results, if comparing two runs \n";
4264 0         0 return undef;
4265             }
4266             else
4267 0         0 { return 1;
4268             }
4269             }
4270              
4271             sub prDocDir
4272 0     0 1 0 { $ddir = findDir(shift);
4273 0         0 1;
4274             }
4275              
4276             sub prLogDir
4277 0     0 1 0 { $ldir = findDir(shift);
4278 0         0 1;
4279             }
4280              
4281             sub prLog
4282 0     0 1 0 { my $mess = shift;
4283 0 0       0 if ($runfil)
4284 0         0 { $mess = prep($mess);
4285 0         0 $log .= "Log~$mess\n";
4286 0         0 return 1;
4287             }
4288             else
4289 0         0 { errLog("You have to give a directory for the logfiles first : prLogDir , aborts");
4290             }
4291              
4292             }
4293              
4294             sub prGetLogBuffer
4295             {
4296 0     0 1 0 return $log;
4297             }
4298              
4299             sub findDir
4300 0     0 0 0 { my $dir = shift;
4301 0 0       0 if ($dir eq '.')
4302 0         0 { return undef; }
4303 0 0       0 if (! -e $dir)
4304 0   0     0 { mkdir $dir || errLog("Couldn't create directory $dir, $!");
4305             }
4306              
4307 0 0 0     0 if ((-e $dir) && (-d $dir))
4308 0 0       0 { if (substr($dir, length($dir), 1) eq '/')
4309 0         0 { return $dir; }
4310             else
4311 0         0 { return ($dir . '/');
4312             }
4313             }
4314             else
4315 0         0 { errLog("Error finding/creating directory $dir, $!");
4316             }
4317             }
4318              
4319             sub prTouchUp
4320 0     0 1 0 { $touchUp = shift;
4321 0 0       0 if ($runfil)
4322 0         0 { $log .= "TouchUp~$touchUp\n";
4323             }
4324 0 0       0 if (! $pos)
4325 0         0 { errLog("No output file, you have to call prFile first");
4326             }
4327 0         0 1;
4328             }
4329              
4330             sub prCompress
4331 0     0 1 0 { $compress = shift;
4332 0 0       0 if ($runfil)
4333 0         0 { $log .= "Compress~$compress\n";
4334             }
4335 0 0       0 if (! $pos)
4336 0         0 { errLog("No output file, you have to call prFile first");
4337             }
4338 0         0 1;
4339              
4340             }
4341              
4342             sub prep
4343 0     0 0 0 { my $indata = shift;
4344 0         0 $indata =~ s/[\n\r]+/ /sgo;
4345 0         0 $indata =~ s/~//sgo;
4346 0         0 return $indata;
4347             }
4348              
4349              
4350             sub xRefs
4351 2     2 0 6 { my ($bytes, $infil) = @_;
4352 2         4 my ($j, $nr, $xref, $i, $antal, $inrad, $Root, $tempRoot, $referens);
4353 2         3 my $buf = '';
4354 2         5 %embedded =();
4355              
4356 2         10 my $res = sysseek INFIL, -50, 2;
4357 2 50       6 if ($res)
4358 2         23 { sysread INFIL, $buf, 100;
4359 2 50       10 if ($buf =~ m'Encrypt'o)
4360 0         0 { errLog("The file $infil is encrypted, cannot be used, aborts");
4361             }
4362 2 50       61 if ($buf =~ m/\bstartxref$ws+(\d+)/)
4363 2         7 { $xref = $1;
4364 2 50       7 if ($xref <= $bytes)
4365             {
4366 2         5 while ($xref)
4367 2         9 { $res = sysseek INFIL, $xref, 0;
4368 2         12 $res = sysread INFIL, $buf, 200;
4369 2 50       63 if ($buf =~ m /^\d+$ws+\d+$ws+obj/os)
4370 0         0 { ($xref, $tempRoot, $nr) = crossrefObj($nr, $xref);
4371             }
4372             else
4373 2         10 { ($xref, $tempRoot, $nr) = xrefSection($nr, $xref, $infil);
4374             }
4375 2 50 33     17 if (($tempRoot) && (! $Root))
4376 2         5 { $Root = $tempRoot;
4377             }
4378             }
4379             }
4380             else
4381 0         0 { errLog("Invalid XREF, aborting");
4382             }
4383             }
4384             }
4385              
4386 2 50       6 ($Root) || errLog("The Root object in $infil couldn't be found, aborting");
4387              
4388             ##############################################################
4389             # Objekten sorteras i fallande ordning (efter offset i filen)
4390             ##############################################################
4391              
4392 2         16 my @offset = sort { $oldObject{$b} <=> $oldObject{$a} } keys %oldObject;
  27         48  
4393              
4394 2         4 my $saved;
4395              
4396 2         6 for (@offset)
4397 14         18 { $saved = $oldObject{$_};
4398 14         20 $bytes -= $saved;
4399              
4400 14 100       29 if ($_ !~ m'^xref'o)
4401 12 50       19 { if ($saved == 0)
4402 0         0 { $oldObject{$_} = [ 0, 0, $embedded{$_}];
4403             }
4404             else
4405 12         42 { $oldObject{$_} = [ $saved, $bytes];
4406             }
4407             }
4408 14         22 $bytes = $saved;
4409             }
4410 2         4 %embedded = ();
4411 2         8 return $Root;
4412             }
4413              
4414             sub crossrefObj
4415 0     0 0 0 { my ($nr, $xref) = @_;
4416 0         0 my ($buf, %param, $len, $tempRoot);
4417 0         0 my $from = $xref;
4418 0         0 sysseek INFIL, $xref, 0;
4419 0         0 sysread INFIL, $buf, 400;
4420 0         0 my $str;
4421 0 0       0 if ($buf =~ m/^(.+>>$ws*)stream/os)
4422 0         0 { $str = $1;
4423 0         0 $from = length($str) + 7;
4424 0 0       0 if (substr($buf, $from, 1) eq "\n")
4425 0         0 { $from++;
4426             }
4427 0         0 $from += $xref;
4428             }
4429              
4430 0         0 for (split('/',$str))
4431 0 0       0 { if ($_ =~ m'^(\w+)(.*)'o)
4432 0   0     0 { $param{$1} = $2 || ' ';
4433             }
4434             }
4435 0 0       0 if (!exists $param{'Index'})
4436 0         0 { $param{'Index'} = "[0 $param{'Size'}]";
4437             }
4438 0 0 0     0 if ((exists $param{'Root'}) && ($param{'Root'} =~ m/^$ws*(\d+)/o))
4439 0         0 { $tempRoot = $1;
4440             }
4441 0         0 my @keys = ($param{'W'} =~ m'(\d+)'og);
4442 0         0 my $keyLength = 0;
4443 0         0 for (@keys)
4444 0         0 { $keyLength += $_;
4445             }
4446 0         0 my $recLength = $keyLength + 1;
4447 0         0 my $upTo = 1 + $keys[0] + $keys[1];
4448 0 0 0     0 if ((exists $param{'Length'}) && ($param{'Length'} =~ m'(\d+)'o))
4449 0         0 { $len = $1;
4450 0         0 sysseek INFIL, $from, 0;
4451 0         0 sysread INFIL, $buf, $len;
4452 0   0     0 my $x = inflateInit()
4453             || die "Cannot create an inflation stream\n" ;
4454 0         0 my ($output, $status) = $x->inflate(\$buf) ;
4455 0 0       0 die "inflation failed\n"
4456             unless $status == 1;
4457              
4458 0         0 my $i = 0;
4459 0         0 my @last = (0, 0, 0, 0, 0, 0, 0);
4460 0         0 my @word = ('0', '0', '0', '0', '0', '0', '0');
4461 0         0 my $recTyp;
4462 0         0 my @intervall = ($param{'Index'} =~ m'(\d+)\D'osg);
4463 0         0 my $m = 0;
4464 0         0 my $currObj = $intervall[$m];
4465 0         0 $m++;
4466 0         0 my $max = $currObj + $intervall[$m];
4467              
4468 0         0 for (unpack ("C*", $output))
4469 0 0 0     0 { if (($_ != 0) && ($i > 0) && ($i < $upTo))
      0        
4470 0         0 { my $tal = $_ + $last[$i] ;
4471 0 0       0 if ($tal > 255)
4472 0         0 {$tal -= 256;
4473             }
4474              
4475 0         0 $last[$i] = $tal;
4476 0         0 $word[$i] = sprintf("%x", $tal);
4477 0 0       0 if (length($word[$i]) == 1)
4478 0         0 { $word[$i] = '0' . $word[$i];
4479             }
4480             }
4481 0         0 $i++;
4482 0 0       0 if ($i == $recLength)
4483 0         0 { $i = 0;
4484 0         0 my $j = 0;
4485 0         0 my $offsObj; # offset or object
4486 0 0       0 if ($keys[0] == 0)
4487 0         0 { $recTyp = 1;
4488 0         0 $j = 1;
4489             }
4490             else
4491 0         0 { $recTyp = hex($word[1]);
4492 0         0 $j = 2;
4493             }
4494 0         0 my $k = 0;
4495 0         0 while ($k < $keys[1])
4496 0         0 { $offsObj .= $word[$j];
4497 0         0 $k++;
4498 0         0 $j++;
4499             }
4500              
4501 0 0       0 if ($recTyp == 1)
    0          
4502 0 0       0 { if (! (exists $oldObject{$currObj}))
4503 0         0 { $oldObject{$currObj} = hex($offsObj); }
4504             else
4505 0         0 { $nr++;
4506 0         0 $oldObject{'xref' . "$nr"} = hex($offsObj);
4507             }
4508             }
4509             elsif ($recTyp == 2)
4510 0 0       0 { if (! (exists $oldObject{$currObj}))
4511 0         0 { $oldObject{$currObj} = 0;
4512             }
4513 0         0 $embedded{$currObj} = hex($offsObj);
4514             }
4515 0 0       0 if ($currObj < $max)
4516 0         0 { $currObj++;
4517             }
4518             else
4519 0         0 { $m++;
4520 0         0 $currObj = $intervall[$m];
4521 0         0 $m++;
4522 0         0 $max = $currObj + $intervall[$m];
4523             }
4524             }
4525             }
4526             }
4527 0         0 return ($param{'Prev'}, $tempRoot, $nr);
4528             }
4529              
4530             sub xrefSection
4531 2     2 0 6 { my ($nr, $xref, $infil) = @_;
4532 2         5 my ($i, $root, $antal);
4533 2         4 $nr++;
4534 2         9 $oldObject{('xref' . "$nr")} = $xref; # Offset för xref sparas
4535 2         7 sysseek INFIL, $xref, 0;
4536 2         11 sysread INFIL, my $buf, 30;
4537 2 50       14 if ($buf =~ /xref/) {
4538 2         15 sysseek INFIL, $xref+$-[0]+5, 0;
4539             }
4540             else {
4541             # If the regexp fails (it shouldn't), fall back to the previous
4542             # behaviour.
4543 0         0 sysseek INFIL, $xref + 5, 0;
4544             }
4545 2         4 $xref = 0;
4546 2         4 my $inrad = '';
4547 2         4 $buf = '';
4548 2         3 my $c;
4549 2         9 sysread INFIL, $c, 1;
4550 2         8 while ($c =~ m!\s!s)
4551 0         0 { sysread INFIL, $c, 1; }
4552              
4553 2   66     14 while ( (defined $c)
      66        
4554             && ($c ne "\n")
4555             && ($c ne "\r") )
4556 6         11 { $inrad .= $c;
4557 6         65 sysread INFIL, $c, 1;
4558             }
4559              
4560 2 50       12 if ($inrad =~ m'^(\d+)\s+(\d+)'o)
4561 2         5 { $i = $1;
4562 2         9 $antal = $2;
4563             }
4564              
4565 2         38 while ($antal)
4566 2         8 { for (my $l = 1; $l <= $antal; $l++)
4567 14         52 { sysread INFIL, $inrad, 20;
4568 14 50       48 if ($inrad =~ m'^\s?(\d+) \d+ (\w)\s*'o)
4569 14 100       29 { if ($2 eq 'n')
4570 12 50       20 { if (! (exists $oldObject{$i}))
4571 12         32 { $oldObject{$i} = int($1); }
4572             else
4573 0         0 { $nr++;
4574 0         0 $oldObject{'xref' . "$nr"} = int($1);
4575             }
4576             }
4577             }
4578 14         28 $i++;
4579             }
4580 2         3 undef $antal;
4581 2         4 undef $inrad;
4582 2         8 sysread INFIL, $c, 1;
4583 2         8 while ($c =~ m!\s!s)
4584 0         0 { sysread INFIL, $c, 1; }
4585              
4586 2   66     20 while ( (defined $c)
      66        
4587             && ($c ne "\n")
4588             && ($c ne "\r") )
4589 14         19 { $inrad .= $c;
4590 14         78 sysread INFIL, $c, 1;
4591             }
4592 2 50       10 if ($inrad =~ m'^(\d+)\s+(\d+)'o)
4593 0         0 { $i = $1;
4594 0         0 $antal = $2;
4595             }
4596              
4597             }
4598              
4599 2         4 while ($inrad)
4600 10         21 { $buf .= $inrad;
4601 10 50       24 if ($buf =~ m'Encrypt'o)
4602 0         0 { errLog("The file $infil is encrypted, cannot be used, aborts");
4603             }
4604 10 100 100     92 if ((! $root) && ($buf =~ m|\/Root$ws+(\d+)$ws+\d+$ws+R|so))
4605 2         5 { $root = $1;
4606 2 50       6 if ($xref)
4607 0         0 { last; }
4608             }
4609              
4610 10 50 33     58 if ((! $xref) && ($buf =~ m|\/Prev$ws+(\d+)\D|so))
4611 0         0 { $xref = $1;
4612 0 0       0 if ($root)
4613 0         0 { last; }
4614             }
4615              
4616 10 100       25 if ($buf =~ m'xref'so)
4617 2         4 { last; }
4618              
4619 8 50 66     27 if($inrad=~ m/trailer/o && (! $root) && ($inrad =~ m'\/Root\s+(\d+)\s{1,2}\d+\s{1,2}R'so))
      66        
4620 0         0 { $root = $1;
4621 0 0       0 if ($xref)
4622 0         0 { last; }
4623             }
4624              
4625 8         36 sysread INFIL, $inrad, 30;
4626             }
4627 2         11 return ($xref, $root, $nr);
4628             }
4629              
4630             sub getObject
4631 14     14 0 31 { my ($nr, $noId, $noEnd) = @_;
4632              
4633 14         17 my $buf;
4634 14         38 my ($offs, $siz, $embedded) = @{$oldObject{$nr}};
  14         34  
4635              
4636 14 50       25 if ($offs)
    0          
    0          
4637 14         56 { sysseek INFIL, $offs, 0;
4638 14         82 sysread INFIL, $buf, $siz;
4639 14 100 66     42 if (($noId) && ($noEnd))
    50          
4640 2 50       75 { if ($buf =~ m/^\d+$ws+\d+$ws+obj$ws*(.*)endobj/os)
4641 2 50       6 { if (wantarray)
4642 0         0 { return ($1, $offs, $siz, $embedded);
4643             }
4644             else
4645 2         8 { return $1;
4646             }
4647             }
4648             }
4649             elsif ($noId)
4650 0 0       0 { if ($buf =~ m/^\d+$ws+\d+$ws+obj$ws*(.*)/os)
4651 0 0       0 { if (wantarray)
4652 0         0 { return ($1, $offs, $siz, $embedded);
4653             }
4654             else
4655 0         0 { return $1;
4656             }
4657             }
4658             }
4659 12 100       19 if (wantarray)
4660 6         23 { return ($buf, $offs, $siz, $embedded)
4661             }
4662             else
4663 6         35 { return $buf;
4664             }
4665             }
4666             elsif (exists $unZipped{$nr})
4667             { ;
4668             }
4669             elsif ($embedded)
4670 0         0 { unZipPrepare($embedded);
4671             }
4672 0 0       0 if ($noEnd)
4673 0 0       0 { if (wantarray)
4674 0         0 { return ($unZipped{$nr}, $offs, $siz, $embedded)
4675             }
4676             else
4677 0         0 { return $unZipped{$nr};
4678             }
4679             }
4680             else
4681 0 0       0 { if (wantarray)
4682 0         0 { return ("$unZipped{$nr}endobj\n", $offs, $siz, $embedded)
4683             }
4684             else
4685 0         0 { return "$unZipped{$nr}endobj\n";
4686             }
4687             }
4688             }
4689              
4690             sub getKnown
4691 0     0 0 0 { my ($p, $nr) = @_;
4692 0         0 my ($del1, $del2);
4693 0         0 my @objData = @{$$$p[0]->{$nr}};
  0         0  
4694 0 0       0 if (defined $objData[oSTREAMP])
4695 0         0 { sysseek INFIL, ($objData[oNR][0] + $objData[oPOS]), 0;
4696 0         0 sysread INFIL, $del1, ($objData[oSTREAMP] - $objData[oPOS]);
4697 0         0 sysread INFIL, $del2, ($objData[oNR][1] - $objData[oSTREAMP]);
4698             }
4699             else
4700 0         0 { my $buf;
4701 0         0 my ($offs, $siz, $embedded) = @{$objData[oNR]};
  0         0  
4702 0 0       0 if ($offs)
    0          
    0          
4703 0         0 { sysseek INFIL, $offs, 0;
4704 0         0 sysread INFIL, $buf, $siz;
4705 0 0       0 if ($buf =~ m/^\d+$ws+\d+$ws+obj$ws*(.*)/os)
4706 0         0 { $del1 = $1;
4707             }
4708             }
4709             elsif (exists $unZipped{$nr})
4710 0         0 { $del1 = "$unZipped{$nr} endobj";
4711             }
4712             elsif ($embedded)
4713 0         0 { @objData = @{$$$p[0]->{$embedded}};
  0         0  
4714 0         0 unZipPrepare($embedded, $objData[oNR][0], $objData[oNR][1]);
4715 0         0 $del1 = "$unZipped{$nr} endobj";
4716             }
4717             }
4718 0         0 return (\$del1, \$del2, $objData[oKIDS], $objData[oTYPE]);
4719             }
4720              
4721              
4722             sub unZipPrepare
4723 0     0 0 0 { my ($nr, $offs, $size) = @_;
4724 0         0 my $buf;
4725 0 0       0 if ($offs)
4726 0         0 { sysseek INFIL, $offs, 0;
4727 0         0 sysread INFIL, $buf, $size;
4728             }
4729             else
4730 0         0 { $buf = getObject($nr);
4731             }
4732 0         0 my (%param, $stream, $str);
4733              
4734 0 0       0 if ($buf =~ m~^(\d+$ws+\d+$ws+obj$ws*<<[\w\d\/\s\[\]<>]+)stream\b~os)
4735 0         0 { $str = $1;
4736 0         0 $offs = length($str) + 7;
4737 0 0       0 if (substr($buf, $offs, 1) eq "\n")
4738 0         0 { $offs++;
4739             }
4740              
4741 0         0 for (split('/',$str))
4742 0 0       0 { if ($_ =~ m'^(\w+)(.*)'o)
4743 0   0     0 { $param{$1} = $2 || ' ';
4744             }
4745             }
4746 0         0 $stream = substr($buf, $offs, $param{'Length'});
4747 0   0     0 my $x = inflateInit()
4748             || die "Cannot create an inflation stream\n";
4749 0         0 my ($output, $status) = $x->inflate($stream);
4750 0 0       0 die "inflation failed\n"
4751             unless $status == 1;
4752              
4753 0         0 my $first = $param{'First'};
4754 0         0 my @oOffsets = (substr($output, 0, $first) =~ m'(\d+)\b'osg);
4755 0         0 my $i = 0;
4756 0         0 my $j = 1;
4757 0         0 my $bytes;
4758 0         0 while ($oOffsets[$i])
4759 0         0 { my $k = $j + 2;
4760 0 0       0 if ($oOffsets[$k])
4761 0         0 { $bytes = $oOffsets[$k] - $oOffsets[$j];
4762             }
4763             else
4764 0         0 { $bytes = length($output) - $first - $oOffsets[$j];
4765             }
4766 0         0 $unZipped{$oOffsets[$i]} = substr($output,($first + $oOffsets[$j]), $bytes);
4767 0         0 $i += 2;
4768 0         0 $j += 2;
4769             }
4770             }
4771             }
4772              
4773             ############################################
4774             # En definitionerna för en sida extraheras
4775             ############################################
4776              
4777             sub getPage
4778 2     2 0 7 { my ($infil, $sidnr, $action) = @_;
4779              
4780 2         6 my ($res, $i, $referens,$objNrSaved,$validStream, $formRes, @objData,
4781             @underObjekt, @sidObj, $strPos, $startSida, $sidor, $filId, $del1, $del2,
4782             $offs, $siz, $embedded, $vektor, $utrad, $robj, $valid, $Annots, $Names,
4783             $AcroForm, $AARoot, $AAPage);
4784              
4785 2         3 my $sidAcc = 0;
4786 2         10 my $seq = 0;
4787 2         4 $imSeq = 0;
4788 2         5 @skapa = ();
4789 2         4 undef $formCont;
4790              
4791              
4792 2         3 $objNrSaved = $objNr;
4793 2         6 my $fSource = $infil . '_' . $sidnr;
4794 2         4 my $checkidOld = $checkId;
4795 2         8 ($infil, $checkId) = findGet($infil, $checkidOld);
4796 2 0 33     6 if (($ldir) && ($checkId) && ($checkId ne $checkidOld))
      0        
4797 0         0 { $log .= "Cid~$checkId\n";
4798             }
4799 2         6 $form{$fSource}[fID] = $checkId;
4800 2         5 $checkId = '';
4801             $behandlad{$infil}->{old} = {}
4802 2 50       23 unless (defined $behandlad{$infil}->{old});
4803             $processed{$infil}->{oldObject} = {}
4804 2 50       10 unless (defined $processed{$infil}->{oldObject});
4805             $processed{$infil}->{unZipped} = {}
4806 2 50       28 unless (defined $processed{$infil}->{unZipped});
4807              
4808 2 50       6 if ($action eq 'print')
4809 2         8 { *old = $behandlad{$infil}->{old};
4810             }
4811             else
4812 0         0 { $behandlad{$infil}->{dummy} = {};
4813 0         0 *old = $behandlad{$infil}->{dummy};
4814             }
4815              
4816 2         5 *oldObject = $processed{$infil}->{oldObject};
4817 2         5 *unZipped = $processed{$infil}->{unZipped};
4818             $root = (exists $processed{$infil}->{root})
4819 2 50       7 ? $processed{$infil}->{root} : 0;
4820              
4821              
4822 2         19 my @stati = stat($infil);
4823 2 50       49 open (INFIL, "<$infil") || errLog("Couldn't open $infil, $!");
4824 2         5 binmode INFIL;
4825              
4826 2 50       17 if (! $root)
4827 2         9 { $root = xRefs($stati[7], $infil);
4828             }
4829              
4830             #############
4831             # Hitta root
4832             #############
4833              
4834 2         6 my $objektet = getObject($root);;
4835              
4836 2 50       8 if ($sidnr == 1)
4837 2 50       69 { if ($objektet =~ m|/AcroForm($ws+\d+$ws+\d+$ws+R)|so)
4838 0         0 { $AcroForm = $1;
4839             }
4840 2 50       52 if ($objektet =~ m|/Names$ws+(\d+)$ws+\d+$ws+R|so)
4841 0         0 { $Names = $1;
4842             }
4843             #################################################
4844             # Finns ett dictionary för Additional Actions ?
4845             #################################################
4846 2 50       39 if ($objektet =~ m|/AA$ws*\<\<$ws*[^\>]+[^\>]+|so) # AA är ett dictionary
4847 0         0 { my $k;
4848 0         0 my ($dummy, $obj) = split /\/AA/, $objektet;
4849 0         0 $obj =~ s/\<\
4850 0         0 $obj =~ s/\>\>/\>\>\#/gs;
4851 0         0 my @ord = split /\#/, $obj;
4852 0         0 for ($i = 0; $i <= $#ord; $i++)
4853 0         0 { $AARoot .= $ord[$i];
4854 0 0       0 if ($ord[$i] =~ m'\S+'os)
4855 0 0       0 { if ($ord[$i] =~ m'<<'os)
4856 0         0 { $k++; }
4857 0 0       0 if ($ord[$i] =~ m'>>'os)
4858 0         0 { $k--; }
4859 0 0       0 if ($k == 0)
4860 0         0 { last; }
4861             }
4862             }
4863             }
4864             }
4865              
4866             #
4867             # Hitta pages
4868             #
4869              
4870 2 50       61 if ($objektet =~ m|/Pages$ws+(\d+)$ws+\d+$ws+R|os)
4871 2         6 { $objektet = getObject($1);
4872 2 50       46 if ($objektet =~ m|/Count$ws+(\d+)|os)
4873 2         6 { $sidor = $1;
4874 2 50       5 if ($sidnr <= $sidor)
4875 2         7 { ($formRes, $valid) = kolla($objektet);
4876             }
4877             else
4878 0         0 { return 0;
4879             }
4880 2 50       6 if ($sidor > 1)
4881 0         0 { undef $AcroForm;
4882 0         0 undef $Names;
4883 0         0 undef $AARoot;
4884 0 0       0 if ($type eq 'docform')
4885 0         0 { errLog("prDocForm can only be used for single page documents - try prDoc or reformat $infil");
4886             }
4887             }
4888             }
4889             }
4890             else
4891 0         0 { errLog("Didn't find Pages in $infil - aborting"); }
4892              
4893 2 50       32 if ($objektet =~ m|/Kids$ws*\[([^\]]+)|os)
4894 2         5 { $vektor = $1; }
4895 2         46 while ($vektor =~ m|(\d+)$ws+\d+$ws+R|go)
4896 2         7 { push @sidObj, $1;
4897             }
4898              
4899 2         4 my $bryt1 = -20; # Hängslen
4900 2         4 my $bryt2 = -20; # Svångrem för att undvika oändliga loopar
4901              
4902 2         6 while ($sidAcc < $sidnr)
4903 2         5 { @underObjekt = @sidObj;
4904 2         5 @sidObj = ();
4905 2         4 $bryt1++;
4906 2         4 for my $uO (@underObjekt)
4907 2         3 { $objektet = getObject($uO);
4908 2 50       29 if ($objektet =~ m|/Count$ws+(\d+)|os)
4909 0 0       0 { if (($sidAcc + $1) < $sidnr)
4910 0         0 { $sidAcc += $1; }
4911             else
4912 0         0 { ($formRes, $valid) = kolla($objektet, $formRes);
4913 0 0       0 if ($objektet =~ m|/Kids$ws*\[([^\]]+)|os)
4914 0         0 { $vektor = $1; }
4915 0         0 while ($vektor =~ m/(\d+)$ws+\d+$ws+R/gso)
4916 0         0 { push @sidObj, $1; }
4917 0         0 last;
4918             }
4919             }
4920             else
4921 2         5 { $sidAcc++; }
4922 2 50       5 if ($sidAcc == $sidnr)
4923 2         5 { $seq = $uO;
4924 2         4 last; }
4925 0         0 $bryt2++;
4926             }
4927 2 50 33     11 if (($bryt1 > $sidnr) || ($bryt2 > $sidnr)) # Bryt oändliga loopar
4928 0         0 { last; }
4929             }
4930              
4931 2         6 ($formRes, $validStream) = kolla($objektet, $formRes);
4932 2         5 $startSida = $seq;
4933              
4934 2 50       6 if ($sidor == 1)
4935             { #################################################
4936             # Kontrollera Page-objektet för annoteringar
4937             #################################################
4938              
4939 2 50       27 if ($objektet =~ m|/Annots$ws*([^\/]+)|so)
4940 0         0 { $Annots = $1;
4941             }
4942             #################################################
4943             # Finns ett dictionary för Additional Actions ?
4944             #################################################
4945 2 50       44 if ($objektet =~ m|/AA$ws*\<\<$ws*[^\>]+[^\>]+|so) # AA är ett dictionary. Hela kopieras
4946 0         0 { my $k;
4947 0         0 my ($dummy, $obj) = split /\/AA/, $objektet;
4948 0         0 $obj =~ s/\<\
4949 0         0 $obj =~ s/\>\>/\>\>\#/gs;
4950 0         0 my @ord = split /\#/, $obj;
4951 0         0 for ($i = 0; $i <= $#ord; $i++)
4952 0         0 { $AAPage .= $ord[$i];
4953 0 0       0 if ($ord[$i] =~ m'\S+'s)
4954 0 0       0 { if ($ord[$i] =~ m'<<'s)
4955 0         0 { $k++; }
4956 0 0       0 if ($ord[$i] =~ m'>>'s)
4957 0         0 { $k--; }
4958 0 0       0 if ($k == 0)
4959 0         0 { last; }
4960             }
4961             }
4962             }
4963             }
4964              
4965 2         7 my $rform = \$form{$fSource};
4966 2         7 @$$rform[fRESOURCE] = $formRes;
4967 2         65 my @BBox;
4968 2 50       8 if (defined $formBox[0])
4969 2         4 { $BBox[0] = $formBox[0]; }
4970             else
4971 0         0 { $BBox[0] = $genLowerX; }
4972              
4973 2 50       5 if (defined $formBox[1])
4974 2         4 { $BBox[1] = $formBox[1]; }
4975             else
4976 0         0 { $BBox[1] = $genLowerY; }
4977              
4978 2 50       5 if (defined $formBox[2])
4979 2         4 { $BBox[2] = $formBox[2]; }
4980             else
4981 0         0 { $BBox[2] = $genUpperX; }
4982              
4983 2 50       5 if (defined $formBox[3])
4984 2         4 { $BBox[3] = $formBox[3]; }
4985             else
4986 0         0 { $BBox[3] = $genUpperY; }
4987              
4988 2         4 @{$form{$fSource}[fBBOX]} = @BBox;
  2         10  
4989              
4990 2 50       5 if ($formCont)
4991 2         4 { $seq = $formCont;
4992 2         3 ($objektet, $offs, $siz, $embedded) = getObject($seq);
4993              
4994 2         7 $robj = \$$$rform[fOBJ]->{$seq};
4995 2         4 @{$$$robj[oNR]} = ($offs, $siz, $embedded);
  2         8  
4996 2         12 $$$robj[oFORM] = 'Y';
4997 2         7 $form{$fSource}[fMAIN] = $seq;
4998 2 50       85 if ($objektet =~ m/^(\d+$ws+\d+$ws+obj$ws*<<)(.+)(>>$ws*stream)/so)
4999 2         6 { $del1 = $2;
5000 2         8 $strPos = length($1) + length($2) + length($3);
5001 2         4 $$$robj[oPOS] = length($1);
5002 2         5 $$$robj[oSTREAMP] = $strPos;
5003 2         3 my $nyDel1;
5004 2         4 $nyDel1 = '<
5005 2         9 $nyDel1 .= "/Resources $formRes" .
5006             "/BBox \[ $BBox[0] $BBox[1] $BBox[2] $BBox[3]\]" .
5007             # "/Matrix \[ 1 0 0 1 0 0 \]" .
5008             $del1;
5009 2 50       5 if ($action eq 'print')
5010 2         4 { $objNr++;
5011 2         5 $objekt[$objNr] = $pos;
5012             }
5013 2         4 $referens = $objNr;
5014              
5015 2         97 $res = ($nyDel1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs);
  2         7  
5016 2 50       7 if ($res)
5017 2         4 { $$$robj[oKIDS] = 1; }
5018 2 50       5 if ($action eq 'print')
5019 2         6 { $utrad = "$referens 0 obj\n" . "$nyDel1" . ">>\nstream";
5020 2         5 $del2 = substr($objektet, $strPos);
5021 2         56 $utrad .= $del2;
5022 2         68 $pos += syswrite UTFIL, $utrad;
5023             }
5024 2         11 $form{$fSource}[fVALID] = $validStream;
5025             }
5026             else # Endast resurserna kan behandlas
5027 0         0 { $formRes =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0         0  
5028             }
5029             }
5030             else # Endast resurserna kan behandlas
5031 0         0 { $formRes =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0         0  
5032             }
5033              
5034 2         5 my $preLength;
5035 2         7 while (scalar @skapa)
5036 4         10 { my @process = @skapa;
5037 4         7 @skapa = ();
5038 4         9 for (@process)
5039 4         4 { my $Font;
5040 4         8 my $gammal = $$_[0];
5041 4         6 my $ny = $$_[1];
5042 4         9 ($objektet, $offs, $siz, $embedded) = getObject($gammal);
5043 4         13 $robj = \$$$rform[fOBJ]->{$gammal};
5044 4         5 @{$$$robj[oNR]} = ($offs, $siz, $embedded);
  4         12  
5045 4 50       82 if($objektet =~ m/^(\d+$ws+\d+$ws+obj$ws*<<)(.+)(>>$ws*stream)/os)
5046 0         0 { $del1 = $2;
5047 0         0 $strPos = length ($1) + length($2) + length($3);
5048 0         0 $$$robj[oPOS] = length($1);
5049 0         0 $$$robj[oSTREAMP] = $strPos;
5050              
5051             ######## En bild ########
5052 0 0       0 if ($del1 =~ m|/Subtype$ws*/Image|so)
5053 0         0 { $imSeq++;
5054 0         0 $$$robj[oIMAGENR] = $imSeq;
5055 0         0 push @{$$$rform[fIMAGES]}, $gammal;
  0         0  
5056              
5057 0 0       0 if ($del1 =~ m|/Width$ws+(\d+)|os)
5058 0         0 { $$$robj[oWIDTH] = $1; }
5059 0 0       0 if ($del1 =~ m|/Height$ws+(\d+)|os)
5060 0         0 { $$$robj[oHEIGHT] = $1; }
5061             }
5062 0         0 $res = ($del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs);
  0         0  
5063 0 0       0 if ($res)
5064 0         0 { $$$robj[oKIDS] = 1; }
5065 0 0       0 if ($action eq 'print')
5066 0         0 { $objekt[$ny] = $pos;
5067 0         0 $utrad = "$ny 0 obj\n<<" . "$del1" . '>>stream';
5068 0         0 $del2 = substr($objektet, $strPos);
5069 0         0 $utrad .= $del2;
5070             }
5071             }
5072             else
5073 4 50       83 { if ($objektet =~ m|^(\d+$ws+\d+$ws+obj$ws*)|os)
5074 4         9 { $preLength = length($1);
5075 4         8 $$$robj[oPOS] = $preLength;
5076 4         10 $objektet = substr($objektet, $preLength);
5077             }
5078             else
5079 0         0 { $$$robj[oPOS] = 0;
5080             }
5081 4         52 $res = ($objektet =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs);
  2         6  
5082 4 100       11 if ($res)
5083 2         5 { $$$robj[oKIDS] = 1; }
5084 4 50       88 if ($objektet =~ m|/Subtype$ws*/Image|so)
    100          
5085 0         0 { $imSeq++;
5086 0         0 $$$robj[oIMAGENR] = $imSeq;
5087 0         0 push @{$$$rform[fIMAGES]}, $gammal;
  0         0  
5088             ###################################
5089             # Sparar dimensionerna för bilden
5090             ###################################
5091 0 0       0 if ($del1 =~ m|/Width$ws+(\d+)|os)
5092 0         0 { $$$robj[oWIDTH] = $1; }
5093              
5094 0 0       0 if ($del1 =~ m|/Height$ws+(\d+)|os)
5095 0         0 { $$$robj[oHEIGHT] = $1; }
5096             }
5097             elsif ($objektet =~ m|/BaseFont$ws*/([^\s\/]+)|os)
5098 2         5 { $Font = $1;
5099 2         6 $$$robj[oTYPE] = 'Font';
5100 2         5 $$$robj[oNAME] = $Font;
5101 2 50 33     11 if ((! exists $font{$Font})
5102             && ($action))
5103 2         5 { $fontNr++;
5104 2         6 $font{$Font}[foINTNAMN] = 'Ft' . $fontNr;
5105 2         5 $font{$Font}[foORIGINALNR] = $gammal;
5106 2         4 $fontSource{$Font}[foSOURCE] = $fSource;
5107 2         5 $fontSource{$Font}[foORIGINALNR] = $gammal;
5108 2 50       31 if ($objektet =~ m|/Subtype$ws*/Type0|os)
5109 0         0 { $font{$Font}[foTYP] = 1;
5110             }
5111 2 50       6 if ($action eq 'print')
5112 2         5 { $font{$Font}[foREFOBJ] = $ny;
5113 2         7 $objRef{'Ft' . $fontNr} = $ny;
5114             }
5115             }
5116             }
5117              
5118 4 50       10 if ($action eq 'print')
5119 4         7 { $objekt[$ny] = $pos;
5120 4         8 $utrad = "$ny 0 obj $objektet";
5121             }
5122             }
5123 4 50       11 if ($action eq 'print')
5124 4         96 { $pos += syswrite UTFIL, $utrad;
5125             }
5126             }
5127             }
5128              
5129 2         7 my $ref = \$form{$fSource};
5130 2         4 my @kids;
5131             my @nokids;
5132              
5133             #################################################################
5134             # lägg upp vektorer över vilka objekt som har KIDS eller NOKIDS
5135             #################################################################
5136              
5137 2         3 for my $key (keys %{$$$ref[fOBJ]})
  2         9  
5138 6         12 { $robj = \$$$ref[fOBJ]->{$key};
5139 6 100       32 if (! defined $$$robj[oFORM])
5140 4 100       13 { if (defined $$$robj[oKIDS])
5141 2         4 { push @kids, $key; }
5142             else
5143 2         5 { push @nokids, $key; }
5144             }
5145 6 50 33     16 if ((defined $$$robj[0]->[2]) && (! exists $$$ref[fOBJ]->{$$$robj[0]->[2]}))
5146 0         0 { $$$ref[fOBJ]->{$$$robj[0]->[2]}->[0] = $oldObject{$$$robj[0]->[2]};
5147             }
5148             }
5149 2 50       5 if (scalar @kids)
5150 2         14 { $form{$fSource}[fKIDS] = \@kids;
5151             }
5152 2 50       5 if (scalar @nokids)
5153 2         4 { $form{$fSource}[fNOKIDS] = \@nokids;
5154             }
5155              
5156 2 50       5 if ($action ne 'print')
5157 0         0 { $objNr = $objNrSaved; # Restore objNo if nothing was printed
5158             }
5159              
5160 2         6 $behandlad{$infil}->{dummy} = {};
5161 2         5 *old = $behandlad{$infil}->{dummy};
5162              
5163 2         4 $objNrSaved = $objNr; # Save objNo
5164              
5165 2 50       5 if ($sidor == 1)
5166 2         4 { @skapa = ();
5167 2         5 $old{$startSida} = $sidObjNr;
5168 2         4 my $ref = \$intAct{$fSource};
5169 2         6 @$$ref[iSTARTSIDA] = $startSida;
5170 2 50       6 if (defined $Names)
5171 0         0 { @$$ref[iNAMES] = $Names;
5172 0         0 quickxform($Names);
5173             }
5174 2 50       7 if (defined $AcroForm)
5175 0         0 { @$$ref[iACROFORM] = $AcroForm;
5176 0         0 $AcroForm =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0         0  
5177             }
5178 2 50       4 if (defined $AARoot)
5179 0         0 { @$$ref[iAAROOT] = $AARoot;
5180 0         0 $AARoot =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0         0  
5181             }
5182 2 50       6 if (defined $AAPage)
5183 0         0 { @$$ref[iAAPAGE] = $AAPage;
5184 0         0 $AAPage =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0         0  
5185             }
5186 2 50       5 if (defined $Annots)
5187 0         0 { my @array;
5188 0 0       0 if ($Annots =~ m'\[([^\[\]]*)\]'os)
5189 0         0 { $Annots = $1;
5190 0         0 @array = ($Annots =~ m/\b(\d+)$ws+\d+$ws+R\b/ogs);
5191             }
5192             else
5193 0 0       0 { if ($Annots =~ m/\b(\d+)$ws+\d+$ws+R\b/os)
5194 0         0 { $Annots = getObject($1);
5195 0         0 @array = ($Annots =~ m/\b(\d+)$ws+\d+$ws+R\b/ogs);
5196             }
5197             }
5198 0         0 @$$ref[iANNOTS] = \@array;
5199 0         0 $Annots =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0         0  
5200             }
5201              
5202 2         6 while (scalar @skapa)
5203 0         0 { my @process = @skapa;
5204 0         0 @skapa = ();
5205 0         0 for (@process)
5206 0         0 { my $gammal = $$_[0];
5207 0         0 my $ny = $$_[1];
5208 0         0 ($objektet, $offs, $siz, $embedded) = getObject($gammal);
5209 0         0 $robj = \$$$ref[fOBJ]->{$gammal};
5210 0         0 @{$$$robj[oNR]} = ($offs, $siz, $embedded);
  0         0  
5211 0 0       0 if ($objektet
5212             =~ m/^(\d+$ws+\d+$ws+obj$ws*<<)(.+)(>>$ws*stream)/os)
5213 0         0 { $del1 = $2;
5214 0         0 $$$robj[oPOS] = length($1);
5215 0         0 $$$robj[oSTREAMP] = length($1) + length($2) + length($3);
5216              
5217 0         0 $res = ($del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs);
  0         0  
5218 0 0       0 if ($res)
5219 0         0 { $$$robj[oKIDS] = 1; }
5220             }
5221             else
5222 0 0       0 { if ($objektet =~ m/^(\d+$ws+\d+$ws+obj)/os)
5223 0         0 { my $preLength = length($1);
5224 0         0 $$$robj[oPOS] = $preLength;
5225 0         0 $objektet = substr($objektet, $preLength);
5226              
5227 0         0 $res = ($objektet =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs);
  0         0  
5228 0 0       0 if ($res)
5229 0         0 { $$$robj[oKIDS] = 1; }
5230             }
5231             }
5232             }
5233             }
5234 2         4 for my $key (keys %{$$$ref[fOBJ]})
  2         6  
5235 0         0 { $robj = \$$$ref[fOBJ]->{$key};
5236 0 0 0     0 if ((defined $$$robj[0]->[2]) && (! exists $$$ref[fOBJ]->{$$$robj[0]->[2]}))
5237 0         0 { $$$ref[fOBJ]->{$$$robj[0]->[2]}->[0] = $oldObject{$$$robj[0]->[2]};
5238             }
5239             }
5240             }
5241              
5242 2         3 $objNr = $objNrSaved;
5243 2         7 $processed{$infil}->{root} = $root;
5244 2         22 close INFIL;
5245 2         19 return $referens;
5246             }
5247              
5248             ##################################################
5249             # Översätter ett gammalt objektnr till ett nytt
5250             # och sparar en tabell med vad som skall skapas
5251             ##################################################
5252              
5253             sub xform
5254 4 50   4 0 10 { if (exists $old{$1})
5255 0         0 { $old{$1};
5256             }
5257             else
5258 4         14 { push @skapa, [$1, ++$objNr];
5259 4         22 $old{$1} = $objNr;
5260             }
5261             }
5262              
5263             sub kolla
5264             { #
5265             # Resurser
5266             #
5267 4     4 0 6 my $obj = shift;
5268 4         9 my $resources = shift;
5269 4         4 my $valid;
5270              
5271 4 100       197 if ($obj =~ m/MediaBox$ws*\[$ws*([\-\.\d]+)$ws+([\-\.\d]+)$ws+([\-\.\d]+)$ws+([\-\.\d]+)/os)
5272 2         7 { $formBox[0] = $1;
5273 2         4 $formBox[1] = $2;
5274 2         5 $formBox[2] = $3;
5275 2         7 $formBox[3] = $4;
5276             }
5277              
5278 4 100       113 if ($obj =~ m|/Contents$ws+(\d+)|so)
    50          
5279 2         5 { $formCont = $1;
5280 2         5 my $cObj = getObject($formCont, 1, 1);
5281 2 50       47 if ($cObj =~ m/^$ws*\[[^\]]+\]$ws*$/os)
5282 0         0 { $valid = 0;
5283 0         0 undef $formCont;
5284             }
5285             else
5286 2         5 { $valid = 1;
5287             }
5288             }
5289             elsif ($obj =~ m|/Contents$ws*\[$ws*(\d+)$ws+\d+$ws+R$ws*\]|so)
5290 0         0 { $formCont = $1;
5291 0         0 $valid = 1;
5292             }
5293              
5294 4 100       17 if ($obj =~ m'^(.+/Resources)'so)
5295 2 50       72 { if ($obj =~ m/Resources($ws+\d+$ws+\d+$ws+R)/os) # Hänvisning
5296 2         5 { $resources = $1; }
5297             else # Resurserna är ett dictionary. Hela kopieras
5298 0         0 { my $dummy;
5299             my $i;
5300 0         0 my $k;
5301 0         0 undef $resources;
5302 0         0 ($dummy, $obj) = split /\/Resources/, $obj;
5303 0         0 $obj =~ s/\<\
5304 0         0 $obj =~ s/\>\>/\>\>\#/gs;
5305 0         0 my @ord = split /\#/, $obj;
5306 0         0 for ($i = 0; $i <= $#ord; $i++)
5307 0         0 { $resources .= $ord[$i];
5308 0 0       0 if ($ord[$i] =~ m'\S+'s)
5309 0 0       0 { if ($ord[$i] =~ m'<<'s)
5310 0         0 { $k++; }
5311 0 0       0 if ($ord[$i] =~ m'>>'s)
5312 0         0 { $k--; }
5313 0 0       0 if ($k == 0)
5314 0         0 { last; }
5315             }
5316             }
5317             }
5318             }
5319 4         12 return ($resources, $valid);
5320             }
5321              
5322             ##############################
5323             # Ett formulär (åter)skapas
5324             ##############################
5325              
5326             sub byggForm
5327 3     3   44 { no warnings;
  3         7  
  3         20119  
5328 0     0 0   my ($infil, $sidnr) = @_;
5329              
5330 0           my ($res, $corr, $nyDel1, $formRes, $del1, $del2, $kids, $typ, $nr,
5331             $utrad);
5332              
5333 0           my $fSource = $infil . '_' . $sidnr;
5334 0           my @stati = stat($infil);
5335              
5336             $behandlad{$infil}->{old} = {}
5337 0 0         unless (defined $behandlad{$infil}->{old});
5338             $processed{$infil}->{oldObject} = {}
5339 0 0         unless (defined $processed{$infil}->{oldObject});
5340             $processed{$infil}->{unZipped} = {}
5341 0 0         unless (defined $processed{$infil}->{unZipped});
5342              
5343 0           *old = $behandlad{$infil}->{old};
5344 0           *oldObject = $processed{$infil}->{oldObject};
5345 0           *unZipped = $processed{$infil}->{unZipped};
5346              
5347 0 0         if ($form{$fSource}[fID] != $stati[9])
5348 0           { errLog("$stati[9] ne $form{$fSource}[fID] aborts");
5349             }
5350 0 0         if ($checkId)
5351 0 0         { if ($checkId ne $stati[9])
5352 0           { my $mess = "$checkId \<\> $stati[9] \n"
5353             . "The Pdf-file $fSource has not the correct modification time. \n"
5354             . "The program is aborted";
5355 0           errLog($mess);
5356             }
5357 0           undef $checkId;
5358             }
5359 0 0         if ($ldir)
5360 0           { $log .= "Cid~$stati[9]\n";
5361             }
5362              
5363 0 0         open (INFIL, "<$infil") || errLog("The file $infil couldn't be opened, aborting $!");
5364 0           binmode INFIL;
5365              
5366             ####################################################
5367             # Objekt utan referenser kopieras och skrivs
5368             ####################################################
5369              
5370 0           for my $key (@{$form{$fSource}->[fNOKIDS]})
  0            
5371 0 0 0       { if ((defined $old{$key}) && ($objekt[$old{$key}])) # already processed
5372 0           { next;
5373             }
5374              
5375 0 0         if (! defined $old{$key})
5376 0           { $old{$key} = ++$objNr;
5377             }
5378 0           $nr = $old{$key};
5379 0           $objekt[$nr] = $pos;
5380              
5381 0           ($del1, $del2, $kids, $typ) = getKnown(\$form{$fSource},$key);
5382              
5383 0 0         if ($typ eq 'Font')
5384 0           { my $Font = ${$form{$fSource}}[0]->{$key}->[oNAME];
  0            
5385 0 0         if (! defined $font{$Font}[foINTNAMN])
5386 0           { $fontNr++;
5387 0           $font{$Font}[foINTNAMN] = 'Ft' . $fontNr;
5388 0           $font{$Font}[foREFOBJ] = $nr;
5389 0           $objRef{'Ft' . $fontNr} = $nr;
5390             }
5391             }
5392 0 0         if (! defined $$del2)
5393 0           { $utrad = "$nr 0 obj " . $$del1;
5394             }
5395             else
5396 0           { $utrad = "$nr 0 obj\n<<" . $$del1 . $$del2;
5397             }
5398 0           $pos += syswrite UTFIL, $utrad;
5399             }
5400              
5401             #######################################################
5402             # Objekt med referenser kopieras, behandlas och skrivs
5403             #######################################################
5404 0           for my $key (@{$form{$fSource}->[fKIDS]})
  0            
5405 0 0 0       { if ((defined $old{$key}) && ($objekt[$old{$key}])) # already processed
5406 0           { next;
5407             }
5408              
5409 0 0         if (! defined $old{$key})
5410 0           { $old{$key} = ++$objNr;
5411             }
5412 0           $nr = $old{$key};
5413              
5414 0           $objekt[$nr] = $pos;
5415              
5416 0           ($del1, $del2, $kids, $typ) = getKnown(\$form{$fSource},$key);
5417              
5418 0           $$del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/translate() . ' 0 R'/oegs;
  0            
5419              
5420 0 0         if (defined $$del2)
5421 0           { $utrad = "$nr 0 obj\n<<" . $$del1 . $$del2;
5422             }
5423             else
5424 0           { $utrad = "$nr 0 obj " . $$del1;
5425             }
5426              
5427 0 0 0       if (($typ) && ($typ eq 'Font'))
5428 0           { my $Font = $form{$fSource}[0]->{$key}->[oNAME];
5429 0 0         if (! defined $font{$Font}[foINTNAMN])
5430 0           { $fontNr++;
5431 0           $font{$Font}[foINTNAMN] = 'Ft' . $fontNr;
5432 0           $font{$Font}[foREFOBJ] = $nr;
5433 0           $objRef{'Ft' . $fontNr} = $nr;
5434             }
5435             }
5436              
5437 0           $pos += syswrite UTFIL, $utrad;
5438             }
5439              
5440             #################################
5441             # Formulärobjektet behandlas
5442             #################################
5443              
5444 0           my $key = $form{$fSource}->[fMAIN];
5445 0 0         if (! defined $key)
5446 0           { return undef;
5447             }
5448              
5449 0 0         if (exists $old{$key}) # already processed
5450 0           { close INFIL;
5451 0           return $old{$key};
5452             }
5453              
5454 0           $nr = ++$objNr;
5455              
5456 0           $objekt[$nr] = $pos;
5457              
5458 0           $formRes = $form{$fSource}->[fRESOURCE];
5459              
5460 0           ($del1, $del2) = getKnown(\$form{$fSource}, $key);
5461              
5462 0           $nyDel1 = '<
5463             $nyDel1 .= "/Resources $formRes" .
5464             '/BBox [' .
5465             $form{$fSource}->[fBBOX]->[0] . ' ' .
5466             $form{$fSource}->[fBBOX]->[1] . ' ' .
5467             $form{$fSource}->[fBBOX]->[2] . ' ' .
5468 0           $form{$fSource}->[fBBOX]->[3] . ' ]' .
5469             # "\]/Matrix \[ $sX 0 0 $sX $tX $tY \]" .
5470             $$del1;
5471 0           $nyDel1 =~ s/\b(\d+)$ws+\d+$ws+R\b/translate() . ' 0 R'/oegs;
  0            
5472              
5473 0           $utrad = "$nr 0 obj" . $nyDel1 . $$del2;
5474              
5475 0           $pos += syswrite UTFIL, $utrad;
5476 0           close INFIL;
5477              
5478 0           return $nr;
5479             }
5480              
5481             ##################
5482             # En bild läses
5483             ##################
5484              
5485             sub getImage
5486 0     0 0   { my ($infil, $sidnr, $bildnr, $key) = @_;
5487 0 0         if (! defined $key)
5488 0           { errLog("Can't find image $bildnr on page $sidnr in file $infil, aborts");
5489             }
5490              
5491 0           @skapa = ();
5492 0           my ($res, $corr, $nyDel1, $del1, $del2, $nr, $utrad);
5493 0           my $fSource = $infil . '_' . $sidnr;
5494 0           my $iSource = $fSource . '_' . $bildnr;
5495              
5496             $behandlad{$infil}->{old} = {}
5497 0 0         unless (defined $behandlad{$infil}->{old});
5498             $processed{$infil}->{oldObject} = {}
5499 0 0         unless (defined $processed{$infil}->{oldObject});
5500             $processed{$infil}->{unZipped} = {}
5501 0 0         unless (defined $processed{$infil}->{unZipped});
5502              
5503 0           *old = $behandlad{$infil}->{old};
5504 0           *oldObject = $processed{$infil}->{oldObject};
5505 0           *unZipped = $processed{$infil}->{unZipped};
5506              
5507 0           my @stati = stat($infil);
5508              
5509 0 0         if ($form{$fSource}[fID] != $stati[9])
5510 0           { errLog("$stati[9] ne $form{$fSource}[fID], modification time has changed, aborting");
5511             }
5512              
5513 0 0         if (exists $old{$key})
5514 0           { return $old{$key};
5515             }
5516              
5517 0 0         open (INFIL, "<$infil") || errLog("The file $infil couldn't be opened, $!");
5518 0           binmode INFIL;
5519              
5520             #########################################################
5521             # En bild med referenser kopieras, behandlas och skrivs
5522             #########################################################
5523              
5524 0           $nr = ++$objNr;
5525 0           $old{$key} = $nr;
5526              
5527 0           $objekt[$nr] = $pos;
5528              
5529 0           ($del1, $del2) = getKnown(\$form{$fSource}, $key);
5530              
5531 0           $$del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
5532 0 0         if (defined $$del2)
5533 0           { $utrad = "$nr 0 obj\n<<" . $$del1 . $$del2;
5534             }
5535             else
5536 0           { $utrad = "$nr 0 obj " . $$del1;
5537             }
5538 0           $pos += syswrite UTFIL, $utrad;
5539             ##################################
5540             # Skriv ut underordnade objekt
5541             ##################################
5542 0           while (scalar @skapa)
5543 0           { my @process = @skapa;
5544 0           @skapa = ();
5545 0           for (@process)
5546 0           { my $gammal = $$_[0];
5547 0           my $ny = $$_[1];
5548              
5549 0           ($del1, $del2) = getKnown(\$form{$fSource}, $gammal);
5550              
5551 0           $$del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
5552 0 0         if (defined $$del2)
5553 0           { $utrad = "$ny 0 obj\n<<" . $$del1 . $$del2;
5554             }
5555             else
5556 0           { $utrad = "$ny 0 obj " . $$del1;
5557             }
5558 0           $objekt[$ny] = $pos;
5559 0           $pos += syswrite UTFIL, $utrad;
5560             }
5561             }
5562              
5563 0           close INFIL;
5564 0           return $nr;
5565              
5566             }
5567              
5568             ##############################################################
5569             # Interaktiva funktioner knutna till ett formulär återskapas
5570             ##############################################################
5571              
5572             sub AcroFormsEtc
5573 0     0 0   { my ($infil, $sidnr) = @_;
5574              
5575 0           my ($Names, $AARoot, $AAPage, $AcroForm);
5576 0           @skapa = ();
5577              
5578 0           my ($res, $corr, $nyDel1, @objData, $del1, $del2, $utrad);
5579 0           my $fSource = $infil . '_' . $sidnr;
5580              
5581             $behandlad{$infil}->{old} = {}
5582 0 0         unless (defined $behandlad{$infil}->{old});
5583             $processed{$infil}->{oldObject} = {}
5584 0 0         unless (defined $processed{$infil}->{oldObject});
5585             $processed{$infil}->{unZipped} = {}
5586 0 0         unless (defined $processed{$infil}->{unZipped});
5587              
5588 0           *old = $behandlad{$infil}->{old};
5589 0           *oldObject = $processed{$infil}->{oldObject};
5590 0           *unZipped = $processed{$infil}->{unZipped};
5591              
5592 0           my @stati = stat($infil);
5593 0 0         if ($form{$fSource}[fID] != $stati[9])
5594 0           { print "$stati[9] ne $form{$fSource}[fID]\n";
5595 0           errLog("Modification time for $fSource has changed, aborting");
5596             }
5597              
5598 0 0         open (INFIL, "<$infil") || errLog("The file $infil couldn't be opened, aborting $!");
5599 0           binmode INFIL;
5600              
5601 0           my $fdSidnr = $intAct{$fSource}[iSTARTSIDA];
5602 0           $old{$fdSidnr} = $sidObjNr;
5603              
5604 0 0 0       if (($intAct{$fSource}[iNAMES]) ||(scalar @jsfiler) || (scalar @inits) || (scalar %fields))
      0        
      0        
5605 0           { $Names = behandlaNames($intAct{$fSource}[iNAMES], $fSource);
5606             }
5607              
5608             ##################################
5609             # Referenser behandlas och skrivs
5610             ##################################
5611              
5612 0 0         if (defined $intAct{$fSource}[iACROFORM])
5613 0           { $AcroForm = $intAct{$fSource}[iACROFORM];
5614 0           $AcroForm =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
5615             }
5616 0 0         if (defined $intAct{$fSource}[iAAROOT])
5617 0           { $AARoot = $intAct{$fSource}[iAAROOT];
5618 0           $AARoot =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
5619             }
5620              
5621 0 0         if (defined $intAct{$fSource}[iAAPAGE])
5622 0           { $AAPage = $intAct{$fSource}[iAAPAGE];
5623 0           $AAPage =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
5624             }
5625 0 0         if (defined $intAct{$fSource}[iANNOTS])
5626 0           { for (@{$intAct{$fSource}[iANNOTS]})
  0            
5627 0           { push @annots, quickxform($_);
5628             }
5629             }
5630              
5631             ##################################
5632             # Skriv ut underordnade objekt
5633             ##################################
5634 0           while (scalar @skapa)
5635 0           { my @process = @skapa;
5636 0           @skapa = ();
5637 0           for (@process)
5638 0           { my $gammal = $$_[0];
5639 0           my $ny = $$_[1];
5640              
5641 0           my $oD = \@{$intAct{$fSource}[0]->{$gammal}};
  0            
5642 0           @objData = @{$$oD[oNR]};
  0            
5643              
5644 0 0         if (defined $$oD[oSTREAMP])
5645 0           { $res = sysseek INFIL, ($objData[0] + $$oD[oPOS]), 0;
5646 0           $corr = sysread INFIL, $del1, ($$oD[oSTREAMP] - $$oD[oPOS]) ;
5647 0 0         if (defined $$oD[oKIDS])
5648 0           { $del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
5649             }
5650 0           $res = sysread INFIL, $del2, ($objData[1] - $corr);
5651 0           $utrad = "$ny 0 obj\n<<" . $del1 . $del2;
5652             }
5653             else
5654 0           { $del1 = getObject($gammal);
5655 0           $del1 = substr($del1, $$oD[oPOS]);
5656 0 0         if (defined $$oD[oKIDS])
5657 0           { $del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
5658             }
5659 0           $utrad = "$ny 0 obj " . $del1;
5660             }
5661              
5662 0           $objekt[$ny] = $pos;
5663 0           $pos += syswrite UTFIL, $utrad;
5664             }
5665             }
5666              
5667 0           close INFIL;
5668 0           return ($Names, $AARoot, $AAPage, $AcroForm);
5669             }
5670              
5671             ##############################
5672             # Ett namnobjekt extraheras
5673             ##############################
5674              
5675             sub extractName
5676 0     0 0   { my ($infil, $sidnr, $namn) = @_;
5677              
5678 0           my ($res, $del1, $resType, $key, $corr, $formRes, $kids, $nr, $utrad);
5679 0           my $del2 = '';
5680 0           @skapa = ();
5681              
5682             $behandlad{$infil}->{old} = {}
5683 0 0         unless (defined $behandlad{$infil}->{old});
5684             $processed{$infil}->{oldObject} = {}
5685 0 0         unless (defined $processed{$infil}->{oldObject});
5686             $processed{$infil}->{unZipped} = {}
5687 0 0         unless (defined $processed{$infil}->{unZipped});
5688              
5689 0           *old = $behandlad{$infil}->{old};
5690 0           *oldObject = $processed{$infil}->{oldObject};
5691 0           *unZipped = $processed{$infil}->{unZipped};
5692              
5693 0           my $fSource = $infil . '_' . $sidnr;
5694              
5695 0           my @stati = stat($infil);
5696              
5697 0 0         if ($form{$fSource}[fID] != $stati[9])
5698 0           { errLog("$stati[9] ne $form{$fSource}[fID] aborts");
5699             }
5700 0 0         if ($checkId)
5701 0 0         { if ($checkId ne $stati[9])
5702 0           { my $mess = "$checkId \<\> $stati[9] \n"
5703             . "The Pdf-file $fSource has not the correct modification time. \n"
5704             . "The program is aborted";
5705 0           errLog($mess);
5706             }
5707 0           undef $checkId;
5708             }
5709 0 0         if ($ldir)
5710 0           { $log .= "Cid~$stati[9]\n";
5711             }
5712              
5713 0 0         open (INFIL, "<$infil") || errLog("The file $infil couldn't be opened, aborting $!");
5714 0           binmode INFIL;
5715              
5716             #################################
5717             # Resurserna läses
5718             #################################
5719              
5720 0           $formRes = $form{$fSource}->[fRESOURCE];
5721              
5722 0 0         if ($formRes !~ m'<<.*>>'os) # If not a directory, get it
5723 0 0         { if ($formRes =~ m/\b(\d+)$ws+\d+$ws+R/o)
5724 0           { $key = $1;
5725 0           $formRes = getKnown(\$form{$fSource}, $key);
5726             }
5727             else
5728 0           { return undef;
5729             }
5730             }
5731 0           undef $key;
5732 0           while ($formRes =~ m|\/(\w+)$ws*\<\<([^>]+)\>\>|osg)
5733 0           { $resType = $1;
5734 0           my $str = $2;
5735 0 0         if ($str =~ m|$namn$ws+(\d+)$ws+\d+$ws+R|s)
5736 0           { $key = $1;
5737 0           last;
5738             }
5739             }
5740 0 0         if (! defined $key) # Try to expand the references
5741 0           { my ($str, $del1, $del2);
5742 0           while ($formRes =~ m|(\/\w+)$ws+(\d+)$ws+\d+$ws+R|ogs)
5743 0           { $str .= $1 . ' ';
5744 0           ($del1, $del2) = getKnown(\$form{$fSource}, $2);
5745 0           my $string = $$del1;
5746 0           $str .= $string . ' ';
5747             }
5748 0           $formRes = $str;
5749 0           while ($formRes =~ m|\/(\w+)$ws*\<\<([^>]+)\>\>|osg)
5750 0           { $resType = $1;
5751 0           my $str = $2;
5752 0 0         if ($str =~ m|$namn$ws+(\d+)$ws+\d+$ws+R|s)
5753 0           { $key = $1;
5754 0           last;
5755             }
5756             }
5757 0 0         return undef unless $key;
5758             }
5759              
5760             ########################################
5761             # Read the top object of the hierarchy
5762             ########################################
5763              
5764 0           ($del1, $del2) = getKnown(\$form{$fSource}, $key);
5765              
5766 0           $objNr++;
5767 0           $nr = $objNr;
5768              
5769 0 0         if ($resType eq 'Font')
    0          
    0          
    0          
    0          
    0          
5770 0           { my ($Font, $extNamn);
5771 0 0         if ($$del1 =~ m|/BaseFont$ws*/([^\s\/]+)|os)
5772 0           { $extNamn = $1;
5773 0 0         if (! exists $font{$extNamn})
5774 0           { $fontNr++;
5775 0           $Font = 'Ft' . $fontNr;
5776 0           $font{$extNamn}[foINTNAMN] = $Font;
5777 0           $font{$extNamn}[foORIGINALNR] = $nr;
5778 0 0         if ($del1 =~ m|/Subtype$ws*/Type0|os)
5779 0           { $font{$extNamn}[foTYP] = 1;
5780             }
5781 0           $fontSource{$Font}[foSOURCE] = $fSource;
5782 0           $fontSource{$Font}[foORIGINALNR] = $nr;
5783             }
5784 0           $font{$extNamn}[foREFOBJ] = $nr;
5785 0           $Font = $font{$extNamn}[foINTNAMN];
5786 0           $namn = $Font;
5787 0           $objRef{$Font} = $nr;
5788             }
5789             else
5790 0           { errLog("Inconsitency in $fSource, font $namn can't be found, aborting");
5791             }
5792             }
5793             elsif ($resType eq 'ColorSpace')
5794 0           { $colorSpace++;
5795 0           $namn = 'Cs' . $colorSpace;
5796 0           $objRef{$namn} = $nr;
5797             }
5798             elsif ($resType eq 'Pattern')
5799 0           { $pattern++;
5800 0           $namn = 'Pt' . $pattern;
5801 0           $objRef{$namn} = $nr;
5802             }
5803             elsif ($resType eq 'Shading')
5804 0           { $shading++;
5805 0           $namn = 'Sh' . $shading;
5806 0           $objRef{$namn} = $nr;
5807             }
5808             elsif ($resType eq 'ExtGState')
5809 0           { $gSNr++;
5810 0           $namn = 'Gs' . $gSNr;
5811 0           $objRef{$namn} = $nr;
5812             }
5813             elsif ($resType eq 'XObject')
5814 0 0         { if (defined $form{$fSource}->[0]->{$nr}->[oIMAGENR])
5815 0           { $namn = 'Ig' . $form{$fSource}->[0]->{$nr}->[oIMAGENR];
5816             }
5817             else
5818 0           { $formNr++;
5819 0           $namn = 'Fo' . $formNr;
5820             }
5821              
5822 0           $objRef{$namn} = $nr;
5823             }
5824              
5825 0           $$del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
5826              
5827 0 0         if (defined $$del2)
5828 0           { $utrad = "$nr 0 obj\n<<" . $$del1 . $$del2;
5829             }
5830             else
5831 0           { $utrad = "$nr 0 obj " . $$del1;
5832             }
5833 0           $objekt[$nr] = $pos;
5834 0           $pos += syswrite UTFIL, $utrad;
5835              
5836             ##################################
5837             # Skriv ut underordnade objekt
5838             ##################################
5839              
5840 0           while (scalar @skapa)
5841 0           { my @process = @skapa;
5842 0           @skapa = ();
5843 0           for (@process)
5844 0           { my $gammal = $$_[0];
5845 0           my $ny = $$_[1];
5846              
5847 0           ($del1, $del2, $kids) = getKnown(\$form{$fSource}, $gammal);
5848              
5849 0 0         $$del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs
  0            
5850             unless (! defined $kids);
5851 0 0         if (defined $$del2)
5852 0           { $utrad = "$ny 0 obj\n<<" . $$del1 . $$del2;
5853             }
5854             else
5855 0           { $utrad = "$ny 0 obj " . $$del1;
5856             }
5857 0           $objekt[$ny] = $pos;
5858 0           $pos += syswrite UTFIL, $utrad;
5859             }
5860             }
5861 0           close INFIL;
5862              
5863 0           return $namn;
5864              
5865             }
5866              
5867             ########################
5868             # Ett objekt extraheras
5869             ########################
5870              
5871             sub extractObject
5872 3     3   36 { no warnings;
  3         9  
  3         50762  
5873 0     0 0   my ($infil, $sidnr, $key, $typ) = @_;
5874              
5875 0           my ($res, $del1, $corr, $namn, $kids, $nr, $utrad);
5876 0           my $del2 = '';
5877 0           @skapa = ();
5878              
5879             $behandlad{$infil}->{old} = {}
5880 0 0         unless (defined $behandlad{$infil}->{old});
5881             $processed{$infil}->{oldObject} = {}
5882 0 0         unless (defined $processed{$infil}->{oldObject});
5883             $processed{$infil}->{unZipped} = {}
5884 0 0         unless (defined $processed{$infil}->{unZipped});
5885              
5886 0           *old = $behandlad{$infil}->{old};
5887 0           *oldObject = $processed{$infil}->{oldObject};
5888 0           *unZipped = $processed{$infil}->{unZipped};
5889              
5890 0           my $fSource = $infil . '_' . $sidnr;
5891 0           my @stati = stat($infil);
5892              
5893 0 0         if ($form{$fSource}[fID] != $stati[9])
5894 0           { errLog("$stati[9] ne $form{$fSource}[fID] aborts");
5895             }
5896 0 0         if ($checkId)
5897 0 0         { if ($checkId ne $stati[9])
5898 0           { my $mess = "$checkId \<\> $stati[9] \n"
5899             . "The Pdf-file $fSource has not the correct modification time. \n"
5900             . "The program is aborted";
5901 0           errLog($mess);
5902             }
5903 0           undef $checkId;
5904             }
5905 0 0         if ($ldir)
5906 0           { $log .= "Cid~$stati[9]\n";
5907 0           my $indata = prep($infil);
5908 0           $log .= "Form~$indata~$sidnr~~load~1\n";
5909             }
5910              
5911 0 0         open (INFIL, "<$infil") || errLog("The file $infil couldn't be opened, aborting $!");
5912 0           binmode INFIL;
5913              
5914             ########################################
5915             # Read the top object of the hierarchy
5916             ########################################
5917              
5918 0           ($del1, $del2, $kids) = getKnown(\$form{$fSource}, $key);
5919              
5920 0 0         if (exists $old{$key})
5921 0           { $nr = $old{$key}; }
5922             else
5923 0           { $old{$key} = ++$objNr;
5924 0           $nr = $objNr;
5925             }
5926              
5927 0 0         if ($typ eq 'Font')
    0          
    0          
    0          
    0          
    0          
5928 0           { my ($Font, $extNamn);
5929 0 0         if ($$del1 =~ m|/BaseFont$ws*/([^\s\/]+)|os)
5930 0           { $extNamn = $1;
5931 0           $fontNr++;
5932 0           $Font = 'Ft' . $fontNr;
5933 0           $font{$extNamn}[foINTNAMN] = $Font;
5934 0           $font{$extNamn}[foORIGINALNR] = $key;
5935 0 0         if ($del1 =~ m|/Subtype$ws*/Type0|os)
5936 0           { $font{$extNamn}[foTYP] = 1;
5937             }
5938 0 0         if ( ! defined $fontSource{$extNamn}[foSOURCE])
5939 0           { $fontSource{$extNamn}[foSOURCE] = $fSource;
5940 0           $fontSource{$extNamn}[foORIGINALNR] = $key;
5941             }
5942 0           $font{$extNamn}[foREFOBJ] = $nr;
5943 0           $Font = $font{$extNamn}[foINTNAMN];
5944 0           $namn = $Font;
5945 0           $objRef{$Font} = $nr;
5946             }
5947             else
5948 0           { errLog("Error in $fSource, $key is not a font, aborting");
5949             }
5950             }
5951             elsif ($typ eq 'ColorSpace')
5952 0           { $colorSpace++;
5953 0           $namn = 'Cs' . $colorSpace;
5954 0           $objRef{$namn} = $nr;
5955             }
5956             elsif ($typ eq 'Pattern')
5957 0           { $pattern++;
5958 0           $namn = 'Pt' . $pattern;
5959 0           $objRef{$namn} = $nr;
5960             }
5961             elsif ($typ eq 'Shading')
5962 0           { $shading++;
5963 0           $namn = 'Sh' . $shading;
5964 0           $objRef{$namn} = $nr;
5965             }
5966             elsif ($typ eq 'ExtGState')
5967 0           { $gSNr++;
5968 0           $namn = 'Gs' . $gSNr;
5969 0           $objRef{$namn} = $nr;
5970             }
5971             elsif ($typ eq 'XObject')
5972 0 0         { if (defined $form{$fSource}->[0]->{$nr}->[oIMAGENR])
5973 0           { $namn = 'Ig' . $form{$fSource}->[0]->{$nr}->[oIMAGENR];
5974             }
5975             else
5976 0           { $formNr++;
5977 0           $namn = 'Fo' . $formNr;
5978             }
5979              
5980 0           $objRef{$namn} = $nr;
5981             }
5982              
5983 0 0         $$del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs
  0            
5984             unless (! defined $kids);
5985 0 0         if (defined $$del2)
5986 0           { $utrad = "$nr 0 obj\n<<" . $$del1 . $$del2;
5987             }
5988             else
5989 0           { $utrad = "$nr 0 obj " . $$del1;
5990             }
5991              
5992 0           $objekt[$nr] = $pos;
5993 0           $pos += syswrite UTFIL, $utrad;
5994              
5995             ##################################
5996             # Skriv ut underordnade objekt
5997             ##################################
5998              
5999 0           while (scalar @skapa)
6000 0           { my @process = @skapa;
6001 0           @skapa = ();
6002 0           for (@process)
6003 0           { my $gammal = $$_[0];
6004 0           my $ny = $$_[1];
6005              
6006 0           ($del1, $del2, $kids) = getKnown(\$form{$fSource}, $gammal);
6007              
6008 0 0         $$del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs
  0            
6009             unless (! defined $kids);
6010              
6011 0 0         if (defined $$del2)
6012 0           { $utrad = "$ny 0 obj<<" . $$del1 . $$del2;
6013             }
6014             else
6015 0           { $utrad = "$ny 0 obj " . $$del1;
6016             }
6017              
6018 0           $objekt[$ny] = $pos;
6019 0           $pos += syswrite UTFIL, $utrad;
6020             }
6021             }
6022 0           close INFIL;
6023 0           return $namn;
6024             }
6025              
6026              
6027             ##########################################
6028             # En fil analyseras och sidorna kopieras
6029             ##########################################
6030              
6031             sub analysera
6032 0     0 0   { my $infil = shift;
6033 0   0       my $from = shift || 1;
6034 0   0       my $to = shift || 0;
6035 0           my $singlePage = shift;
6036 0           my ($i, $res, @underObjekt, @sidObj, $vektor, $resources, $valid,
6037             $strPos, $sidor, $filId, $Root, $del1, $del2, $utrad);
6038              
6039 0           my $extraherade = 0;
6040 0           my $sidAcc = 0;
6041 0           @skapa = ();
6042              
6043             $behandlad{$infil}->{old} = {}
6044 0 0         unless (defined $behandlad{$infil}->{old});
6045             $processed{$infil}->{oldObject} = {}
6046 0 0         unless (defined $processed{$infil}->{oldObject});
6047             $processed{$infil}->{unZipped} = {}
6048 0 0         unless (defined $processed{$infil}->{unZipped});
6049 0           *old = $behandlad{$infil}->{old};
6050 0           *oldObject = $processed{$infil}->{oldObject};
6051 0           *unZipped = $processed{$infil}->{unZipped};
6052              
6053             $root = (exists $processed{$infil}->{root})
6054 0 0         ? $processed{$infil}->{root} : 0;
6055              
6056 0           my ($AcroForm, $Annots, $Names, $AARoot);
6057 0           undef $taInterAkt;
6058 0           undef %script;
6059              
6060 0           my $checkIdOld = $checkId;
6061 0           ($infil, $checkId) = findGet($infil, $checkIdOld);
6062 0 0 0       if (($ldir) && ($checkId) && ($checkId ne $checkIdOld))
      0        
6063 0           { $log .= "Cid~$checkId\n";
6064             }
6065 0           undef $checkId;
6066 0           my @stati = stat($infil);
6067 0 0         open (INFIL, "<$infil") || errLog("Couldn't open $infil,aborting. $!");
6068 0           binmode INFIL;
6069              
6070 0 0         if (! $root)
6071 0           { $root = xRefs($stati[7], $infil);
6072             }
6073             #############
6074             # Hitta root
6075             #############
6076              
6077 0           my $offSet;
6078             my $bytes;
6079 0           my $objektet = getObject($root);
6080              
6081 0 0 0       if ((! $interActive) && ( ! $to) && ($from == 1))
      0        
6082 0 0         { if ($objektet =~ m|/AcroForm($ws+\d+$ws+\d+$ws+R)|so)
6083 0           { $AcroForm = $1;
6084             }
6085 0 0         if ($objektet =~ m|/Names$ws+(\d+)$ws+\d+$ws+R|so)
6086 0           { $Names = $1;
6087             }
6088 0 0 0       if ((scalar %fields) || (scalar @jsfiler) || (scalar @inits))
    0 0        
6089 0           { $Names = behandlaNames($Names);
6090             }
6091             elsif ($Names)
6092 0           { $Names = quickxform($Names);
6093             }
6094              
6095             #################################################
6096             # Finns ett dictionary för Additional Actions ?
6097             #################################################
6098 0 0         if ($objektet =~ m|/AA($ws+\d+$ws+\d+$ws+R)|os) # Hänvisning
    0          
6099 0           { $AARoot = $1; }
6100             elsif ($objektet =~ m|/AA$ws*\<\<$ws*[^\>]+[^\>]+|so) # AA är ett dictionary
6101 0           { my $k;
6102 0           my ($dummy, $obj) = split /\/AA/, $objektet;
6103 0           $obj =~ s/\<\
6104 0           $obj =~ s/\>\>/\>\>\#/gs;
6105 0           my @ord = split /\#/, $obj;
6106 0           for ($i = 0; $i <= $#ord; $i++)
6107 0           { $AARoot .= $ord[$i];
6108 0 0         if ($ord[$i] =~ m'\S+'os)
6109 0 0         { if ($ord[$i] =~ m'<<'os)
6110 0           { $k++; }
6111 0 0         if ($ord[$i] =~ m'>>'os)
6112 0           { $k--; }
6113 0 0         if ($k == 0)
6114 0           { last; }
6115             }
6116             }
6117             }
6118 0           $taInterAkt = 1; # Flagga att ta med interaktiva funktioner
6119             }
6120              
6121             #
6122             # Hitta pages
6123             #
6124              
6125 0 0         if ($objektet =~ m|/Pages$ws+(\d+)$ws+\d+$ws+R|os)
6126 0           { $objektet = getObject($1);
6127 0           $resources = checkResources($objektet, $resources);
6128 0 0         if ($objektet =~ m|/Count$ws+(\d+)|os)
6129 0           { $sidor = $1;
6130 0           $behandlad{$infil}->{sidor} = $sidor;
6131             }
6132             }
6133             else
6134 0           { errLog("Didn't find pages "); }
6135              
6136 0           my @levels; my %kids;
6137 0           my $li = -1;
6138              
6139 0 0         if ($objektet =~ m|/Kids$ws*\[([^\]]+)|os)
6140 0           { $vektor = $1;
6141 0           while ($vektor =~ m|(\d+)$ws+\d+$ws+R|go)
6142 0           { push @sidObj, $1;
6143             }
6144 0           $li++;
6145 0           $levels[$li] = \@sidObj;
6146             }
6147              
6148 0   0       while (($li > -1) && ($sidAcc < $sidor))
6149 0 0         { if (scalar @{$levels[$li]})
  0            
6150 0           { my $j = shift @{$levels[$li]};
  0            
6151 0           $objektet = getObject($j);
6152 0 0         if ($objektet =~ m|/Kids$ws*\[([^\]]+)|os)
6153 0           { $resources = checkResources($objektet, $resources);
6154 0           $vektor = $1;
6155 0           my @sObj;
6156 0           while ($vektor =~ m/(\d+)$ws+\d+$ws+R/go)
6157 0 0         { push @sObj, $1 if !$kids{$1}; $kids{$1}=1;
  0            
6158             }
6159 0 0         if(@sObj)
6160 0           { $li++;
6161 0           $levels[$li] = \@sObj;
6162             }
6163             }
6164             else
6165 0           { $sidAcc++;
6166 0 0         if ($sidAcc >= $from)
6167 0 0         { if ($to)
6168 0 0         { if ($sidAcc <= $to)
6169 0           { sidAnalys($j, $objektet, $resources);
6170 0           $extraherade++;
6171 0           $sida++;
6172             }
6173             else
6174 0           { $sidAcc = $sidor;
6175             }
6176             }
6177             else
6178 0           { sidAnalys($j, $objektet, $resources);
6179 0           $extraherade++;
6180 0           $sida++;
6181             }
6182             }
6183             }
6184             }
6185             else
6186 0           { $li--;
6187             }
6188             }
6189              
6190 0 0         if (defined $AcroForm)
6191 0           { $AcroForm =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
6192             }
6193 0 0         if (defined $AARoot)
6194 0           { $AARoot =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
6195             }
6196              
6197 0           while (scalar @skapa)
6198 0           { my @process = @skapa;
6199 0           @skapa = ();
6200 0           for (@process)
6201 0           { my $gammal = $$_[0];
6202 0           my $ny = $$_[1];
6203 0           $objektet = getObject($gammal);
6204              
6205 0 0         if($objektet =~ m/^(\d+$ws+\d+$ws+obj$ws*<<)(.+)(>>$ws*stream)/os)
6206 0           { $del1 = $2;
6207 0           $strPos = length($2) + length($3) + length($1);
6208 0           $del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
6209 0           $objekt[$ny] = $pos;
6210 0           $utrad = "$ny 0 obj<<" . "$del1" . '>>stream';
6211 0           $del2 = substr($objektet, $strPos);
6212 0           $utrad .= $del2;
6213              
6214 0           $pos += syswrite UTFIL, $utrad;
6215             }
6216             else
6217 0 0         { if ($objektet =~ m/^(\d+$ws+\d+$ws+obj)/os)
6218 0           { my $preLength = length($1);
6219 0           $objektet = substr($objektet, $preLength);
6220             }
6221 0           $objektet =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
6222 0           $objekt[$ny] = $pos;
6223 0           $utrad = "$ny 0 obj$objektet";
6224 0           $pos += syswrite UTFIL, $utrad;
6225             }
6226             }
6227             }
6228 0           close INFIL;
6229 0           $processed{$infil}->{root} = $root;
6230              
6231 0 0         if (! $singlePage)
6232 0           { return ($extraherade, $Names, $AARoot, $AcroForm);
6233             }
6234             else
6235 0 0         { if ($extraherade)
6236 0           { my $kvar = $behandlad{$infil}->{sidor} - $from;
6237 0           return ($kvar, $Names, $AARoot, $AcroForm);
6238             }
6239             else
6240 0           { return (undef, undef, undef, undef);
6241             }
6242             }
6243             }
6244              
6245             sub sidAnalys
6246 0     0 0   { my ($oNr, $obj, $resources) = @_;
6247 0           my ($ny, $strPos, $spar, $closeProc, $del1, $del2, $utrad, $Annots,
6248             $resursObjekt, $streamObjekt, @extObj, $langd);
6249              
6250 0 0 0       if ((defined $stream) && (length($stream) > 0))
6251             {
6252 0 0         if ($checkCs)
6253 0           { @extObj = ($stream =~ m'/(\S+)\s*'gso);
6254 0           checkContentStream(@extObj);
6255             }
6256              
6257 0           $objNr++;
6258 0           $objekt[$objNr] = $pos;
6259              
6260 0 0 0       if (( $compress ) && ( length($stream) > 99 ))
6261 0           { my $output = compress($stream);
6262 0 0 0       if ((length($output) > 25) && (length($output) < (length($stream))))
6263 0           { $stream = $output;
6264             }
6265 0           $langd = length($stream);
6266 0           $stream = "\n" . $stream . "\n";
6267 0           $langd++;
6268 0           $streamObjekt = "$objNr 0 obj<
6269             . "/Length $langd>>stream" . $stream;
6270 0           $streamObjekt .= "endstream\nendobj\n";
6271              
6272             }
6273             else
6274 0           { $langd = length($stream);
6275 0           $streamObjekt = "$objNr 0 obj<>stream\n" . $stream;
6276 0           $streamObjekt .= "\nendstream\nendobj\n";
6277             }
6278 0           $pos += syswrite UTFIL, $streamObjekt;
6279 0           $streamObjekt = "$objNr 0 R ";
6280              
6281             ########################################################################
6282             # Sometimes the contents reference is a ref to an object which
6283             # contains an array of content streams. Replace the ref with the array
6284             ########################################################################
6285              
6286 0 0         if ($obj =~ m|/Contents$ws+(\d+)$ws+\d+$ws+R|os)
6287 0           { my $cObj = getObject($1, 1, 1);
6288 0 0         if ($cObj =~ m/^$ws*\[[^\]]+\]$ws*$/os)
6289 0           { $obj =~ s|/Contents$ws+\d+$ws+\d+$ws+R|'/Contents ' . $cObj|oes;
  0            
6290             }
6291             }
6292              
6293 0           my ($from, $to);
6294              
6295 0           ($resources, $from, $to) = checkResources ($obj, $resources);
6296 0 0 0       if ($from && $to)
6297 0           { $obj = substr($obj, 0, $from) . substr($obj, $to);
6298             }
6299              
6300              
6301             ##########################
6302             # Hitta resursdictionary
6303             ##########################
6304 0           my $i = 0;
6305 0   0       while (($resources !~ m'\/'os) && ($i < 10))
6306 0           { $i++;
6307 0 0         if ($resources =~ m/$ws+(\d+)$ws+\d+$ws+R/os)
6308 0           { $resources = getObject($1, 1, 1);
6309             }
6310             }
6311 0 0         if ($i > 7)
6312 0           { errLog("Couldn't find resources to merge");
6313             }
6314 0 0         if ($resources =~ m/$ws*\<\<(.*)\>\>/os)
6315 0           { $resources = $1;
6316             }
6317              
6318 0 0         if ($resources !~ m'/ProcSet')
6319 0           { $resources = '/ProcSet[/PDF/Text] ' . $resources;
6320             }
6321              
6322             ###############################################################
6323             # Läsa ev. referenser och skapa ett resursobjekt bestående av
6324             # dictionaries (för utvalda resurser)
6325             ###############################################################
6326              
6327 0 0         if (scalar %sidFont)
6328 0 0         { if ($resources =~ m|/Font$ws+(\d+)$ws+\d+$ws+R|os)
6329 0           { my $dict = getObject($1, 1, 1);
6330 0           $resources =~ s"/Font$ws+\d+$ws+\d+$ws+R"'/Font' . $dict"ose;
  0            
6331             }
6332             }
6333              
6334 0 0         if (scalar %sidXObject)
6335 0 0         { if ($resources =~ m|/XObject$ws+(\d+)$ws+\d+$ws+R|os)
6336 0           { my $dict = getObject($1, 1, 1);
6337 0           $resources =~ s"/XObject$ws+\d+$ws+\d+$ws+R"'/XObject' . $dict"ose;
  0            
6338             }
6339             }
6340              
6341 0 0         if (scalar %sidExtGState)
6342 0 0         { if ($resources =~ m|/ExtGState$ws+(\d+)$ws+\d+$ws+R|os)
6343 0           { my $dict = getObject($1, 1, 1);
6344 0           $resources =~ s"/ExtGState$ws+\d+$ws+\d+$ws+R"'/ExtGState' . $dict"ose;
  0            
6345             }
6346             }
6347              
6348 0 0         if (scalar %sidPattern)
6349 0 0         { if ($resources =~ m|/Pattern$ws+(\d+)$ws+\d+$ws+R|os)
6350 0           { my $dict = getObject($1, 1, 1);
6351 0           $resources =~ s"/Pattern$ws+\d+$ws+\d+$ws+R"'/Pattern' . $dict"ose;
  0            
6352             }
6353             }
6354              
6355 0 0         if (scalar %sidShading)
6356 0 0         { if ($resources =~ m|/Shading$ws+(\d+)$ws+\d+$ws+R|os)
6357 0           { my $dict = getObject($1, 1, 1);
6358 0           $resources =~ s"/Shading$ws+\d+$ws+\d+$ws+R"'/Shading' . $dict"ose;
  0            
6359             }
6360             }
6361              
6362 0 0         if (scalar %sidColorSpace)
6363 0 0         { if ($resources =~ m|/ColorSpace$ws+(\d+)$ws+\d+$ws+R|os)
6364 0           { my $dict = getObject($1, 1, 1);
6365 0           $resources =~ s"/ColorSpace$ws+\d+$ws+\d+$ws+R"'/ColorSpace' . $dict"ose;
  0            
6366             }
6367             }
6368             ####################################################
6369             # Nu är resurserna "normaliserade" med ursprungliga
6370             # värden. Spara värden för "översättning"
6371             ####################################################
6372              
6373 0           $resources =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
6374              
6375             ###############################
6376             # Komplettera med nya resurser
6377             ###############################
6378              
6379 0 0         if (scalar %sidFont)
6380 0           { my $str = '';
6381 0           for (sort keys %sidFont)
6382 0           { $str .= "/$_ $sidFont{$_} 0 R";
6383             }
6384 0 0         if ($resources !~ m'\/Font'os)
6385 0           { $resources = "/Font << $str >> " . $resources;
6386             }
6387             else
6388 0           { $resources =~ s"/Font$ws*<<"'/Font<<' . $str"oges;
  0            
6389             }
6390             }
6391              
6392 0 0         if (scalar %sidXObject)
6393 0           { my $str = '';
6394 0           for (sort keys %sidXObject)
6395 0           { $str .= "/$_ $sidXObject{$_} 0 R";
6396             }
6397 0 0         if ($resources !~ m'\/XObject'os)
6398 0           { $resources = "/XObject << $str >> " . $resources;
6399             }
6400             else
6401 0           { $resources =~ s"/XObject$ws*<<"'/XObject<<' . $str"oges;
  0            
6402             }
6403             }
6404              
6405 0 0         if (scalar %sidExtGState)
6406 0           { my $str = '';
6407 0           for (sort keys %sidExtGState)
6408 0           { $str .= "/$_ $sidExtGState{$_} 0 R";
6409             }
6410 0 0         if ($resources !~ m'\/ExtGState'os)
6411 0           { $resources = "/ExtGState << $str >> " . $resources;
6412             }
6413             else
6414 0           { $resources =~ s"/ExtGState$ws*<<"'/ExtGState<<' . $str"oges;
  0            
6415             }
6416             }
6417              
6418 0 0         if (scalar %sidPattern)
6419 0           { my $str = '';
6420 0           for (sort keys %sidPattern)
6421 0           { $str .= "/$_ $sidPattern{$_} 0 R";
6422             }
6423 0 0         if ($resources !~ m'\/Pattern'os)
6424 0           { $resources = "/Pattern << $str >> " . $resources;
6425             }
6426             else
6427 0           { $resources =~ s"/Pattern$ws*<<"'/Pattern<<' . $str"oges;
  0            
6428             }
6429             }
6430              
6431 0 0         if (scalar %sidShading)
6432 0           { my $str = '';
6433 0           for (sort keys %sidShading)
6434 0           { $str .= "/$_ $sidShading{$_} 0 R";
6435             }
6436 0 0         if ($resources !~ m'\/Shading'os)
6437 0           { $resources = "/Shading << $str >> " . $resources;
6438             }
6439             else
6440 0           { $resources =~ s"/Shading$ws*<<"'/Shading<<' . $str"oges;
  0            
6441             }
6442             }
6443              
6444 0 0         if (scalar %sidColorSpace)
6445 0           { my $str = '';
6446 0           for (sort keys %sidColorSpace)
6447 0           { $str .= "/$_ $sidColorSpace{$_} 0 R";
6448             }
6449 0 0         if ($resources !~ m'\/ColorSpace'os)
6450 0           { $resources = "/ColorSpace << $str >> " . $resources;
6451             }
6452             else
6453 0           { $resources =~ s"/ColorSpace$ws*<<"'/ColorSpace<<'.$str"oges;
  0            
6454             }
6455             }
6456              
6457 0 0         if (exists $resurser{$resources})
6458 0           { $resources = "$resurser{$resources} 0 R\n"; # Fanns ett identiskt,
6459             } # använd det
6460             else
6461 0           { $objNr++;
6462 0 0         if ( keys(%resurser) < 10)
6463 0           { $resurser{$resources} = $objNr; # Spara 10 första resursobjekten
6464             }
6465 0           $objekt[$objNr] = $pos;
6466 0           $resursObjekt = "$objNr 0 obj<<$resources>>endobj\n";
6467 0           $pos += syswrite UTFIL, $resursObjekt ;
6468 0           $resources = "$objNr 0 R\n";
6469             }
6470              
6471 0           %sidXObject = ();
6472 0           %sidExtGState = ();
6473 0           %sidFont = ();
6474 0           %sidPattern = ();
6475 0           %sidShading = ();
6476 0           %sidColorSpace = ();
6477 0           undef $checkCs;
6478              
6479 0           $stream = '';
6480             }
6481              
6482 0 0         if (! $parents[0])
6483 0           { $objNr++;
6484 0           $parents[0] = $objNr;
6485             }
6486 0           my $parent = $parents[0];
6487              
6488 0 0 0       if (($sidObjNr) && (! defined $objekt[$sidObjNr]))
6489 0           { $ny = $sidObjNr;
6490             }
6491             else
6492 0           { $objNr++;
6493 0           $ny = $objNr;
6494             }
6495              
6496 0           $old{$oNr} = $ny;
6497              
6498 0 0         if ($obj =~ m|/Parent$ws+(\d+)$ws+\d+$ws+R\b|os)
6499 0           { $old{$1} = $parent;
6500             }
6501              
6502 0 0         if ($obj =~ m/^\d+$ws+\d+$ws+obj$ws*<<(.+)>>$ws*endobj/os)
6503 0           { $del1 = $1;
6504             }
6505              
6506 0 0         if (%links)
6507 0           { my $tSida = $sida + 1;
6508 0 0 0       if ((%links && $links{'-1'} && @{$links{'-1'}}) || (%links && $links{$tSida} && @{$links{$tSida}}))
  0   0        
  0   0        
      0        
      0        
6509 0 0         { if ($del1 =~ m|/Annots$ws*([^\/\<\>]+)|os)
6510 0           { $Annots = $1;
6511 0           @annots = ();
6512 0 0         if ($Annots =~ m'\[([^\[\]]*)\]'os)
6513             { ; }
6514             else
6515 0 0         { if ($Annots =~ m/\b(\d+)$ws+\d+$ws+R\b/os)
6516 0           { $Annots = getObject($1);
6517             }
6518             }
6519 0           while ($Annots =~ m/\b(\d+)$ws+\d+$ws+R\b/ogs)
6520 0           { push @annots, xform();
6521             }
6522 0           $del1 =~ s?/Annots$ws*([^\/\<\>]+)??os;
6523             }
6524 0           $Annots = '/Annots ' . mergeLinks() . ' 0 R';
6525             }
6526             }
6527              
6528 0 0         if (! $taInterAkt)
6529 0           { $del1 =~ s?$ws*/AA$ws*<<[^>]*>>??os;
6530             }
6531              
6532 0           $del1 =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
6533              
6534 0 0         if ($del1 !~ m'/Resources'o)
6535 0           { $del1 .= "/Resources $resources";
6536             }
6537              
6538 0 0         if (defined $streamObjekt) # En ny ström ska läggas till
6539 0 0         { if ($del1 =~ m|/Contents$ws+(\d+)$ws+\d+$ws+R|os)
    0          
6540 0           { my $oldCont = $1;
6541 0           $del1 =~ s|/Contents$ws+(\d+)$ws+\d+$ws+R|'/Contents [' . "$oldCont 0 R $streamObjekt" . ']'|oes;
  0            
6542             }
6543             elsif ($del1 =~ m|/Contents$ws*\[|os)
6544 0           { $del1 =~ s|/Contents$ws*\[([^\]]+)|'/Contents [' . $1 ." $streamObjekt"|oes;
  0            
6545             }
6546             else
6547 0           { $del1 .= "/Contents $streamObjekt\n";
6548             }
6549             }
6550              
6551 0 0         if ($Annots)
6552 0           { $del1 .= $Annots;
6553             }
6554              
6555 0           $utrad = "$ny 0 obj<<$del1>>";
6556 0 0         if (defined $del2)
6557 0           { $utrad .= "stream\n$del2";
6558             }
6559             else
6560 0           { $utrad .= "endobj\n";
6561             }
6562              
6563 0           $objekt[$ny] = $pos;
6564 0           $pos += syswrite UTFIL, $utrad;
6565              
6566 0           push @{$kids[0]}, $ny;
  0            
6567 0           $counts[0]++;
6568 0 0         if ($counts[0] > 9)
6569 0           { ordnaNoder(8);
6570             }
6571             }
6572              
6573              
6574             sub checkResources
6575 0     0 0   { my $pObj = shift;
6576 0           my $reStr = shift;
6577 0           my $to;
6578              
6579 0           my $p = index($pObj, '/Resources');
6580 0 0         if ( $p < 0)
    0          
6581             { ;
6582             }
6583             elsif ($pObj =~ m|/Resources($ws+\d+$ws+\d+$ws+R)|os)
6584 0           { $reStr = $1;
6585 0           $to = $p + 10 + length($reStr);
6586             }
6587             else
6588 0           { my $t = length($pObj);
6589 0           my $i = $p + 10;
6590 0           my $j = $i;
6591 0           my $k = 0;
6592 0           my $c;
6593 0           while ($i < $t)
6594 0           { $c = substr($pObj,$i,1);
6595 0 0 0       if (($c eq '<' )
6596             || ($c eq '>'))
6597 0 0         { if ($c eq '<' )
6598 0           { $k++;
6599             }
6600             else
6601 0           { $k--;
6602             }
6603 0 0         last if ($k == 0);
6604             }
6605 0           $i++;
6606             }
6607 0 0         if ($i != $t)
6608 0           { $i++;
6609 0           $reStr = substr($pObj, $j, ($i - $j));
6610 0           $to = $i;
6611             }
6612             }
6613              
6614 0 0         if (wantarray)
6615 0           { return ($reStr, $p, $to);
6616             }
6617             else
6618 0           { return $reStr;
6619             }
6620             }
6621              
6622              
6623             sub translate
6624 0 0   0 0   { if (exists $old{$1})
6625 0           { $old{$1}; }
6626             else
6627 0           { $old{$1} = ++$objNr;
6628             }
6629             }
6630              
6631             sub behandlaNames
6632 0     0 0   { my ($namnObj, $iForm) = @_;
6633              
6634 0           my ($low, $high, $antNod0, $entry, $nyttNr, $ny, $obj,
6635             $fObjnr, $offSet, $bytes, $res, $key, $func, $corr, @objData);
6636 0           my (@nod0, @nodUpp, @kid, @soek, %nytt);
6637              
6638 0           my $objektet = '';
6639 0           my $vektor = '';
6640 0           my $antal = 0;
6641 0           my $antNodUpp = 0;
6642 0 0         if ($namnObj)
6643 0 0         { if ($iForm) # Läsning via interntabell
6644 0           { $objektet = getObject($namnObj, 1);
6645              
6646 0 0         if ($objektet =~ m'<<(.+)>>'ogs)
6647 0           { $objektet = $1; }
6648 0 0         if ($objektet =~ s|/JavaScript$ws+(\d+)$ws+\d+$ws+R||os)
6649 0           { my $byt = $1;
6650 0           push @kid, $1;
6651 0           while (scalar @kid)
6652 0           { @soek = @kid;
6653 0           @kid = ();
6654 0           for my $sObj (@soek)
6655 0           { $obj = getObject($sObj, 1);
6656 0 0         if ($obj =~ m|/Kids$ws*\[([^]]+)|ogs)
6657 0           { $vektor = $1;
6658             }
6659 0           while ($vektor =~ m/\b(\d+)$ws+\d+$ws+R\b/ogs)
6660 0           { push @kid, $1;
6661             }
6662 0           $vektor = '';
6663 0 0         if ($obj =~ m|/Names$ws*\[([^]]+)|ogs)
6664 0           { $vektor = $1;
6665             }
6666 0           while ($vektor=~m|\(([^\)]+)\)$ws*(\d+)$ws+\d$ws+R|gos)
6667 0           { $script{$1} = $2;
6668             }
6669             }
6670             }
6671             }
6672             }
6673             else # Läsning av ett "doc"
6674 0           { $objektet = getObject($namnObj);
6675 0 0         if ($objektet =~ m'<<(.+)>>'ogs)
6676 0           { $objektet = $1; }
6677 0 0         if ($objektet =~ s|/JavaScript$ws+(\d+)$ws+\d+$ws+R||os)
6678 0           { my $byt = $1;
6679 0           push @kid, $1;
6680 0           while (scalar @kid)
6681 0           { @soek = @kid;
6682 0           @kid = ();
6683 0           for my $sObj (@soek)
6684 0           { $obj = getObject($sObj);
6685 0 0         if ($obj =~ m|/Kids$ws*\[([^]]+)|ogs)
6686 0           { $vektor = $1;
6687             }
6688 0           while ($vektor =~ m|\b(\d+)$ws+\d+$ws+R\b|ogs)
6689 0           { push @kid, $1;
6690             }
6691 0           undef $vektor;
6692 0 0         if ($obj =~ m|/Names$ws*\[([^]]+)|ogs)
6693 0           { $vektor = $1;
6694             }
6695 0           while($vektor =~ m/\(([^\)]+)\)$ws*(\d+)$ws+\d\$ws+R/gos)
6696 0           { $script{$1} = $2;
6697             }
6698             }
6699             }
6700             }
6701             }
6702             }
6703 0           for my $filnamn (@jsfiler)
6704 0           { inkludera($filnamn);
6705             }
6706 0           my @nya = (keys %nyaFunk);
6707 0           while (scalar @nya)
6708 0           { my @behandla = @nya;
6709 0           @nya = ();
6710 0           for $key (@behandla)
6711 0 0         { if (exists $initScript{$key})
6712 0 0         { if (exists $nyaFunk{$key})
6713 0           { $initScript{$key} = $nyaFunk{$key};
6714             }
6715 0 0         if (exists $script{$key}) # företräde för nya funktioner !
6716 0           { delete $script{$key}; # gammalt script m samma namn plockas bort
6717             }
6718 0           my @fall = ($initScript{$key} =~ m'([\w\d\_\$]+)\s*\('ogs);
6719 0           for (@fall)
6720 0 0 0       { if (($_ ne $key) && (exists $nyaFunk{$_}))
6721 0           { $initScript{$_} = $nyaFunk{$_};
6722 0           push @nya, $_;
6723             }
6724             }
6725             }
6726             }
6727             }
6728 0           while (($key, $func) = each %nyaFunk)
6729 0           { $fObjnr = skrivJS($func);
6730 0           $script{$key} = $fObjnr;
6731 0           $nytt{$key} = $fObjnr;
6732             }
6733              
6734 0 0         if (scalar %fields)
6735 0           { push @inits, 'Ladda();';
6736 0           $fObjnr = defLadda();
6737 0 0         if ($duplicateInits)
6738 0           { $script{'Ladda'} = $fObjnr;
6739 0           $nytt{'Ladda'} = $fObjnr;
6740             }
6741             }
6742              
6743 0 0 0       if ((scalar @inits) && ($duplicateInits))
6744 0           { $fObjnr = defInit();
6745 0           $script{'Init'} = $fObjnr;
6746 0           $nytt{'Init'} = $fObjnr;
6747             }
6748 0           undef @jsfiler;
6749              
6750 0           for my $key (sort (keys %script))
6751 0 0         { if (! defined $low)
6752 0           { $objNr++;
6753 0           $ny = $objNr;
6754 0           $objekt[$ny] = $pos;
6755 0           $obj = "$ny 0 obj\n";
6756 0           $low = $key;
6757 0           $obj .= '<< /Names [';
6758             }
6759 0           $high = $key;
6760 0           $obj .= '(' . "$key" . ')';
6761 0 0         if (! exists $nytt{$key})
6762 0           { $nyttNr = quickxform($script{$key});
6763             }
6764             else
6765 0           { $nyttNr = $script{$key};
6766             }
6767 0           $obj .= "$nyttNr 0 R\n";
6768 0           $antal++;
6769 0 0         if ($antal > 9)
6770 0           { $obj .= ' ]/Limits [(' . "$low" . ')(' . "$high" . ')] >>' . "endobj\n";
6771 0           $pos += syswrite UTFIL, $obj;
6772 0           push @nod0, \[$ny, $low, $high];
6773 0           $antNod0++;
6774 0           undef $low;
6775 0           $antal = 0;
6776             }
6777             }
6778 0 0         if ($antal)
6779 0           { $obj .= ']/Limits [(' . $low . ')(' . $high . ')]>>' . "endobj\n";
6780 0           $pos += syswrite UTFIL, $obj;
6781 0           push @nod0, \[$ny, $low, $high];
6782 0           $antNod0++;
6783             }
6784 0           $antal = 0;
6785              
6786 0           while (scalar @nod0)
6787 0           { for $entry (@nod0)
6788 0 0         { if ($antal == 0)
6789 0           { $objNr++;
6790 0           $objekt[$objNr] = $pos;
6791 0           $obj = "$objNr 0 obj\n";
6792 0           $low = $$entry->[1];
6793 0           $obj .= '<
6794             }
6795 0           $high = $$entry->[2];
6796 0           $obj .= " $$entry->[0] 0 R";
6797 0           $antal++;
6798 0 0         if ($antal > 9)
6799 0           { $obj .= ']/Limits [(' . $low . ')(' . $high . ')]>>' . "endobj\n";
6800 0           $pos += syswrite UTFIL, $obj;
6801 0           push @nodUpp, \[$objNr, $low, $high];
6802 0           $antNodUpp++;
6803 0           undef $low;
6804 0           $antal = 0;
6805             }
6806             }
6807 0 0         if ($antal > 0)
6808 0 0         { if ($antNodUpp == 0) # inget i noderna över
6809 0           { $obj .= ']>>' . "endobj\n";
6810 0           $pos += syswrite UTFIL, $obj;
6811             }
6812             else
6813 0           { $obj .= ']/Limits [(' . "$low" . ')(' . "$high" . ')]>>' . "endobj\n";
6814 0           $pos += syswrite UTFIL, $obj;
6815 0           push @nodUpp, \[$objNr, $low, $high];
6816 0           $antNodUpp++;
6817 0           undef $low;
6818 0           $antal = 0;
6819             }
6820             }
6821 0           @nod0 = @nodUpp;
6822 0           $antNod0 = $antNodUpp;
6823 0           undef @nodUpp;
6824 0           $antNodUpp = 0;
6825             }
6826              
6827              
6828 0           $ny = $objNr;
6829 0           $objektet =~ s|$ws*/JavaScript$ws*\d+$ws+\d+$ws+R||os;
6830 0           $objektet =~ s/\b(\d+)$ws+\d+$ws+R\b/xform() . ' 0 R'/oegs;
  0            
6831 0 0         if (scalar %script)
6832 0           { $objektet .= "\n/JavaScript $ny 0 R\n";
6833             }
6834 0           $objNr++;
6835 0           $ny = $objNr;
6836 0           $objekt[$ny] = $pos;
6837 0           $objektet = "$ny 0 obj<<" . $objektet . ">>endobj\n";
6838 0           $pos += syswrite UTFIL, $objektet;
6839 0           return $ny;
6840             }
6841              
6842              
6843             sub quickxform
6844 0     0 0   { my $inNr = shift;
6845 0 0         if (exists $old{$inNr})
6846 0           { $old{$inNr}; }
6847             else
6848 0           { push @skapa, [$inNr, ++$objNr];
6849 0           $old{$inNr} = $objNr;
6850             }
6851             }
6852              
6853              
6854             sub skrivKedja
6855 0     0 0   { my $code = ' ';
6856              
6857 0           for (values %initScript)
6858 0           { $code .= $_ . "\n";
6859             }
6860 0           $code .= "function Init() { ";
6861 0           $code .= 'if (typeof this.info.ModDate == "object")' . " { return true; }";
6862 0           for (@inits)
6863 0           { $code .= $_ . "\n";
6864             }
6865 0           $code .= "} Init(); ";
6866              
6867 0           my $spar = skrivJS($code);
6868 0           undef @inits;
6869 0           undef %initScript;
6870 0           return $spar;
6871             }
6872              
6873              
6874              
6875             sub skrivJS
6876 0     0 0   { my $kod = shift;
6877 0           my $obj;
6878 0 0 0       if (($compress) && (length($kod) > 99))
6879 0           { $objNr++;
6880 0           $objekt[$objNr] = $pos;
6881 0           my $spar = $objNr;
6882 0           $kod = compress($kod);
6883 0           my $langd = length($kod);
6884 0           $obj = "$objNr 0 obj<
6885             . "/Length $langd>>stream\n" . $kod
6886             . "\nendstream\nendobj\n";
6887 0           $pos += syswrite UTFIL, $obj;
6888 0           $objNr++;
6889 0           $objekt[$objNr] = $pos;
6890 0           $obj = "$objNr 0 obj<>endobj\n";
6891             }
6892             else
6893 0           { $kod =~ s'\('\\('gso;
6894 0           $kod =~ s'\)'\\)'gso;
6895 0           $objNr++;
6896 0           $objekt[$objNr] = $pos;
6897 0           $obj = "$objNr 0 obj<
6898 0           $obj .= ">>endobj\n";
6899             }
6900 0           $pos += syswrite UTFIL, $obj;
6901 0           return $objNr;
6902             }
6903              
6904             sub inkludera
6905 0     0 0   { my $jsfil = shift;
6906 0           my $fil;
6907 0 0         if ($jsfil !~ m'\{'os)
6908 0 0         { open (JSFIL, "<$jsfil") || return;
6909 0           while ()
6910 0           { $fil .= $_;}
6911              
6912 0           close JSFIL;
6913             }
6914             else
6915 0           { $fil = $jsfil;
6916             }
6917 0           $fil =~ s|function\s+([\w\_\d\$]+)\s*\(|"zXyZcUt function $1 ("|sge;
  0            
6918 0           my @funcs = split/zXyZcUt /, $fil;
6919 0           for my $kod (@funcs)
6920 0 0         { if ($kod =~ m'^function ([\w\_\d\$]+)'os)
6921 0           { $nyaFunk{$1} = $kod;
6922             }
6923             }
6924             }
6925              
6926              
6927             sub defLadda
6928 0     0 0   { my $code = "function Ladda() {";
6929 0           for (keys %fields)
6930 0           { my $val = $fields{$_};
6931 0 0         if ($val =~ m'\s*js\s*\:(.+)'oi)
6932 0           { $val = $1;
6933 0           $code .= "if (this.getField('$_')) this.getField('$_').value = $val; ";
6934             }
6935             else
6936 0           { $val =~ s/([^A-Za-z0-9\-_.!* ])/sprintf("%%%02X", ord($1))/ge;
  0            
6937 0           $code .= "if (this.getField('$_')) this.getField('$_').value = unescape('$val'); ";
6938             }
6939              
6940             }
6941 0           $code .= " 1;} ";
6942              
6943              
6944 0           $initScript{'Ladda'} = $code;
6945 0 0         if ($duplicateInits)
6946 0           { my $ny = skrivJS($code);
6947 0           return $ny;
6948             }
6949             else
6950 0           { return 1;
6951             }
6952             }
6953              
6954             sub defInit
6955 0     0 0   { my $code = "function Init() { ";
6956 0           $code .= 'if (typeof this.info.ModDate == "object")' . " { return true; } ";
6957 0           for (@inits)
6958 0           { $code .= $_ . "\n";
6959             }
6960 0           $code .= '}';
6961              
6962 0           my $ny = skrivJS($code);
6963 0           return $ny;
6964              
6965             }
6966              
6967              
6968              
6969             sub errLog
6970 3     3   45 { no strict 'refs';
  3         7  
  3         2075  
6971 0     0 0   my $mess = shift;
6972 0           my $endMess = " $mess \n More information might be found in";
6973 0 0         if ($runfil)
6974 0           { $log .= "Log~Err: $mess\n";
6975 0           $endMess .= "\n $runfil";
6976 0 0         if (! $pos)
    0          
6977 0           { $log .= "Log~Err: No pdf-file has been initiated\n";
6978             }
6979             elsif ($pos > 15000000)
6980 0           { $log .= "Log~Err: Current pdf-file is very big: $pos bytes, will not try to finish it\n";
6981             }
6982             else
6983 0           { $log .= "Log~Err: Will try to finish current pdf-file\n";
6984 0           $endMess .= "\n $utfil";
6985             }
6986             }
6987 0           my $errLog = 'error.log';
6988 0           my $now = localtime();
6989 0   0       my $lpos = $pos || 'undef';
6990 0   0       my $lobjNr = $objNr || 'undef';
6991 0   0       my $lutfil = $utfil || 'undef';
6992              
6993 0   0       my $lrunfil = $runfil || 'undef';
6994 0 0         open (ERRLOG, ">$errLog") || croak "$mess can't open an error log, $!";
6995 0           print ERRLOG "\n$mess\n\n";
6996 0           print ERRLOG Carp::longmess("The error occurred when executing:\n");
6997 0           print ERRLOG "\nSituation when the error occurred\n\n";
6998 0           print ERRLOG " Bytes written to the current pdf-file, pos = $lpos\n";
6999 0           print ERRLOG " Object processed, not necessarily written objNr = $lobjNr\n";
7000 0           print ERRLOG " Current pdf-file, utfil = $lutfil\n";
7001 0           print ERRLOG " File logging the run, runfil = $lrunfil\n";
7002 0           print ERRLOG " Local time = $now\n";
7003 0           print ERRLOG "\n\n";
7004 0           close ERRLOG;
7005 0           $endMess .= "\n $errLog";
7006 0 0 0       if (($pos) && ($pos < 15000000))
7007 0           { prEnd();
7008             }
7009 0           print STDERR Carp::shortmess("An error occurred \n");
7010 0           croak "$endMess\n";
7011             }