ftp.nice.ch/pub/next/unix/text/pdf2ps.2.18a.s.tar.gz#/pdf2ps.pl

This is pdf2ps.pl in view mode; [Download] [Up]

#!/usr/local/bin/perl
#
# read Adobe PDF Files (PDF-1.0 + PDF-1.1) and convert to PostScript Level 2
# Detlev Droege, <droege@informatik.uni-koblenz.de>, Sept. 1993
# Copyright (C) 1993-1995 Detlev Droege
#

# RCS: "$Id: pdf2ps.pl,v 3.6 95/10/06 22:02:12 droege Exp Locker: droege $";
# RCS: "$Source: /Users/droege/pdf/pdf2ps/RCS/pdf2ps.pl,v $";

$Version = "2.18a";
$RCS_Revision = '$Revision: 3.6 $';
($dummy, $Rev, $dummy) = split (/ /, $RCS_Revision);

require "ctime.pl";
require "getopts.pl";

$logging = 0;
$noType3 = 0;
$opt_h = $opt_v = $opt_3 = $opt_b = 0;
$streamOutMode = 0;		# will be set to 1 or 2 during binary output unless -b

$UsageMsg = "usage: $0 [-abxhtv3] file.pdf
  -a	produce ASCII85 encoded data (default, SLOW, smallest pure 7-Bit files)
  -x	produce HEX encoded data     (fast, rather large pure 7-Bit files)
  -b	produce possibly binary data (fastest, might mess up data transfer)

  -h	print this message and exit
  -t	don't generate seperate PS file with thumbnails
  -v	be a bit more verbose
  -3	fake all Type3 fonts as Times-Roman";

&Getopts('abxhtv3');
die "This is $0, Version $Version (Rev $Rev)\n$UsageMsg\n" if $opt_h;
($pdffile = $ARGV[0]) || die "$UsageMsg\n";

$noType3 = $opt_3;
$verbose = $opt_v;
$NoThumbs = $opt_t;
$avoidBinary = (! $opt_b);
$opt_a = 1 unless (($opt_b) || ($opt_x));

if ($opt_x && (! $opt_a)) { # use HEX as default
	$avoidBinary = 1;
	$defaultAsciiMode = 1;
	$defaultAsciiFilter = "/ASCIIHexDecode"; # must match !!
	$defaultAsciiProcSuffix = "_Hex"; # must match !!
	warn "Option -x overrides -b\n" if ($opt_b);
}
if ($opt_a) {	# use ASCII85 output
	$avoidBinary = 1;
	$defaultAsciiMode = 2;
	$defaultAsciiFilter = "/ASCII85Decode"; # must match !!
	$defaultAsciiProcSuffix = "_A85"; # must match !!
	warn "Option -a overrides -b\n" if ($opt_b);
	warn "Option -a overrides -x\n" if ($opt_x);
};

$pdffile =~ m:(.*)\.[Pp][Dd][Ff]$:;
$basename = $1;
$basename = "x" if ($basename eq "");
# print "Basename: $basename\n";

open (PDF, "$pdffile") || die "Can't open file '$pdffile'\n";

# let's try to figure out the line ending char, \012 or \015, to set $/
while (1) {
	$c = getc PDF;
	last if ($c eq "\012");
	last if ($c eq "\015");
};
$/ = $c;
$c = getc PDF;
$/ = $c if (($/ eq "\015") && ($c eq "\012"));	# handle DOS's  CR LF

if ($logging) {
	print "In this file, lines seems to be terminated by ";
	print "Carriage Return (CR)\n" if ($/ eq "\015");
	print "Line Feed (LF)\n" if ($/ eq "\012");
}
seek (PDF, 0, 0);
# done. now let's start.

$_ = <PDF>;
/^%PDF-/ || die "File '$pdffile' is not a PDF file\n";
if (/^%PDF-(\d+).(\d+)/) {
	chop;
	$pdf_version = $1 * 1000 + $2;
	if ($pdf_version == 1000) {
		$pdf10 = 1;
	}
	elsif ($pdf_version == 1001) {
		$pdf11 = 1;
	}
	else {
    	warn "'$pdffile': never tried $_ files - let's see ...\n";
	}
}

sub put_proc_set
{
	if (open (HDR, "header_for_pdf")) {
		while (<HDR>) {
			print PS;
		};
		return;
	};
		# if header_for_pdf not present, use this stuff:
	print PS <<'EndOfProcSet';

% PostScript definitions for PDF interpretation
% Copyright 1994-1995 Detlev Droege.
currentfile /ASCII85Decode filter /LZWDecode filter cvx exec
J07)\i!]IG!!!$b"FpQf%g`4F^^#[A$ip<WSRDL(Zsklu!It/8#.YcdM3.cZ":.D<
rXOq2L2ja0)uta<_>l<s,fVJ:)UG/l3<0$n!&m:,!DiiJIk?o,BV<-@n;Sdq$@i-X
m6X<@!(]Cp]!qf<+,Q$DdRc<L!E:d@_&rk;/gVL0d4Z5$Zp$ef!"ks4C9@73@i4!O
#XABaM)(]*`7SIB!&&u"K5f9Er%cIr!rsDF.p[`n&HFo!dYWS6A#6WTC59@FHoqC.
$oSf(S!R3LM=.P^rJ1MkhVZE!*%89/Mdp@'B5iZ,68:dl5OVHeKsk4qRK*?g!rgbJ
#j(bu;AqPsbo?<3.!-j3kJ@l41ACI:5dtpG2$MHX![2LRL:/M6!2d&u"2Fn1"E.5U
Z&B6(MuXUo$ma[0"cIj!(BFXs]I(b<ZLB9H+^3cs&I\T"]O`UB$Tq9"jHmTA>(0=0
Bg`5K/J(!;T90`N;J\lVC_4'$AK-)[QkE#cihHXXN1H:JPFT*,"OsU`92\q[N"^7-
;)$()_#l?T'1AdKOHTDo2^kW@;(n(GUpto<&i,Ii:K&/15>TC"D]qj9jG^X7'KhX;
TB$_&!"9Q`VP9kt$\#X='XY<1Uh'E^!#bk(?D!G0q2nTQ'<1t+bN8t28'U+j^0F]\
]_5:FaAF*ce*6[.,:"MQJMAGrl[G]L!9Ht7'/`d\<mP=T@qjMZE>9]DAVIBp:dl\?
VVCeO0MC23L!+!O"73`i?#giQ9t;[Cj#<#S1I<?nol2@!LDT<E!"JG(63L[r!!#^L
Vnb6(TB(+.G[^<C'MGq"g!P]33#O4'[0$UnE$Zd$1&q\"*J0E=:pND1AQD,e8@Ri7
TFFlb),6Ft"ibP?,p[hdnV8"]4,"9PGQ8:gfcimdB7NI@Q%0!AIYAaAc>in!OL)_b
CK^d/7-R&C_kX%R4+7K8JB##ak[4E7[qndW/?/mnVU1lqPo7pVeEPWjhknAJ!P4@O
W):J"$^kt>\mPUim(3kBFHMXW)8R4pLpnA0]C-(]66Q`*7VHk%Jr5YAXRbN#PT<Be
nA'Tf>k(^_PNQ!Y%\HDp$6@U&n>P9_4I:/[Zbj8(SiY]Y`,B#`&UE39S_^EiYRBch
rU6JFJ:5!u+F%/$!.?H4HFNIX.2h7>pBH5;jX@+5q!WSOjE/b?T>F(o*r.]7Dtj;r
oL;K7Z-NCNWWE8)4@i$LI"C2UQj2b$84-Vq499a9J,m%]aafX9UkC9b1?K8.kY-ZF
!$T067M&sqPm1#DOcGdtp'IYt"gBlk]jcjrhP./u01k1bYQ4;'F3K5H@IH@B'+9^,
'7Rt:s.!0d'd+sEJ5?jt4n;'&b@r@QiW8k`Jjqb1#QP7./?uZ]`u7MT0TE?)!"Kk(
!!'rYBts^ea)_aA`p@CbA&+kK;7@H77"f>cAjd92$HG]BZSo$1qAM`,;pNIG1*?S\
U3#NDO.qD!kb/s2R7_l/C%Pl-!Q^E[Z4r,J-mrH_16_8[G"DHgPYaUF%&Z?d_Z[5(
!?t^0J>jr(BE0!Wr/=;^Y\6;?`?4[km)u\`*mU0+RDsX$NdrO$Au*#+,JIb#q6im)
#e6AfhJeYBXLi)g^mITE6r($n4%]A=+6!3Dbh;.$-a>n."Cc-Z0G+cW2#d^n#%L>^
Gs>t9cSS/OG#78n`/`()3!1@^:O4Q_9aL!RZtPS[MC;(-(f3'qga^_Hr]Fm4oEPVS
OG3NB&!>)QHuuNP+i/nTLte&77C`I*EnZ'Mh)U$Qie.;'i^/0t5cH$oWKdQP!2r/#
W&7Pe<I,2WBS&8ni\#m0([3o:.A7iJ`2jUPi(PPu=?qDR\.\$[?43.:6H"g:<ru2h
_M*+[oX8M,5cmJ3E*"F;WcHQEZ7F6/7%jd+X;3Ne?n74)!!(HH<B>k,)8P176ste4
!gkD"7(FMkehjhN+_E1g2mL?[Z,"8`:+4?',U;9igCde.aUB>uEsRI/$[Y.1,?94.
NVltsTQn?h#S%*fU`&_m0H?X56Pg`$=@@$MlrX6"dS8EF6Ap,Gq&"-2<QL6\0L*Yg
7B#lr&WimB*GnK>[`I=\,B/trl%)YrQ>l3JoM]AZ`WNQT#bU%qYY21e^HR4eqH6I&
A3^=G[e2&pPHdDi/k!4`P-Fd!1UCoQNCgg.Nq\V*?$Hk%%Or8Sc^lfk:GE/n/9hC4
?@lI>YeB8"-ZB&q_Hi,$4n\jV2Z/gIo$7Gm*QKtIjGj#gB?Q[(`tUA/'R[#mnA%#n
ARN'#$;Og@!8,J)rpLG8]e@\35`3>YO_*2?j=9+@^rY<&^&/V,Yi]iKj^>(jL=hLQ
/eZA3(<ISe/4p5QT[<8O#O$26GH[#4^fkLpl-`jiSfT)ojS533]Jj_#_;cLR:D++r
/RZo$W^?QNrZ=i.TX+R)ds)O3,CGVE1She1k@[!0E\48.?@t`>BS?YLV3_R5_aKUP
AF#cYLGf?Z!"Sp+D#H`!EE4;-8)OhedbRkN72X\+jj>e$+>".m7\LDPU#elfG'ANX
Y=5UH^jXk4%i#B--+^9#RJFUr-LKaThgt,$eok,=#Tr[(M"&[LOblcmi`$TlENUls
FpZik*,g#k5!QDt;G*@)PCR\f:1(d:c'RLG?ZO$>bpP.HhPC&s'B_S-Y=.\GmT%X&
U<@\"*Tb%k:DDeI,L^R$:TL$Z5]n&:\9bP_lC3F(FagsQFQibjh.Nm6:8+S3hcT7d
:Tr;4\(UY.CraKo@Zp0FcT1S[S?e67*](tcc_REad\NrX?uY-4reW#rba2H<IK0On
jjEjb<&f:K!!A"4]=<fA&eo3m]?#MmTs4AnY/!\gWG<4diq)j_hi#VJ:Rnp_Pd91G
=]eLAQfO4`AFD6u#f*Fd,c!EsYQ=2i\81digYW6]asBXRI_:@S-(A6!7a\Jc.,bEs
G9_Zb0lO9X,u]>AKU)AAhnM66JF381NVWq$au^c>qF9$?*e"+hp6[t,LKVb5O-]eJ
Z>eq1podHW:NH,d4R#YEWhNbt9S,OlFtI=;/T9Phk9C!Z:>KAL!5rdX0AQ_JG6>&*
S?O,V0('qp5XU'@s"F*#kG7sY70*qI%.INV#lY"3DVr=O#>bmT!8<f-`X`9Bg&_ss
i=`Dug;oA'e"_U!j64So5!!.>/n!WCD:TpC?NhVP#\3*&l[\pe70[]*,68XY8!X,c
SICLl--r7Sn$rmgg*7+67dbT\&,cE:kQLBo,]ElUn*#\UNr`"=LCcf=Wm:^M(B,QB
#=I_=6<nSb%Uc'<%c[!S6aA:2ZOX)?4i=Q>j671C>[K38qBO)]+G?!]Hp+\)'FUNI
nM3:^d1u*K7e'A<0gmDN[a*8_7e'_Qi854tOpu>B&"in3Z&7O;+A#Fm#N>XnY/W`s
Lc[>a/TI4KmnFAq>oKuT,r);:"6gb]>!@\X7c7<2J5F0o6G3\1]Ar,qj0Kd0D@C%>
!X/]?UZg@3<]_j_--tp(aXlNcHGU54,8'FtN(1C[If?;r_\$Z,LV=u6-QaqY`3L4A
1'2c""t/nH7oCWWMpOM\D]b^'+6%bp-ZL=#3;?r:'i!Bpc"t=<gEC(5,f28^&QoT2
kp=;S-4C8/;Cs6$)UX[Tf<09jKBN\8+;6!`'1:sjl6$^lkn#+Y-Gf]^M('*Jkn;#]
&d!OGJprrEc6^:c)BrH7_GVNW'H5n!#EdamEn^WS2]\S_%KQ>1o'%dBIO3D*+VNZa
P2%:&lRqbi0@L(X;ZA?nIkS'T/n-al'*Bgb!?Ihp*$Fo-!]Mm@/g\@;4"44r@U/[q
Z3pd!$dsh6J:f62>SufWQpPs2">hpp:]qG@dc9PcKPr[<*'5rE7e92-d$?'NH6q$i
2_7Gi`,@VEIlO0.2aS*";hR>uR#g;X.KgIe9gLb<GT/=,nmi":"<oY]C`O1(edY)1
+N5nKIe$r7$kpK($,-NB6oup4":$>=M+EtaXS]'_-Ap*8J,qM^]*tn8-c/58A$[/L
>aI)r(_c&Z'FXsU&<uZr/7=SH9btc:5sRbB4b=J5is6_@+#_>U6;Xno@M(tj<lQV'
75RY&0$)N2E:_RZ$W:(O0YW`m0+EnP7`(fJJulWn0^*TI_Z?;mK%t_4NYmC`I6]JO
b(`@c!#Lkq#(gY1Pc>rA9gA!k"qd%lJntTI^If`$*n7M#&(1Lna%F,I"#SU@_o;]k
h[Qb)5*OG5cR(#I+@*e?DuifW'M/?^[l^U361k5u1o(3&CI"f34EF@I6D7$?o'q<\
%3t(WW,kTH+Z;b[.o[Zi+9>D-gcT]o(%k2Nd7mL*3t$U35(d3)nIT^b=[dtK"jKV<
,ATnO<?-'M$8la$6<jXiW'^0.7;^U<FK%D:e0>JN+[Jt(b@=I$a\l#m*RF;O6KSOg
4OSb"=qf-6FN$2'm%P,kd7l\_#9s'iI`;gY-?Y9gom]ZncNam$6Gf)t&G]Gd!EDk]
6A08Z9gmdr78@ga+7AnJ!!JY\igc[c-c-U,2*jsSZ3g]t%T,r"i[nU'b0OaA&p4u,
_HgWs$6^.m!#9,e.Tl0rO&GV-hua&TeC5r`2&5cF>Z4VNY<"a!=%e-7++n;O6?WA$
0cRQ6<=Sn1KPq=^"s;%0Q-YG&_m1!$@Qp*%"C_rSKBX4*_(9&F).HNZ!!']bkbVg-
%Wla)';-Q`VYDg2BnN_`QI.`\kgU/MP=)XT_UiYT@f+I"=^h<2&-j+3\IjGFC][iU
(0%<L!DM(Qqp*`3j6:I/]4htU>1RUs_ScETa'/-C',F1c@1c_i2de8aF#Q$ioVG\B
Vc6_qs"/-Q;BZ*#0R"9,-h)`tOMW7c4]-E@f<l99MlCqN,Rk@D]0NVtpI7XEHUeW[
BbTk#A$]I+iF!j7!,e/d1[aH:Da_g&U(U$/e7ffO$Od_R4,k7WW-"OD,=5jF5sg&e
KJ!Z5=?A/N5k":5<9ln11'#lh[m0p6(ZmO5NY<63:c)$tQ/>.j(Bs2UJQ,uA;aA1+
B1:7.Fr0"!Q`Y@igN!eKEQ\n@p[BCC!I7@.r03%b<2E.Od5_i"+7R-"@8fkj_+jt1
'KBY/'UMMSF]fQ'_\Gqc2n[%j'^KYTY!NmaJpoN$:_lFU*?fE'`,;^monLNP!#@[I
"C$a"VQTt#L,c5kiZS?>IgSRr7*.qI'GG<HPDcnUNE(3mpY;CYZFXML,[bVK%A;GM
=#_BYH<#qs=K'!eh)BT:5)H]of]]oa)ik<'-8f0WeF,Y2rpjMf*roYr:B;[BkcXK_
?dojY6jNeqK^A7tW?OYk!@YU56G.IDA$m)=3F,V:(-EdXN#9$f\T*S3o.33dPX8Z1
Fpob?,iB75-.U0COKD(d$V^]c#1pg'3Lu=8G:9N!'bt(LP&laO0q.TFqO*V('Eaif
^+OA/7PJN]\]#.3ngF"UE+/bu!^\%q7>J$2"Sq7Np@'m$!!NZ[-,@YJGtL8e!3;an
T%,c0-`<LZ>RWDn-!C)e@Nh=ZKZ!pHTn9LY8M&;@_4gUe>hTda==\6?Mk4)>-.Q0\
.a<,aO_T1iAm,g/2.f>S:.G(YJL<saRFEApo0Yer#`I'!H/\f)-)]!K&*(M`+Up9Q
JZ17fWIinP!#l^@J0"K^bl@jGUW+1?W\bkTWDCqG3iXUdfg&Uo*nn[p!'++'!'C7<
WhMruHF>Gp]r;q5Y$.<q_WDDU_>jT-WhQF*3iY:C)6Q#jfE#'V+\Si0'Fai`/mtlc
TIm94?j>??6b<Z-]*eKZ_m)H,)"DKa+\9KNUU/r=C.(#^[#c"20F:qP;OY6L?rJo&
+r-$!*kL>2qU?qOe#o@]XQ)V[HWgY9?2t$%W0pE@]8Rp6V5qI&#+K-J@;\1O?it_T
-GYbFil2t-Ot(uD\`+/:Mio#`Os\#C\Kem,g5'bmJZ.K,(cpXq>He).f=/Nq(OE)6
@2$0q'G-as,[cb8_o<4VOu+>K^4>U],/tTA)?9f5^4BA"JW%5cFhqKrXPuP`Hj90^
1(h.^'YE?<>Ncj7mJm75\Kf*1Hnkt2l42S4&GtGtS/)Lf1)@Lo6Q;1:i9.89V8FF\
_#OH@r%\KrOtL-j`h6tZTE#(A!!!"#_]V1]+A9bj.EH!0__A[_!"6i`l*[5:X271<
]J:J<l5MeL)uG@-g?KLO=r=j9%XR+9]':&Wl5)O:'cU<iqW\dmC(spO%9lE%:#i._
IQSehW,'`k&C\BT7PT9a!#u.&*"M$0iQ@Z_6_%]J*.$ZcG(EnK6_'%p*/2dfO!pNe
j;aoT*1h^dVF,kM_`Y6c*3V_7[R6Rrj;c,!*6dI`aFRUC6_)fi*7X$hki<`EJR%P/
SFGSX]&Xf\]c0=rTc(0U=qA3X`uV/[)g4T!_6plsd<h3.Rot[GcbJ3"`CnPn0[mO;
`SGaH#2>NOHG,WUce_s\Q7/;_(GiKDV>qRIhP*rj:-m/Gp&R=Z+8Y`?h>B)jWScOq
e$E.B+93BbW[7bGWsLemRloaNguKF@j;^SG)W9NSA$.m'j;SciHNE+F#"+jOnbW+C
*8TMhkKh(,ZZ:j04tX-j+g%JsZ?n&*RjnVI8$!bYaZ_)SHMj%urVuu?hE&l3>NUKA
']^4k6_#(U*"(aH,(WuG6_#Xe*$=7s5MgXe^771D**e&"@F>u8,@TrL3lfWp(uuW_
d9sN$@&L*e#RULP])D=-S*1(1c65G_m@k03fM@J)('U+<4#FE?JeS8C<$>Tc4#JU:
/_BQX"=4,J%KLd'Q5mp@cW$MG8M=<n&&i56A0N*A"*JbV^K$sL>@6Y=H$D\RT2m0Q
EW?o!4#_M02h1SRKU[Jl*$7D-6)")K%>+>RJNkCO[EujA;i>95nJQgf[KZ656e4*)
q>+Co6='0^''Fa$d"2gm!aP8&]i8A?@fdhN?\=GC*[gb.5M+XkaG^6d-hL;nrPC5p
@K6CZ+M\N^ps'!B7">9q!s&0&"b2\D0M!nW.KBO#![JVA)Bf._J,oWN,^9>*J&l1U
,K+1Q*KRtR5T-!@1BniE?h&uA^(V^pJ,n#S;"bP1Oh)elYYY?T+dEdP1,04V,qOX=
^_M\/nm<R@=">%W'\^kqZqFfRM\V]6/"TtJ25lc9j*6^-_q!rG[WsEda[4VG"O%0D
U&YZ*p_57_%`_ghPBl6KB6KZb/Tni4Y1G-jfI*#D?@HJm\\`3'\X:rm%A;A?GO)ZG
B5l>bk$U8>Deh-a:BNV)<&B\%RDgLo\Xh_[5d=/LZT:Q?B\;E5J.sgFDPpLmgj"+:
'mInYYjF%_%n<;B1XO(CQadgcH#X(<9d\o9gb=_kkiad\j!`tL%jQVI2[k=0`]=C#
E5jiQ_f3mG#pLW30o3_lgc>bg#g3Rkj.OCGN_oN-1W/6$ehdl@]M^eMUL:r"`8`Bg
2Fc_jqD4(_Gj$i?@iQ=H$q$-!3t.m#M\SV^8D#[+UDVE>$ur5i2@Q@rW\]Z&%%8Zg
o$"QqbOR3)15YT2`\N7cFGD?)_L0T[%C5'--d?TQP;gUX9H=4oUR9IiM)3)t0*sH(
as,1hKaB'Pj-YHhLpUF[1l+!Dp,kW[5gVHMUR8q'N[(W\*K3?n`%[3]/QGhJn@`12
N3s5G$HV`@$8N$B#gWS_6R?"j%)YW]3m)TLc8J2Q37']hQ?7[!N2&4)3f[*C-9R79
'Hpcl_TaMs;$5(j90pJ"djiq1-)G?_6S,idhUXibA_sh"$%:\B+PU<7@mh2de<=R'
-]X@[WZ^9KTZSD*6^ZgVN46=L1l`9XX_a!&*U.=l\I=7E97qV@2[tm[*\`S;S-V4c
EP;];NoP7^6Xe@>Kq/\5S8X#g0dVf,NcN]12e_4obpP`Zm$p+t0OWfs<6u34;[N:@
@Pe?7/_NNhj.sXDalAK7$4[0`8L9>f7HY]DZ@!Tm@e!0J0b+:N`&cWtV.F[[n19nH
fQJ\/Z4:BH5;\D-OR#EXG^N*&NVnIC(/.V>habgkS_u?O['Uo+:Gi<BcO?RC+!(!\
XV!(+1gojkc3#X?,Bbg*_\C/o%OET`4D]r1;j-kM3-Z(c#V,A=Ii9\ZP_C/%aRS>/
+Q\58K>u>@[@](3Pp#-H%m>]l.X^tJ*]ELIG-F)b^GjEU<DcKQ3Q8m'0au.6r?-b'
Mk"h"AT-Oe5]dL>&3tGQ6.Q/D+OG_-3,V;R]JZA$?lYV5.7<&g'I=;q*YR[SKW"l/
KFhCtd\q0mW)YgkGXTbSLgtqna=4BINXMM3`eSA@(C)kE#(n<k%H4N-/>RV*,#^<.
JP"Pskb&S0fOPJC25pgGTFh5^7!N.+/qdaTKHams$=VF="D"AI:tcUUZ*6+i"B65U
QpZW`dEMnMKZSih7h(P_%jD",&;,4POE"jjU\PIV_k9sp6'O$WjquBqP.Hc!,pG(Z
`Xl.[AWn:K!/48)L;P]H$fR$tL1%_9j\&hfTjgZM#h]HWMRj/\_=ImlAePo8FH<Le
4<g2+-CKh!$>^2W`IQ;S6Wd\]_4"Ci'L=O,qAbc@3@DYP*#PCqe..[FVTS/=$\Li2
#XG=L#D<^/_JE1E_9t`t$.os089t]<C`!?&5mrc6+Cn&C&-K^q#Q]Gu<^G(D!Y@[5
"!CPLJP\3-5fON@]L7+f,mD:JSBB>R:I)`R=GF&5'ET+<%5&&;+F&te6\6pY!=UF)
fQ@]LE`Ro\&h_XdWY?%9D%:R-H%^rX[)8P.$)&YPLFQVicm6e^aCl,.6pMSbk]6k,
^,NqP>oeM@-4BIY3PqH47[,cA6B&Jd;ei^9,8EGD#P8QNWLt4]XHRTX.Pm`D^4ZN#
7LUHu&6H*s#V2&V"gY;HKL^b66CO`D0cV?iOJimF!-kPY<#=%5roTBl9+7+'2ch\h
&nq>WUeR@9LPnj1_^pm8G/,kc0ZXZ<l:DD8'J'A0YS7/0[1%T$,(u1;&;!G:#Jgk:
KJ8i16<HUd'-&6M+GLT5:i$F%Lcg>EO&D.A\."11GGK2SFRLVE]LY.?h2oJpDb<O1
QTFnpY]pZ[Otqp9?1V3\aqTG89FF-mra6-;&Ak:A#acOo"CQjUmN=In\*tO!$l``o
9gl<&\0-H_0H7m%8d%DL.KZ9A)fRc9%ma#PKg=]6"#*.NJI!_/E)[[*:hBl&0(Oc?
c5=H8edQ5j3S#n@)qagpJl@5R"[%kd/W_cY!JplMgmB*)Q;>Un2P2+*^k+>t3,QKZ
3X5Gu*DoPbD5$,IAkFb=-P0jSaDtO?krbZdP]0/2cT6fL^GN:DDG^0$1M6REK]s%X
$:2A;kB'=MoKJ+Lq?ogWV,<nm,hGA&+h'3l5RIQ0.0KXh*.s>b$[!"@#,$MVLIA]o
[8JJ>Tp-)i8M7X)3ZeSlJ/JFHAZA$=,Z&gKK=k_*2FEa<C#H=!CV>$"2*`f!+N%jp
I<5l`cnksBkSSq[5T)G2"p=rA:kA\7k+L@If/n49lQ'S&5Q~>

EndOfProcSet
};

sub find_startxref
{
	seek (PDF, -50, 2);
	local($found_startxref) = 0;
	$startxref = 0;
	while (<PDF>) {
		if (/^startxref/) {
			$found_startxref = 1;
			next;
		}
		if (/[\012\015]+startxref[\012\015]+(\d+)[ \012\015]+/) {
			$startxref = $1;
			$found_startxref = 1;
			last;
		}
		next if (/^[ \015]*$/);
		/^(\d+)/;
		$startxref = $1 if $found_startxref;
		last if ($startxref > 0);
		$found_startxref = 0;
	}
	warn "Could not locate 'startxref' entry - truncated file ?\n"
		unless $found_startxref;
};

sub load_xref
{
	local ($start) = @_;
	local ($first, $num);

	seek (PDF, $start, 0);
	$_ = <PDF>;
	chop;
	/^xref/ || die "XREF not found at pos. $start as expected\n";
	print "loading Xref at pos. $start\n" if $verbose;
	while (<PDF>) {
		# print ">> $_ <<\n";
		next if (/^[ \015]*$/);
		last if (/^trailer/);
		($first, $num) = split;
		for ($i = $first; $num; $i++, $num--) {
			$_ = <PDF>;
			$_ = <PDF> if (/^[ \015]*$/);
			chop;
			/^(\d+) (\d+) ([nf])/;
			if ($Xpos[$i]) {
				# print " ignore Xref '$_' for obj $i (use $Xpos[$i] $Xver[$i] $Xuse[$i])\n";
				next;		# don't overwrite existing entries
			}
			$Xpos[$i] = $1 + 0;
			$Xver[$i] = $2;
			$Xuse[$i] = $3;
		};
	};
};

sub token
{
	local ($token);	# $tbuf sollte 'static' sein ... :-(
	local ($tktyp, $multi);
	
	$_ = $tbuf;
	$multi = 0;
	do {
		$_ = <PDF> if (/^$/);	# next line if empty
		s/^[\s\015]*//;			# strip leading blanks
		s/^%.*$//;				# strip comments
	} while (/^$/);
	if (m:^(/[\002a-zA-Z0-9\._][^\s\012\015%()<>[\]{}/]*):) {	# /Identifier
		$token = $1;
		$tktyp = "Id";
	}
	elsif (m:^(\d+\s+\d+\s+R)[\s\012\015%()<>\[\]{}/]:) {
		$token = $1;	# Reference: 	num num R
		$tktyp = "Ref";
	}
	elsif (/^([\[\]])/) {	# '[' or ']'
		$token = $1;
		$tktyp = "Array begin/end";
	}
	elsif (/^(<<)/) {	# dict start '<<'
		$token = $1;
		$tktyp = "Dict start";
	}
	elsif (/^(>>)/) {	# dict end '>>'
		$token = $1;
		$tktyp = "Dict end";
	}
	elsif (/^(true)/) {	# Constant:	true
		$token = $1;
		$tktyp = "const true";
	}
	elsif (/^(false)/) {	# Constant:	false
		$token = $1;
		$tktyp = "const false";
	}
	elsif (/^(null)/) {		# Constant:	null
		$token = $1;
		$tktyp = "const null";
	}
	elsif (/^([+-]?[0-9]*\.?[0-9]+)/) {	# Number	# OK ???
		$token = $1;
		$tktyp = "Number";
	}
	elsif (/^([\w]+)/) {	# Name (\w == alphanumeric + '_')
		$token = $1;
		$tktyp = "Name";
	}
	elsif (/^(\([^\)]*\))/) {	#	String:		(abc)
			# (string) - multiline stings see below !!!
		$token = $1;
		$tktyp = "String";
	}
	elsif (/^(\([^\)]*$)/) {	#	String:		multiline (abc\^Mdef)
		$token = $1;
		$tktyp = "String(multiline)";
		$multi = 1;
		do {
			$token =~ s/\\[\012\015]+//;
			$_ = <PDF>;
			if (/^([^\)]*\))/) {
				$token .= $1;
				last;
			};
			$token .= $_;
		} while (1);
		print STDERR "ML: '$token'\n";
	}
	elsif (/^(<[0-9a-fA-F]+>)/) {	# HEX-String:	<0fab12>
			# HEX (string) - can't yet handle multiline hex stings !!! ???
		$token = "$1";
		$tktyp = "Hex-String";
	}
	else {
		$tpos = tell(PDF);
		open (ERR, ">/tmp/PDF_ERR");
		print ERR "Unrecognized token: '$_' (near PDF pos $tpos)\n";
		die "Unrecognized token: '$_' (near PDF pos $tpos)\n ";
		$tktyp = "Unknown";
		return 0;
	};
	$tpos = tell(PDF) - length;
	if ($multi) {
		$_ = substr ($_, length ($1));
	}
	else {
		$_ = substr ($_, length ($token));
	}
	$tbuf = $_;
	# warn "TOKEN[$ld_nest]: '$token'\n" if $Problem;
	die "Null token '$_' ($tpos)" if ("$token" eq "");
	return $token;
};

	# load_dir: aktuelle Zeile ist die, in der '<<' steht
sub load_dir
{
	local ($tok, $key, $val, %val, %pairs, $len);
	$ld_nest++;
	$tok = &token;
	($tok eq "<<") || die "dictionary start not recognized near pos ",
		tell(PDF), " \n ";
	# print LOG "load_dir: at pos ", tell(PDF), "\n" if $logging;
	while ($tok = &token) {
		last if ($tok eq ">>");
		$len = length;
		$key = $tok;
		$key =~ s:^/::; 	# strip leading slash
		$tok = &token;
		if ($tok eq "[") {
			$array_nest = 1;	# first '[' already scanned
			$val = $tok;
			do {
				$tok = &token;
				$val .= " ".$tok;
				$array_nest++ if ($tok eq "[");
				$array_nest-- if ($tok eq "]");
			} until (($array_nest == 0) && ($tok eq "]"));
			# print "ARRAY in DICT: /$key $val\n";
		}
		elsif ($tok eq "<<") {
			$val = $tpos;			# just store position to find it.
			$tbuf = "<< ".$tbuf;	# push "<<" back in for load_dir
			%val = &load_dir;
			$loaded_rnam {"DPos_$val"} = 1;
			eval "\%DPos_$val = \%val;";
		}
		else {
			$val = $tok;
		};
		$pairs{$key} = $val;
		# print "LD[$ld_nest]: /$key  := $val\n" if $Problem;
	};
	# print "Dir loaded[$ld_nest]: "; &dump_dir(%pairs);
	$ld_nest--;
	return %pairs;
};

# pos_to: position to given byte in PDF file and read current line
sub pos_to
{
	local($position) = @_;
	
	seek (PDF, $position + 0, 0);
	print LOG "pos: positioning to $position\n" if $logging;
	$tbuf = $_ = <PDF>;
};

sub load_dir_by_ref
{
	local ($ref) = @_;
	local (%dir,$rnam,$isref);
	
	if ($ref =~ /(\d+)\s+(\d+)\s+R/) {
		$rnam = "DRef_$1_$2_R";
		$isref = 1;
	}
	else {
		$rnam = "DPos_$ref";
		$isref = 0;
	};
	print LOG "load_dir_by_ref: ref '$ref' ($rnam)\n" if $logging;
	if ($loaded_rnam {$rnam}) {
		eval "return \%$rnam;";
	}
	else {
		if ($isref) {
			&pos_ref ($ref);
		}
		else {
			&pos_to ($ref);
		};
		%dir = &load_dir;
		$loaded_rnam {$rnam} = 1;
		$streamPos{$ref} = tell (PDF);	# might be a stream which starts _here_
		eval "\%$rnam = \%dir;";
		return %dir;
	};
};

# pos_ref: position to a reference (given as string "num ver R")
sub pos_ref
{
	local($par) = @_;
	local ($obj, $ver, $o, $v);
	
	($obj, $ver) = ($par =~ /(\d+) (\d+) R/);

	print LOG "pos_ref: ref = $par, " if $logging;
	&pos_to ($Xpos[$obj]);
	($o, $v) = /(\d+)\s+(\d+)\s+obj/;
	if (($obj != $o) || ($ver != $v)) {
		print "=='$_'==($o, $v)\n";
		die "Illegal Xref ($obj, $ver)\n ";
	};
	$tbuf = $_ = <PDF>;
};

# pos_dir_or_ref: position to reference or byte, depending on par format
sub pos_dir_or_ref
{
	local($par) = @_;
	
	if ($par =~ /\d+\s+\d+\s+R/) {
		&pos_ref ($par);
	}
	else {
		&pos_to ($par);
	};
};

sub load_pages
{
	local($ref) = @_;
	local(*dir, $kids, $typ);
	
	# printf "[$ref] ";
	# &pos_ref($ref); %dir = &load_dir;
	%dir = &load_dir_by_ref ($ref);
	# print "Ref '$ref':\n"; &dump_dir (%dir);
	if ( ! ($typ = $dir{"Type"})) {
		# circumvent bug - some /Pages dicts don't have /Type fields
		# (seen in file generated by Mac Net Distiller 1.0 from FrameMaker3.01)
		$typ = "/Pages" if ($dir{"Kids"});
		warn "/Type entry missing in Dict '$ref', guess '$typ'\n";
	}
	if ($typ =~ m"/Pages") {
	
		# printf "($ref) Pages:\n";
		# &dump_dir (%dir);
		
		$kids = $dir{"Kids"};
		$kids =~ s/\s*\[(.*)\]\s*/$1/;
		while ($kids =~ /(\d+ \d+ R)/) {
			&load_pages ($1);
			$kids =~ s/\s*\d+ \d+ R\s*(.*)/$1/;
		};
	}
	else {
		die "wrong type: '$typ' instead of '/Page' in object\n "
			if ($typ ne "/Page");
		$page_cnt++;
		$page[$page_cnt] = $ref;
		# printf "($ref) Page %d:\n", $page_cnt;
		# &dump_dir (%dir);
		
		return;
	};
};

sub dump_dir
{
	local(%dir) = @_;
	foreach $i (keys(%dir)) {
		printf "%12s = %12s\n", $i, $dir{$i};
	};
};

sub gen_page_resource
{
	local($pg) = @_;
	local(%page, %resources, %fonts, %xobj, %cs);
	local($fdir, $fnt, $key, $xdir, $cs);
	
	# &pos_ref ($page[$pg]); %page = &load_dir;
	%page = &load_dir_by_ref($page[$pg]);
	# print "Ref '$page[$pg]':\n"; &dump_dir (%page);
	
	$cnt_annots++ if ($page{"Annots"});
	print "Rotate ignored on Page $pg ($page{\"Rotate\"})\n"
		if ($page{"Rotate"});
	&make_thumb ($page{"Thumb"}, $pg) if ($page{"Thumb"});
	return unless $page{"Resources"};
	
	&pos_dir_or_ref ($page{"Resources"});
	%resources = &load_dir;
	# print "Resource (pg $pg):\n";
	# &dump_dir (%resources);
	
	if ($fdir = $resources{"Font"}) {
		local($fn, $fref, $refnam);
		# &pos_dir_or_ref ($fdir); %fonts = &load_dir;
		%fonts = &load_dir_by_ref ($fdir);
		# print "Resources/Font (pg $pg):\n";
		# &dump_dir (%fonts);
		
		while (($fn, $fref) = each %fonts) {
			$fref =~ m:(\d+)\s+(\d+)\s+R:;
			$refnam = "Fnt_$1_$2";
			&font_prolog ($refnam, $fref);
		};
	};
	if ($xdir = $resources{"XObject"}) {
		local($xn, $xref, $refnam);
		&pos_dir_or_ref ($xdir);
		%xobj = &load_dir;
		# print "Resources/XObject (pg $pg):\n";
		# &dump_dir (%xobj);
		
		while (($xn, $xref) = each %xobj) {
			$xref =~ m:(\d+)\s+(\d+)\s+R:;
			$refnam = "XObj_$1_$2";
			&xobj_prolog ($refnam, $xref);
			$XObjects++;
		};
	};
	if ($cs = $resources{"ColorSpace"}) {
		local($csn, $csref, $refnam);
		&pos_dir_or_ref ($cs);
		%cs = &load_dir;
		print "Page $pg: unhandled ColorSpace\n"; # unless ($cs_warn_cnt++);
		print PS "%%Page $pg: unhandled ColorSpace\n";
		if ($verbose) {
			print "Resources/ColorSpace (pg $pg):\n";
			&dump_dir (%cs);
		};
		
		while (($csn, $csref) = each %cs) {
			$csref =~ m:(\d+)\s+(\d+)\s+R:;
			$refnam = "ColorSpace_$1_$2";
			&cs_prolog ($refnam, $csref);
		};
		# ??? ColorSpace ??? noch nicht behandelt		
	};
	foreach $key (sort keys(%resources)) {
		next if ($key eq "Font");
		next if ($key eq "XObject");
		next if ($key eq "ProcSet"); # !!!!??? noch nicht richtig behandelt.
		next if ($key eq "ColorSpace");
		print "Page $pg: unhandled Resource '$key = $resources{$key}'\n";
	};
};

sub setup_page_output
{
	local(%page) = @_;
	local(%resources, %fonts, %xobj);
	local($fdir, $fnt, $key, $xdir);
	
	return unless $page{"Resources"};
	
	&pos_dir_or_ref ($page{"Resources"});
	%resources = &load_dir;
	
	if ($fdir = $resources{"Font"}) {
		local($fn, $fref, $refnam);
		# &pos_dir_or_ref ($fdir); %fonts = &load_dir;
		%fonts = &load_dir_by_ref ($fdir);
		
		while (($fn, $fref) = each %fonts) {
			$fref =~ m:(\d+)\s+(\d+)\s+R:;
			$refnam = "Fnt_$1_$2";
			print PS "  /$fn /$refnam\n";
		};
	};
	if ($xdir = $resources{"XObject"}) {
		local($xn, $xref, $refnam);
		&pos_dir_or_ref ($xdir);
		%xobj = &load_dir;
		
		while (($xn, $xref) = each %xobj) {
			$xref =~ m:(\d+)\s+(\d+)\s+R:;
			$refnam = "XObj_$1_$2";
			print PS "  /$xn /$refnam\n";
		};
	};
};

# copy /Indexed color space table from PDF to output file (THUMB or PS)
# &load_print_index_lookup($lookup, $name, THUMB);
sub load_print_index_lookup
{
	local($ref, $name, $OUTFILE) = @_;
	local($tmppos, %idir, $filter, $inxLlen, $l);
	
	$tmppos = tell(PDF);
	print $OUTFILE "% Indexed lookup table object $ref\n";
	# &pos_ref($ref); %idir = &load_dir;
	%idir = &load_dir_by_ref($ref);
	$l = $idir{"Length"};
	$inxLlen = &get_val($l);
	$filter = &gen_filterChain ($idir{"Filter"}, $idir{"DecodeParms"});
	if ($stream_is_binary && $avoidBinary) {
		$filter = "$defaultAsciiFilter filter $filter";
		$streamOutMode = $defaultAsciiMode;
	};
	print $OUTFILE " { /$name currentfile $filter\n ";	# defer execution
	print $OUTFILE "1024 string readstring pop def } exec\n";
	# print STDERR "CALL(2): copy_stream_len ($$inxLlen, \$OUTFILE)\n";
	# if load_dir_by_ref returned a "stored" dict we need to set the position:
	seek (PDF, $streamPos{$ref}, 0);
	
	&copy_stream_len ($inxLlen, $OUTFILE);
	seek (PDF, $tmppos, 0);
};

sub setup_thumb
{
	return if $setup_thumb_done;
	$setup_thumb_done = 1;
	
	open (THUMB, ">$basename.thumb.ps")
		|| die "Can't open/create $basename.thumb.ps\n ";
	print "Thumb File: $basename.thumb.ps\n";

	print THUMB "%!PS-Adobe-2.0\n%%Pages: (atend)\n";
	print THUMB "%%LanguageLevel: 2\n%%EndComments\n\n";

	$thumb_x = $thumb_x_off =  20;
	$thumb_y = $thumb_y_off= 680;
	$thumb_x_inc =  90;
	$thumb_y_inc =  130;
	$thumb_pg =  1;
	print THUMB "%%Page: $thumb_pg $thumb_pg\n\n";
	print THUMB " /Helvetica findfont 12 scalefont setfont .15 setlinewidth\n";
	print THUMB "180 820 moveto (Thumbnails for PDF-File '$pdffile') show\n";
};

sub make_thumb
{
	local ($ref, $pg) = @_;
	local (%thumb, $filter, $w, $h, $bps, $cs, $hcs, $len, $mypos);
	local ($tmppos, $dec, $base, $lookup, $lnam, $hival);
	local ($tlen);
	
	return if $NoThumbs;
	&setup_thumb;
	
	# &pos_ref ($ref); %thumb = &load_dir;
	%thumb = &load_dir_by_ref ($ref);
	$mypos = tell(PDF);
	
	$w = $thumb{"Width"};
	$h = $thumb{"Height"};
	$bps = $thumb{"BitsPerComponent"};
	$cs = $thumb{"ColorSpace"};
	$len = $thumb{"Length"};
	$tlen = &get_val ($len);
		# must handle /CalRGB... (PDF-1.1) ColorSpaces
	$hcs = &get_val ($cs);
	if ($hcs eq "[") {
		$hcs = &get_ref_array ($cs);
		$cs = "/Indexed";
	}
	else {
		$cs = $hcs;
	};
	$dec = $Decode{$cs} unless ($thumb{"Decode"});
	if ($hcs =~
	  m:\[\s*/Indexed\s*(/Device[A-Z]+)\s+(\d+)\s+(\d+\s+\d+\s+R)\s*\]:) {
		  	$base = $1;
			$hival = $2;
			$lookup = $3;
			$lnam = $lookup;
			$lnam =~ s: R::;
			$lnam =~ s: :_:g;
			$lnam = "inx_lookup_obj_$lnam";
			 # PROBLEM: this load should go into the prolog of
			 # the thumb-nail file. Would need an extra scan for that.
			 # So I delete the loaded entries mark after a showpage ... :-(
			&load_print_index_lookup($lookup, $lnam, THUMB)
				unless $loaded{"THUMB/$lnam"};
			$loaded{"THUMB/$lnam"} = 1;
			$hcs = "[/Indexed$base $hival $lnam]";
			$dec = "[0 $hival]" unless ($thumb{"Decode"});
	};

	print THUMB "% thumbnail for page $pg (object '$ref')\n";
	print THUMB "$thumb_x $thumb_y 15 add moveto\n";
	print THUMB " gsave currentpoint translate";
	printf THUMB " -1 -1 %d %d rectstroke\n", $w+2, $h+2;
	
	print THUMB " /.im_proc { currentfile ";
	if ($filter = $thumb{"Filter"}) {
		$filter =~ s/\s*\[(.*)\]\s*/$1/;
		while ($filter =~ m:(/[^\s]+):) {
			print THUMB "$1 filter ";
			$filter =~ s:/[^\s]+\s*(.*):$1:;
		};
	};
	print THUMB "} def\n";
	# print "THUMB: /ColorSpace $hcs\n";
	if ($hcs =~ m:^\[:) {
		#warn "Can't yet deal with /Indexed ColorSpace (Thumbnail page $pg)\n";
		# fake it as DeviceGray ... !!! ???
	};
	print THUMB " $hcs setcolorspace\n";
	print THUMB " << /ImageType 1 /Width $w /Height $h /ImageMatrix ";
	warn "Can't yet deal with /Decode entries (XObject page $pg)\n"
		if $xdir{"Decode"};
	print THUMB "[1 0 0 -1 0 $h]\n";
	print THUMB "   /DataSource .im_proc ";
	print THUMB "\n   /BitsPerComponent $bps";
	if ($thumb{"Decode"}) {
		warn "Can't yet deal with /Decode entries (Thumbnail page $pg)\n";
		print THUMB " /Decode $Decode{$cs}"; # fake, use standard ???
	}
	else {
		print THUMB " /Decode $dec";
	};
	print THUMB " >>\n image\n";
	seek (PDF, $mypos, 0);
	# print STDERR "CALL(3): copy_stream_len ($tlen, THUMB)\n";
	&copy_stream_len ($tlen, THUMB);
	print THUMB "\ngrestore %currentpoint $w $h rectstroke\n";
	print THUMB "$thumb_x 15 add $thumb_y moveto (Page $pg) show\n\n";
	
	$thumb_x += $thumb_x_inc;
	if ($thumb_x > 520) {
		$thumb_x = $thumb_x_off;
		$thumb_y -= $thumb_y_inc;
		if ($thumb_y < 0) {
			$thumb_pg++;
			$thumb_y = $thumb_y_off;
			print THUMB " showpage\n%%Page: $thumb_pg $thumb_pg\n\n";
			print THUMB
				" /Helvetica findfont 12 scalefont setfont .15 setlinewidth\n";
			foreach $key (keys %loaded) {
				delete $loaded{$key} if ($key =~ m:THUMB/inx_lookup:); #old
				delete $loaded{$key} if ($key =~ m:^Thumb:);	#new
			};
		};
	};
};

sub gen_page_output
{
	local($pg) = @_;
	local(%page, $contents, $c);
	
	# &pos_ref ($page[$pg]); %page = &load_dir;
	%page = &load_dir_by_ref ($page[$pg]);
	print PS "<<\n";
	&setup_page_output(%page);
	print PS " >> begin startPage\n";
	
	$contents = $page{"Contents"};
	if (! ($contents =~ m/^\[/)) {
		$c = &get_val ($contents);
		if ($c eq "[") {
			$contents = &get_ref_array ($contents);
		}
	}
	print STDERR "pg $pg: Contents Array: '$contents'\n"
		if (($contents =~ m/\[/) && $verbose);
	print LOG "gen_page_output: /Contents '$contents'\n" if $logging;
	$contents =~ s/\s*\[(.*)\]\s*/$1/;
	print PS "% Page $pg ";
	
	while ($contents =~ /(\d+ \d+ R)/) {
			&gen_stream ($1);
			$contents =~ s/\s*\d+ \d+ R\s*(.*)/$1/;
	};
	print PS " endPage end showpage\n";
};

sub gen_filterChain
{
	local ($filter, $DecodeParms) = @_;
	local (@dec, $f, $fil, $dp);
	local ($dpar, $d2, %dpdir);
	$stream_is_compressed = 0;
	$stream_is_binary = 1;

	return "" unless $filter;
	
	$fil = "";
	$dp = $DecodeParms;
	$filter =~ s/\s*\[\s*(.*)\s*\]\s*/$1/;
	$dp =~ s/\s*\[\s*(.*)\s*\]\s*/$1/ if ($dp);
	@dec = split (/\s+/, $filter);
	foreach $f (@dec) {
		$dpar = "";
		if ($dp) {
			if (($dp =~ m/^(\d+)/) && $loaded_rnam{"DPos_$1"}) {
				$d2 = $1;
				$dp =~ s/^\d+\s*(.*)/$1/;
				$dpar = "<<";
				eval "\%dpdir = \%DPos_$d2;";
				foreach $k (keys(%dpdir)) {
					$dpar .= "/$k $dpdir{$k} ";
				}
				$dpar .= ">>";
			}
			else {
				$dp =~ s:\s*([^\s]+)\s*(.*):$2:; # get "word"
				$dpar = $1;
				$dpar = "" if ($dpar eq "null");
				if ($dpar eq "<<") {
					do {
						$dp =~ s:\s*([^\s]+)\s*(.*):$2:; # get "word"
						$d2 = $1;
						$dpar = $dpar . " $d2";
					} until ($d2 eq ">>");
				};
			}
		};
		$fil .= "$dpar $f filter ";
		# determine data characteristics
		$stream_is_compressed = 1 if ($f eq "/LZWDecode");
		$stream_is_compressed = 1 if ($f eq "/DCTDecode");
		$stream_is_compressed = 1 if ($f eq "/CCITTFaxDecode");
		$stream_is_compressed = 1 if ($f eq "/RunLengthDecode");
		$stream_is_binary = 0 if ($f eq "/ASCII85Decode");
		$stream_is_binary = 0 if ($f eq "/ASCIIHexDecode");
	}
	return $fil;
};

sub gen_stream
{
	local ($ref) = @_;
	local (%stream, $dec, $len);
	
	&pos_ref ($ref);
	%stream = &load_dir;
			# resolve indirect values if needed:
	$stream{"Length"} = &get_val($stream{"Length"}) if $stream{"Length"};
	#$stream{"Length1"} = &get_val($stream{"Length1"}) if $stream{"Length1"};
	#$stream{"Length2"} = &get_val($stream{"Length2"}) if $stream{"Length2"};
	#$stream{"Length3"} = &get_val($stream{"Length3"}) if $stream{"Length3"};
	
	print PS "% stream ref $ref\n";
	$dec = &gen_filterChain ($stream{"Filter"}, $stream{"DecodeParms"});
	if ($stream_is_binary && $avoidBinary) {
		$streamOutMode = $defaultAsciiMode;
		$dec = "$defaultAsciiFilter filter $dec";
	}
	print PS " currentfile $dec cvx exec\n" unless ($dec =~ m/^\s*$/);
	$len = $stream{"Length"};
	# print STDERR "CALL(4): copy_stream_len ($len, PS)\n";
	&copy_stream_len ($len, PS);
	print PS "\n\n%% END stream ref $ref\n";
};

# test if a given font exists on this machine (NEXTSTEP only !!!)
sub font_exists_here
{
	local ($fname) = @_;
	local ($n);
	
	if (-f ($n = "$ENV{'HOME'}/Library/Fonts/$fname.font/$fname") ||
	    -f ($n = "/LocalLibrary/Fonts/$fname.font/$fname") ||
	    -f ($n = "/NextLibrary/Fonts/$fname.font/$fname")) {
		print PS "% $fname exists locally\n";
		return $n;
	};
	return 0;
};

sub loadType3font
{
	local ($bfont, $fref) = @_;
	local (%fdir, $bbox, $fmatrix, $first, $last, $size);
	local ($cpref, %cpdir, %cstream, $glyph, $len, $fil);
	
	return if $loaded{$bfont};
	$loaded{$bfont} = 1;
	
	&pos_ref ($fref);
	%fdir = &load_dir;
	$bbox = $fdir{'FontBBox'};
	$fmatrix = $fdir{'FontMatrix'};
	$cpref = $fdir{'CharProcs'};
	$first = $fdir{'FirstChar'};
	$last = $fdir{'LastChar'};

	&pos_ref ($cpref);
	%cpdir = &load_dir;

	print PS "% make Type3 font $bfont:\n";
	$size = $last - $first + 1 + 1;		# second +1 for /.notdef
	print PS " $bbox $fmatrix $size beginSetupType3font\n";
	print PS " CharProcs begin\n";
	local ($op, $target);
	foreach $glyph (keys(%cpdir)) {
		&pos_ref ($cpdir{$glyph});
		%cstream = &load_dir;
		$fil = &gen_filterChain ($cstream{"Filter"}, $cstream{"DecodeParms"});
		$len = $cstream{"Length"};
		if ($len > 65500) {
			warn "Type3 character description too large (> 64KB), ignored";
			print PS "% /$glyph: description to large (>64KB), make dummy\n";
			print PS " FilProcs /$glyph {} put\n";
			print PS " /$glyph () def\n"; # should at least move by it's width
			# MISSING_CODE: move right by width of character
			next;
		}
		else {
			$op = "copy_to_string";
			$target = "/$glyph";
		}
		print PS " FilProcs /$glyph {$fil} put\n";
		if ($stream_is_binary && $avoidBinary) {
			$streamOutMode = $defaultAsciiMode;
			$op .= $defaultAsciiProcSuffix;
		}
		print PS " $target $len $op\n";
		&copy_stream_len ($len, PS);
	};

	print PS " end $bfont endSetupType3font\n";
};

sub font_prolog
{
	local($fname, $fref) = @_;
	local(%font, %encoding, $ftype, $enc, $basefont, $diffname, $nam);
	local($style, $fdesc);
	
	return if $loaded{$fname};
	$loaded{$fname} = 1;	# auch bei fehler nicht noch mal laden
	
	&pos_ref ($fref);
	%font = &load_dir;
	# &dump_dir (%font);
	$ftype = $font{"Subtype"};
	$nam = $font{"Name"};
	$basefont = $font{'BaseFont'};
	# print "FNT: $fname, $basefont, $ftype\n";
	if (($ftype eq "/Type1") || ($ftype eq "/MMType1")) {
	  if ($basefont =~ m/_/) {
		local ($mmname) = $basefont;
		local ($mmbase, $ff);
		
		$mmname =~ s:^/::;
		$mmname =~ s/,.*$//;
		$mmname =~ s/^[A-Z]{6}\+//;
		$mmbase = $mmname;
		$mmbase =~ s/_[0-9A-Za-z_]+$//;
		# print "$fname is a $ftype font ($mmname / $mmbase)";
		if (($ff = &font_exists_here ($mmbase)) && (! $loaded{$mmbase})) {
			print PS "%  $mmbase included for $fname\n";
			# Font must be in prolog for e.g. MyriadMM_650_300_ names to work
			print PS "%%BeginResource: font $mmbase\n";
			open (MM, "<$ff");
			while (<MM>) {
				print PS;
			};
			close (MM);
			print PS "\n%%EndResource\n";
			$loaded{$mmbase} = 1;
		}
		print PS "%  $mmname: will just be generated from $mmbase\n";
	  }
	}
	elsif ($ftype eq "/TrueType") {
		$basefont = "TrueType_$fname" unless $basefont;
		warn "$fname: Can't deal with $ftype fonts yet (faked !!! ???)\n";
		print PS " /$fname [] /Times-Roman mk_diff_font  % faked !!!???\n";
		return;
	}
	elsif ($ftype eq "/Type3") {
		$basefont = "/Type3_$fname" unless $basefont;
		if ($noType3) {
		print PS " $basefont [] /Times-Roman mk_diff_font  % faked upon request\n";
		}
		else {
			&loadType3font ($basefont, $fref);
		}
	}
	else {
		$basefont = "Unknown_$fname" unless $basefont;
		print PS "%  $fname: Unknown font type $ftype\n";
		print PS "/$fname [] /Times-Roman mk_diff_font %% (faked!)\n";
		warn "$fname: Can't deal with $ftype fonts (faked!)\n";
		# $prolog_error = 1;
		return;
	}

	$style = '';
	($basefont, $style) = split(/,/, $basefont, 2) if ($basefont =~ /.*,.*/);
	$DocFonts{$basefont}++; # Liste aller verwendeten (base-) fonts

	if ( (! $FontBase{$basefont}) && ($ftype ne "/Type3") ) {
			# should include font here !!!! ???
		$fdesc = $font{"FontDescriptor"};
		if (! $fdesc) {
			print "ERROR: FontDescriptor missing for $fname\n";
			print PS "% FontDescriptor missing for $fname\n";
			$prolog_error = 1;
		};
		print PS "%  load font $basefont for $fname here:\n";
		&load_font_desc($fdesc) unless ($ftype eq "/MMType1");
		$FontBase{$basefont} = 100;		# mark as "loaded", nonstandard
	};

	print PS "% load font $fname here (ref $fref, BaseFont = $basefont):\n";
	if (! ($enc = $font{"Encoding"})) {	# if no /Encoding entry
			# take original font encoding, no differences
		print PS "/$fname [] $basefont mk_diff_font\n";
		return;
	};
	if ($enc =~ m:/\w+Encoding:) {
		$enc =~ s/\W*(\w+)\W*/$1/;
		if (   ($enc ne "MacRomanEncoding")
			&& ($enc ne "MacExpertEncoding")
			&& ($enc ne "WinAnsiEncoding")) {
			die "Unknown font encoding $enc\n ";
		};
		if (   ($enc ne "MacRomanEncoding")
			&& ($enc ne "WinAnsiEncoding")) {
			print "WARNING: $enc not yet supported - ";
			$enc = "StandardEncoding";
			print "will use $enc\n";
		};
		# mit vordefinierten Encoding Vektoren
		print PS "/$fname $enc $basefont mk_enc_font\n";
		return;
	};
	# ????????? BaseEncoding , MacRomanEncoding etc. noch behandeln !!!
	if ($enc =~ /(\d+)\s+(\d+)\s+R/) {
		$diffname = "EncObj_$1_$2_Diff";
		if ( ! $loaded{$diffname} ) {
			print PS "% encoding from object $enc\n";
			&pos_ref ($enc);
			%encoding = &load_dir;
			$enc = $encoding{"Differences"};
			print PS "/$diffname $enc def\n";
			$loaded{$diffname} = 1;
			# &dump_dir (%encoding);
		};
	}
	else {
		$diffname = $fname . "_Diffs";
		# ??? hier noch mehrfach def's von /Diffs vermeiden
		print PS "/$diffname $enc def\n";
	}
	print PS "/$fname $diffname $basefont mk_diff_font\n";
};

sub load_font_desc
{
	local($fd) = @_;
	local(%fddir, $ffile, $fname);
	
	&pos_ref ($fd);
	%fddir = &load_dir;
	die "Error in FontDescriptor\n" if ($fddir{"Type"} ne "/FontDescriptor");
	$ffile = $fddir{"FontFile"};
	$fname = $fddir{"FontName"};
	$fname =~ s:^/::;
	if ($ffile) {	# embedded Type1 Font
		print PS "%%BeginResource: font $fname\n";
		&gen_stream ($ffile);
		print PS "\n%%EndResource\n";
	}
	elsif (! &font_exists_here ($fname)) {
		print PS "% Can't yet replace font $fname\n";
		print PS "/$fname [] /Times-Roman mk_diff_font % (faked!)\n";
		print "% Can't yet replace font $fname (use Times-Roman instead)\n";
	}
	else {
		print PS "%% $fname is an existing font - wait and see\n";
	};
};

sub get_val
{
	local($val) = @_;
	if ($val =~ /^\s*(\d+)\s+(\d+)\s+R\s*$/) {
		local($tmppos) = tell (PDF);
		&pos_ref ($val);
		$val = &token;
		seek (PDF, $tmppos, 0);
	}
	return $val;
}

sub get_ref_array
{
	local($ref) = @_;
	local($val, $tok, $array_nest, $tmppos);
	
	if ($ref =~ /^\s*(\d+)\s+(\d+)\s+R\s*$/) {
		$tmppos = tell (PDF);
		&pos_ref ($ref);
		$tok = &token;
		if ($tok ne "[") {
			die "get_ref_array: array expected, found '$tok' !!";
		};
		if ($tok eq "[") {
			$array_nest = 1;	# first '[' already scanned
			$val = $tok;
			do {
				$tok = &token;
				$val .= " ".$tok;
				$array_nest++ if ($tok eq "[");
				$array_nest-- if ($tok eq "]");
			} until (($array_nest == 0) && ($tok eq "]"));
		}
		seek (PDF, $tmppos, 0);
	}
	else {
		die "get_ref_array: '$ref' must be a reference !!";
	};
	return $val;
}

sub enc85
{
	local ($val) = @_;
	local ($tmp, $b1, $b2, $b3, $b4, $b5);
	use integer;
	
	# print "TRACE: enc85: val=$val\n";
	return "z" if ($val == 0);
	
    if ($val < 0) {	# Because some don't support unsigned long 
      $tmp = 32;
      $val = $val - (85 * 85 * 85 * 85 * 32);
    }
    if ($val < 0) {
      $tmp = 64;
      $val = $val - (85 * 85 * 85 * 85 * 32);
    }
    $b1 = (($val / (85 * 85 * 85 * 85)) + $tmp) + 33;
    $val %= (85 * 85 * 85 * 85);
    $b2 = ($val / (85 * 85 * 85)) + 33;
    $val %= (85 * 85 * 85);
    $b3 = ($val / (85 * 85)) + 33;
    $val %= (85 * 85);
    $b4 = ($val / 85) + 33;
    $val %= 85;
    $b5 = ($val) + 33;
	return pack ("C5", $b1, $b2, $b3, $b4, $b5);
}

# $blen MUST be a multiple of 4 exept for the last chunk
sub encodeASCII85
{
	local ($blen, $buf, $last, $OUTFILE) = @_;
	local ($i, $v, $off);
	
	$off = 0;
	while ($blen >= 4) {
		$v = unpack ("L", substr ($buf, $off, 4));
		$off += 4;
		$blen -= 4;
		$i = &enc85 ($v);
		$pos85 += length ($i);
		print $OUTFILE $i;
		if ($pos85 > 72) {
			print $OUTFILE "\n";
			$pos85 = 0;
		}
	}
	if ($blen && (! $last)) {
		warn "internal: ascii base-85 encoding called inconsistently";
	}
	if ($blen) {
		$v = 0;
		$i = 0;
		while ($i < $blen) {
			$v = $v * 256 + unpack ("C", substr ($buf, $off, 1));
			$off++;
			$i++;
		}
		while ($i < 4) {
			$v = $v * 256;
			$i++;
		}
		print $OUTFILE substr (&enc85 ($v), 0, $blen + 1);
		$pos85 += $blen + 1;
	}
	if ($last) {
		print $OUTFILE "~>";
		$pos85 = 0;
	}
}

sub copyAndEnc85
{
	local ($encLen, $INFILE, $OUTFILE) = @_;
	local ($val, $i, $outstr);
	use integer;
		
	# print "TRACE: copyAndEnc85: encLen=$encLen\n";
	$outstr = "";
	$val = 0;
	while ($encLen >= 4) {
		$val = ord (getc $INFILE);
		$val = ($val * 256) + ord (getc $INFILE);
		$val = ($val * 256) + ord (getc $INFILE);
		$val = ($val * 256) + ord (getc $INFILE);
		$encLen -= 4;
		$outstr .= &enc85 ($val);
		if (length ($outstr) > 66) {
			print $OUTFILE "$outstr\n";
			$outstr = "";
		}
	}
	if ($encLen) {
		$val = 0;
		$i = 0;
		while ($i < $encLen) {
			$val = $val * 256 + ord (getc $INFILE);
			$i++;
		}
		while ($i < 4) {
			$val = $val * 256;
			$i++;
		}
		$outstr .= substr (&enc85 ($val), 0, $encLen + 1);
	}
	print $OUTFILE "$outstr~>";
}

sub encodeHex
{
	local ($blen, $buf, $last, $OUTFILE) = @_;
	$blen *= 2;
	printf $OUTFILE "%s%s\n", unpack ("H$blen", $buf), ($last) ? ">" : "";
}

sub copy_stream_len
{	# copy stream from PDF current position to $OUTFILE
	local ($cpSlen, $OUTFILE) = @_;
	local ($l, $n, $buf, $chunksize);
	
	$l = $cpSlen;
	$cpSlen = &get_val ($cpSlen); # might be a reference, won't harm otherwise
	# print "TRACE: copy_stream_len: len=$cpSlen (oldl=$l)\n";
	
	while (<PDF>) {
		last if (/^stream/);
	};
	$n = tell(PDF);
	seek (PDF, $n - 6, 0);
	while (1) {
		$c = getc(PDF);
		last if ($c eq "m");	# "streaM"
	}
	$c = getc (PDF); # get LF (or CR) char behind word "stream"
	$n = tell(PDF);
	$c = getc (PDF) if ($c eq "\015"); # get LF if previous was CR
	if ($c ne "\012") {
		warn "Illegal chars after 'stream': (CR) not followed by LF (PDF pos $n)\n"
			unless ($pdf_version == 1000);
		seek (PDF, $n, 0);
	}
	
	$chunksize = 1024;	# for direct copy
	$chunksize = 38 if ($streamOutMode == 1);	# HexEncoded
	# $chunksize = 56 if ($streamOutMode == 2);	# ASCII85Encoded ???
	if ($streamOutMode == 2) {
		if (1) {
			&copyAndEnc85 ($cpSlen, PDF, $OUTFILE);
		}
		else {	local ($tnam) = "/tmp/_e85_$$";
			open (E85, "|encode85>$tnam") || die "PIPE setup";
			while ($cpSlen > 0) {
				$l = $chunksize;
				$l = $cpSlen if ($cpSlen < $chunksize);
				$n = read (PDF, $buf, $l);
				warn "stream read: wanted $l bytes, got only $n" if ($n != $l);
				print E85 $buf;
				$cpSlen -= $n;
			};
			close E85;
			open (I85, "<$tnam");
			while ($n = read (I85, $buf, 1024)) {
				print $OUTFILE $buf;
			}
			close I85;
			print $OUTFILE "~>";
			unlink $tnam;
		}
	}
	else {
	while ($cpSlen > 0) {
		$l = $chunksize;
		$l = $cpSlen if ($cpSlen < $chunksize);
		$n = read (PDF, $buf, $l);
		warn "stream read: wanted $l bytes, got only $n" if ($n != $l);
		if ($streamOutMode == 0) {
			print $OUTFILE "$buf";
		} elsif ($streamOutMode == 1) {
			&encodeHex ($n, $buf, ($n == $cpSlen), $OUTFILE);
		} elsif ($streamOutMode == 2) {
			&encodeASCII85 ($n, $buf, ($n == $cpSlen), $OUTFILE);
		} else {
			warn "internal: illegal streamOutMode ($streamOutMode)\n";
			print $OUTFILE "$buf";
		}
		$cpSlen -= $n;
	};
	}
	$_ = <PDF>;
	$_ = <PDF> if (/^[\012\015]*$/);
	unless (m:^endstream:){ local ($p); $p = tell (PDF);
		warn "stream read: 'endstream' not found (p=$p)" ;
		open (ERR, ">>/tmp/PDF_ERR");
		print ERR "stream read (p=$p): 'endstream' not found in '$_'\n";
	};
	$streamOutMode = 0;
	# while (<PDF>) {
	# 	last if (/^endstream/);
	# 	print $OUTFILE $_;
	# };
};

sub cs_prolog
{
	local($csname, $csref) = @_;
	local(%csdir);
	
	return if $loaded{$csname};
	#$loaded{$csname} = 1;	# auch bei fehler nicht noch mal laden
	
	### ??? not yet finished !!!!
	
	#&pos_ref ($csref);
	#%csdir = &load_dir;
	# &dump_dir (%csdir);
};

sub do_xobj_form
{
	local ($xname, %xdir) = @_;
	local ($ftype, $BBox, $filter, $dp, $matrix);
	
	$ftype = $xdir{"FormType"};
	if ($ftype != 1) {
		print PS "% $xname: Can't deal with $ftype FormType (faked)\n";
		print PS "/$xname { } def\n";
		warn "$xname: Can't deal with $ftype FormType (faked)\n";
		return;
	}
	$len = $xdir{"Length"};
	$len = &get_val($len);
	$BBox = $xdir{"BBox"};
	$matrix = $xdir{"Matrix"};

	print PS "% load XObject $xname here:\n";
	print PS "/$xname { 5 dict\nbegin\n";
	if ($len > 65500) {
		print PS " /.pa_cnt 0 def\n";
		print PS " /_pdf_xobject_$xname {\n";
		print PS "  _pdf_xobjectArray_$xname .pa_cnt get\n";
		print PS "  /.pa_cnt .pa_cnt 1 add def\n";
		print PS " } def\n";
	}
	print PS " << /FormType 1 /BBox $BBox\n   ";
	print PS "/Matrix $matrix\n";

	$dp = $xdir{"DecodeParms"};
	print PS "% DecodeParms = $dp\n" if ($dp);
	$filter = &gen_filterChain ($xdir{"Filter"}, $dp);
	print PS "   /PaintProc { pop _pdf_xobject_$xname \n";
	print PS "    $filter cvx exec }\n"; 

	print PS " >> execform\nend } def\n";

	print PS "% store /$xname data:\n";
	local ($op, $target);
	if ($len > 65500) {
		$op = "copy_to_procarray";
		$target = "/_pdf_xobjectArray_$xname";
	}
	else {
		$op = "copy_to_string";
		$target = "/_pdf_xobject_$xname";
	}
	if ($stream_is_binary && $avoidBinary) {
		$streamOutMode = $defaultAsciiMode;
		$op .= $defaultAsciiProcSuffix;
	}
	print PS " $target $len $op\n";
	
	&copy_stream_len ($len, PS);
	print PS "\n%%_pdf_End_of_Data\n";
}

sub xobj_prolog
{
	local($xname, $xref) = @_;
	local(%xdir, $xtype, $nam, $w, $h, $bpc, $cs, $hcs, $filter, $tmppos);
	local($len, $imask, $dp);
	
	return if $loaded{$xname};
	$loaded{$xname} = 1;	# auch bei fehler nicht noch mal laden
	
	&pos_ref ($xref);
	%xdir = &load_dir;
	# &dump_dir (%xdir);
	$xtype = $xdir{"Subtype"};
	$nam = $xdir{"Name"};
	if ($xtype ne "/Image") {
		# $prolog_error = 1;
		if ($xtype eq "/Form") {
			&do_xobj_form ($xname, %xdir);
			return;
		};
		print PS "% $xname: Can't deal with $xtype XObjects yet (faked)\n";
		print PS "/$xname { } def\n";
		warn "$xname: Can't deal with $xtype XObjects yet (faked)\n";
		return;
	};
	$w = $xdir{"Width"};
	$h = $xdir{"Height"};
	$bpc = $xdir{"BitsPerComponent"};
	$imask = ($xdir{"ImageMask"} eq "true");
	$len = $xdir{"Length"};
	$len = &get_val($len);
	$cs = $xdir{"ColorSpace"};
	$dec = $xdir{"Decode"};
	$hcs = $cs;
	$hcs = &get_val($cs) if ($cs =~ /^\d+\s+\d+\s+R$/);
	if ($hcs eq "[") {
		$hcs = &get_ref_array($cs) if ($cs =~ /\d+\s+\d+\s+R/);
		$cs = "/Indexed";
		print "/Indexed Image on page $pg\n";
	}
	else {
		$cs = $hcs;
	};
	$dec = $Decode{$cs} unless ($xdir{"Decode"});
	if ($hcs =~
	  m:\[\s*/Indexed\s*(/Device[A-Z]+)\s+(\d+)\s+(\d+\s+\d+\s+R)\s*\]:) {
	  	local ($base, $hival, $lookup, $lnam);
		  	$base = $1;
			$hival = $2;
			$lookup = $3;
			$lnam = $lookup;
			$lnam =~ s: R::;
			$lnam =~ s: :_:g;
			$lnam = "inx_lookup_obj_$lnam";
			&load_print_index_lookup($lookup, $lnam, PS)
				unless $loaded{$lnam};
			$loaded{$lnam} = 1;
			$hcs = "[/Indexed$base $hival $lnam]";
			$dec = "[0 $hival]" unless ($xdir{"Decode"});
	};
	
	print PS "% load XObject $xname here:\n";
	print PS "/$xname { 5 dict\nbegin\n";
	if ($len > 65500) {
		print PS " /.pa_cnt 0 def\n";
		print PS " /_pdf_xobject_$xname {\n";
		print PS "  _pdf_xobjectArray_$xname .pa_cnt get\n";
		print PS "  /.pa_cnt .pa_cnt 1 add def\n";
		print PS " } def\n";
	}
	print PS " $hcs setcolorspace\n" unless $imask;
	# print PS " gsave [$w 0 0 -$h 0 $h] concat mk_cross grestore\n";
	print PS " gsave mk_cross grestore\n" unless ($imask); # shines through
	print PS " << /ImageType 1 /Width $w /Height $h\n   ";
	print PS "/ImageMatrix [$w 0 0 -$h 0 $h]\n";

	$dp = $xdir{"DecodeParms"};
	print PS "% DecodeParms = $dp\n" if ($dp);
	$filter = &gen_filterChain ($xdir{"Filter"}, $dp);
	print PS "   /DataSource { _pdf_xobject_$xname }\n";
	print PS "    $filter\n"; 

	print PS "   /BitsPerComponent $bpc";
	print PS " /Decode $dec" if $dec;
	if ($imask)
		{ print PS " /Decode [0 1] " unless $dec;
		  print PS " >> imagemask\nend } def\n";
		}
	else
		{ print PS " >> image\nend } def\n";}
	if (0 && ($xdir{"Filter"} =~ m:/CCITTFaxDecode:)) {
	# bug in NeXT DiplayPostScript interpreter up to NEXTSTEP version 3.2
	# fixed since NEXTSTEP 3.3 (delete the "0 &&" above if you run <= 3.2)
		print PS "% image $xname omitted due to bug in PS CCITTFaxDecode\n";
		print "% image $xname omitted due to bug in PS CCITTFaxDecode\n";
		print PS "/$xname { gsave mk_cross /Helvetica findfont 0.05 scalefont
			setfont 0.2 0.4 moveto ($xname) show grestore } def
			% override def to avoid any harm\n";
	}
	print PS "% store /$xname data:\n";
	local ($op, $target);
	if ($len > 65500) {
		$op = "copy_to_procarray";
		$target = "/_pdf_xobjectArray_$xname";
	}
	else {
		$op = "copy_to_string";
		$target = "/_pdf_xobject_$xname";
	}
	if ($stream_is_binary && $avoidBinary) {
		$streamOutMode = $defaultAsciiMode;
		$op .= $defaultAsciiProcSuffix;
	}
	print PS " $target $len $op\n";
	
	# print STDERR "CALL(1): copy_stream_len ($len, PS)\n";
	&copy_stream_len ($len, PS);
	print PS "\n%%_pdf_End_of_Data\n";
};

sub scan_outlines
{
	local ($ort) = @_;
	local (%odir, $l, $f);
	
	return unless $ort;
	%odir = &load_dir_by_ref ($ort);
	$l = $odir{"Last"};
	$f = $odir{"First"};
	return unless $f;
	&scan_one_level ($f, $l, ":= ");
}

sub scan_one_level
{
	local	($el, $end, $pref) = @_;
	local	(%edir, $i);
	
	# print "$pref--- Start (sub-)list\n";
	$i = 0;
	while (1) {
		$i++;
		%edir = &load_dir_by_ref ($el);
		print "$pref $i. $edir{'Title'}   ==> $edir{'Dest'}\n";
		if ($edir{"Count"}) {
			&scan_one_level ($edir{"First"}, $edir{"Last"}, "$pref  "); 
		};
		last if ($el eq $end);
		$el = $edir{"Next"};
	}
	# print "$pref--- End list ($i entries)\n";
	return;
}

sub init
{		# Base-14 fonts (always defined in PDF)
	$FontBase{"/Courier"} = 14;
	$FontBase{"/Courier-Bold"} = 14;
	$FontBase{"/Courier-Oblique"} = 14;
	$FontBase{"/Courier-BoldOblique"} = 14;
	$FontBase{"/Helvetica"} = 14;
	$FontBase{"/Helvetica-Bold"} = 14;
	$FontBase{"/Helvetica-Oblique"} = 14;
	$FontBase{"/Helvetica-BoldOblique"} = 14;
	$FontBase{"/Times-Roman"} = 14;
	$FontBase{"/Times-Bold"} = 14;
	$FontBase{"/Times-Italic"} = 14;
	$FontBase{"/Times-BoldItalic"} = 14;
	$FontBase{"/Symbol"} = 14;
	$FontBase{"/ZapfDibgbats"} = 14;
		# Base-35 fonts (found in most PostScript printers)
	$FontBase{"/AvantGarde-Book"} = 35;
	$FontBase{"/AvantGarde-BookOblique"} = 35;
	$FontBase{"/AvantGarde-Demi"} = 35;
	$FontBase{"/AvantGarde-DemiOblique"} = 35;
	$FontBase{"/Bookman-Demi"} = 35;
	$FontBase{"/Bookman-DemiItalic"} = 35;
	$FontBase{"/Bookman-Light"} = 35;
	$FontBase{"/Bookman-LightItalic"} = 35;
	$FontBase{"/Helvetica-Narrow"} = 35;
	$FontBase{"/Helvetica-Narrow-Bold"} = 35;
	$FontBase{"/Helvetica-Narrow-Oblique"} = 35;
	$FontBase{"/Helvetica-Narrow-BoldOblique"} = 35;
	$FontBase{"/NewCenturySchlbk-Bold"} = 35;
	$FontBase{"/NewCenturySchlbk-BoldItalic"} = 35;
	$FontBase{"/NewCenturySchlbk-Italic"} = 35;
	$FontBase{"/NewCenturySchlbk-Roman"} = 35;
	$FontBase{"/Palatino-Bold"} = 35;
	$FontBase{"/Palatino-BoldItalic"} = 35;
	$FontBase{"/Palatino-Italic"} = 35;
	$FontBase{"/Palatino-Roman"} = 35;
	$FontBase{"/ZapfDingbats"} = 35;
	
	$Decode{"/DeviceGray"} = "[0 1]";
	$Decode{"/DeviceRGB"} = "[0 1 0 1 0 1]";
	$Decode{"/DeviceCMYK"} = "[0 1 0 1 0 1 0 1]";
	$Decode{"/CIEBasedABC"} = "[0 1 0 1 0 1]";
	$Decode{"/CIEBasedA"} = "[0 1]";
	$Decode{"/Seperation"} = "[0 1]";
	$Decode{"/Indexed"} = "[0 255]";	# Dummy, 255 not ok !!! ???
};
	######### Main Program ############

	print  "Analyzing PDF file '$pdffile'\n";

# load cross refrence table

	&init;
	&find_startxref;
	die "PDF file structure corrupt - can't continue.\n" unless $startxref;

	open (LOG, ">$basename.log") if $logging;

	printf "Xref starts at %d\n", $startxref if $verbose;
	$pos = $startxref;
	while (1) {
		&load_xref ($pos);
		if (1) {
			(/^trailer/) || die "Trailer keyword not recognized\n";
			$tbuf = <PDF>;
		}
		else {
			(&token eq "trailer") || die "Trailer keyword not recognized\n";
			# $tbuf = <PDF>;
		}
		%tmp = &load_dir;
		%document = %tmp unless $document{"Root"}; # preserve "latest" trailer
		$pos = $tmp{"Prev"};
		last unless $pos;
	};

	printf "Root is '%s', Info is '%s'\n",
		$document{"Root"}, $document{"Info"} if $verbose;
	&dump_dir (%document) if $verbose;
	
	if ($document{"Encrypt"}) {
		unlink ("$basename.ps");
		die "\nThis document is encrypted. The en/decryption algorithm is
not documented by Adobe, so I can't convert it - sorry\n\n"
	}
# get catalog object
	print LOG "== get catalog object\n" if $logging;
	&pos_ref ($document{"Root"});
	%catalog = &load_dir;
	if ($verbose) {
		print "Catalog:\n";
		&dump_dir (%catalog);
	};
	# print "Outlines ignored\n" if $catalog{"Outlines"};
	&scan_outlines ($catalog{"Outlines"}) if $verbose;

# get list of page objects

	print LOG "== get list of page objects\n" if $logging;
	$page_cnt = 0;
	&load_pages ($catalog{"Pages"});
	
# write header

	open (PS, ">$basename.ps");
	print "Output File: $basename.ps\n";
	
	print PS "%!PS-Adobe-2.0\n";
	print PS "%%Title: $pdffile\n";
	$Date = &ctime(time);
	$tmp = $0;
	$tmp =~ s:.*/::;	# strip leading path if present
	print PS "%%CreationDate: $Date";
	print PS "%%Creator: $tmp (Version $Version [Rev $Rev], (C) 1993-1995 by D. Droege)\n";
	print PS "%%BoundingBox: 0 0 612 842\n";
	print PS "%%Pages: $page_cnt 1\n";
	print PS "%%For: $ENV{'USER'}@$ENV{'HOST'}\n";
	print PS "%%DocumentNeededResources: (atend)\n";
	print PS "%%DocumentSuppliedResources: (atend)\n";# ??? avoid if not needed
	print PS "%%LanguageLevel: 2\n";	# needed for 'filter' etc.
	print PS "%%EndComments\n";
	
	print PS "\n%%BeginProlog\n\n";
	print PS "systemdict /languagelevel known\n";
	print PS " {languagelevel 2 ge}{false}ifelse not\n";
	print PS " {(== Must run on PostScript Level 2 device ==)== stop} if\n\n";
	print PS "\n%%BeginResource: procset PDF_ProcSet\n 1 setobjectformat\n";
	&put_proc_set;
	print PS " /copy_to_string_Hex { % /strname length copy_to_string_Hex
        string currentfile /ASCIIHexDecode filter exch readstring pop def
  } bd\n";
	print PS " /copy_to_string_A85 { % /strname length copy_to_string_A85
        string currentfile /ASCII85Decode filter exch readstring pop def
  } bd\n";
	print PS " /copy_to_procarray_fil { % /paname length file copy_to_procarray
        /.xfile exch def
        /.xlen exch def
        /.xnamA exch def
        [
         {
          .xlen 0 le { exit } if
          .xlen 4096 le { .xlen } { 4096 } ifelse
          dup .xlen exch sub /.xlen exch def
          string .xfile exch readstring pop
         } loop
         ()     % empty string as EOD to signal end of data
        ] .xnamA exch def
  } bd\n";
	print PS " /copy_to_procarray_Hex { % /paname length copy_to_procarray_Hex
        currentfile /ASCIIHexDecode filter copy_to_procarray_fil
  } bd\n";
	print PS " /copy_to_procarray_A85 { % /paname length copy_to_procarray_A85
        currentfile /ASCII85Decode filter copy_to_procarray_fil
  } bd\n";

	print PS "\n%%EndResource\n\n";
	
	print LOG "== collect needed resources/writing prolog\n" if $logging;
	print "Writing out $page_cnt page resources ...\n";
	for ($pg = 1; $pg <= $page_cnt; $pg++) {
		&gen_page_resource ($pg);
		# print STDERR "$pg " if (($pg % 10) == 0);
	};
	print " generated $XObjects XObjects\n" if $XObjects;
	print " $cnt_annots Annotations ignored\n" if ($verbose && $cnt_annots);
	print PS "\n%%EndProlog\n";
	if ((! $NoThumbs) && $setup_thumb_done) {
		print THUMB "showpage\n%%Trailer\n%%Pages: $thumb_pg 1\n";
		close THUMB;
	};
	# print STDERR "\n";
	
	die "Error while generating PostScript Prolog\n" if $prolog_error;
	
	print LOG "== generate pages\n" if $logging;
	for ($pg = 1; $pg <= $page_cnt; $pg++) {
		print STDERR "[$pg";
		print PS "\n%%Page: $pg $pg\n";
		&gen_page_output ($pg);
		print STDERR "] ";
		print STDERR "\n" if (($pg % 10) == 0);
	};
	print STDERR "\n" if (! ((($pg - 1) % 10) == 0));
	# print PS "usertime startTime sub 1000 div 20 string cvs ==\n";
	print PS "%%Trailer\n";
		# ??? veraltet, umstellen auf ...SuppliedResurces ...
	$first = 1;
	foreach $fnt (sort keys(%DocFonts)) {
		next if ($FontBase{$fnt} > 35);
		$fnt =~ s:^/::;
		if ($first == 1) {
			print PS "%%DocumentNeededResources: font $fnt\n";
			$first = 0;
		}
		else {
			print PS "%%+ font $fnt\n";
		};
	};
	foreach $fnt (sort keys(%DocFonts)) {
		next if ($FontBase{$fnt} > 35);
		$fnt =~ s:^/::;
		print PS "%%IncludeResource: font $fnt\n";
	};
	print PS "%%DocumentSuppliedResources: procset PDF_ProcSet\n";
	foreach $fnt (sort keys(%DocFonts)) {
		next if ($FontBase{$fnt} <= 35);
		$fnt =~ s:^/::;
		print PS "%%+ font $fnt\n";
	};
	print PS "%%EOF\n";

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.