📄 genps.pl
字号:
++$curcolumn < $psconf{idxcolumns} ) { # We're actually breaking text into columns, not pages $curypos = $columnstart; } else { undef $columnstart; $curpage++; $curypos = 0; } next; } # Add end of paragraph skip if ( $$linfo[1] & 2 ) { $curypos += $skiparray{$$linfo[0]}; } }}ps_break_pages(0,$nlines); # Break the main text body into pages## Find the page number of all the indices#%ps_xref_page = (); # Crossref anchor pages%ps_index_pages = (); # Index item pages$nlines = scalar(@pslines);for ( $i = 0 ; $i < $nlines ; $i++ ) { my $linfo = $pslines[$i]->[0]; foreach my $c ( @{$pslines[$i]->[1]} ) { if ( $$c[0] == -4 ) { if ( !defined($ps_index_pages{$$c[1]}) ) { $ps_index_pages{$$c[1]} = []; } elsif ( $ps_index_pages{$$c[1]}->[-1] eq $$linfo[4] ) { # Pages are emitted in order; if this is a duplicated # entry it will be the last one next; # Duplicate } push(@{$ps_index_pages{$$c[1]}}, $$linfo[4]); } elsif ( $$c[0] == -5 ) { $ps_xref_page{$$c[1]} = $$linfo[4]; } }}## Emit index paragraphs#$startofindex = scalar(@pslines);@ixparas = ([[-5,'index'],[0,'Index']]);@ixptypes = ('chap');foreach $k ( @ixentries ) { my $n,$i; my $ixptype = 'idx0'; my $prefix = $ixhasprefix{$k}; my @ixpara = mkparaarray($ixptype,@{$ixterms{$k}}); my $commapos = undef; if ( defined($prefix) && $ixprefixes{$prefix} > 1 ) { # This entry has a "hanging comma" for ( $i = 0 ; $i < scalar(@ixpara)-1 ; $i++ ) { if ( substr($ixpara[$i]->[1],-1,1) eq ',' && $ixpara[$i+1]->[1] eq ' ' ) { $commapos = $i; last; } } } if ( defined($commapos) ) { if ( $ixcommafirst{$k} ) { # This is the first entry; generate the # "hanging comma" entry my @precomma = splice(@ixpara,0,$commapos); if ( $ixpara[0]->[1] eq ',' ) { shift(@ixpara); # Discard lone comma } else { # Discard attached comma $ixpara[0]->[1] =~ s/\,$//; push(@precomma,shift(@ixpara)); } push(@precomma, [-6,undef]); push(@ixparas, [@precomma]); push(@ixptypes, $ixptype); shift(@ixpara); # Remove space } else { splice(@ixpara,0,$commapos+2); } $ixptype = 'idx1'; } push(@ixpara, [-6,undef]); # Left/right marker $i = 1; $n = scalar(@{$ps_index_pages{$k}}); foreach $p ( @{$ps_index_pages{$k}} ) { if ( $i++ == $n ) { push(@ixpara,[-7,$p],[0,"$p"],[-1,undef]); } else { push(@ixpara,[-7,$p],[0,"$p,"],[-1,undef],[0,' ']); } } push(@ixparas, [@ixpara]); push(@ixptypes, $ixptype);}## Flow index paragraphs into lines#ps_break_lines(\@ixparas, \@ixptypes);## Format index into pages#$nlines = scalar(@pslines);ps_break_pages($startofindex, $nlines);## Push index onto bookmark list#push(@bookmarks, ['index', 0, 'Index']);# Get the list of fonts used%ps_all_fonts = ();foreach $fset ( @AllFonts ) { foreach $font ( @{$fset->{fonts}} ) { $ps_all_fonts{$font->[1]->{name}}++; }}# Emit the PostScript DSC headerprint "%!PS-Adobe-3.0\n";print "%%Pages: $curpage\n";print "%%BoundingBox: 0 0 ", $psconf{pagewidth}, ' ', $psconf{pageheight}, "\n";print "%%Creator: (NASM psflow.pl)\n";print "%%DocumentData: Clean7Bit\n";print "%%DocumentFonts: ", join(' ', keys(%ps_all_fonts)), "\n";print "%%DocumentNeededFonts: ", join(' ', keys(%ps_all_fonts)), "\n";print "%%Orientation: Portrait\n";print "%%PageOrder: Ascend\n";print "%%EndComments\n";print "%%BeginProlog\n";# Emit the configurables as PostScript tokensforeach $c ( keys(%psconf) ) { print "/$c ", $psconf{$c}, " def\n";}foreach $c ( keys(%psbool) ) { print "/$c ", ($psbool{$c}?'true':'false'), " def\n";}# Emit custom encoding vector$zstr = '/NASMEncoding [ ';foreach $c ( @NASMEncoding ) { my $z = '/'.(defined($c)?$c:'.notdef ').' '; if ( length($zstr)+length($z) > 72 ) { print $zstr,"\n"; $zstr = ' '; } $zstr .= $z;}print $zstr, "] def\n";# Font recoding routine# newname fontname --print "/nasmenc {\n";print " findfont dup length dict begin\n";print " { 1 index /FID ne {def}{pop pop} ifelse } forall\n";print " /Encoding NASMEncoding def\n";print " currentdict\n";print " end\n";print " definefont pop\n";print "} def\n";# Emit fontset definitionsforeach $font ( keys(%ps_all_fonts) ) { print '/',$font,'-NASM /',$font," nasmenc\n";}foreach $fset ( @AllFonts ) { my $i = 0; my @zfonts = (); foreach $font ( @{$fset->{fonts}} ) { print '/', $fset->{name}, $i, ' ', '/', $font->[1]->{name}, '-NASM findfont ', $font->[0], " scalefont def\n"; push(@zfonts, $fset->{name}.$i); $i++; } print '/', $fset->{name}, ' [', join(' ',@zfonts), "] def\n";}# This is used by the bullet-paragraph PostScript methodsprint "/bullet [",ps_string($charcode{'bullet'}),"] def\n";# Emit the canned PostScript prologueopen(PSHEAD, "< head.ps");while ( defined($line = <PSHEAD>) ) { print $line;}close(PSHEAD);print "%%EndProlog\n";# Generate a PostScript stringsub ps_string($) { my ($s) = @_; my ($i,$c); my ($o) = '('; my ($l) = length($s); for ( $i = 0 ; $i < $l ; $i++ ) { $c = substr($s,$i,1); if ( ord($c) < 32 || ord($c) > 126 ) { $o .= sprintf("\\%03o", ord($c)); } elsif ( $c eq '(' || $c eq ')' || $c eq "\\" ) { $o .= "\\".$c; } else { $o .= $c; } } return $o.')';}# Generate PDF bookmarksprint "%%BeginSetup\n";foreach $b ( @bookmarks ) { print '[/Title ', ps_string($b->[2]), "\n"; print '/Count ', $b->[1], ' ' if ( $b->[1] ); print '/Dest /',$b->[0]," /OUT pdfmark\n";}# Ask the PostScript interpreter for the proper size mediaprint "setpagesize\n";print "%%EndSetup\n";# Start a PostScript pagesub ps_start_page() { $ps_page++; print "%%Page: $ps_page $ps_page\n"; print "%%BeginPageSetup\n"; print "save\n"; print "%%EndPageSetup\n"; print '/', $ps_page, " pa\n";}# End a PostScript pagesub ps_end_page($) { my($pn) = @_; if ( $pn ) { print "($ps_page)", (($ps_page & 1) ? 'pageodd' : 'pageeven'), "\n"; } print "restore showpage\n";}$ps_page = 0;# Title pageps_start_page();$title = $metadata{'title'} || '';$title =~ s/ \- / $charcode{'emdash'} /;$subtitle = $metadata{'subtitle'} || '';$subtitle =~ s/ \- / $charcode{'emdash'} /;# Print titleprint "/ti ", ps_string($title), " def\n";print "/sti ", ps_string($subtitle), " def\n";print "lmarg pageheight 2 mul 3 div moveto\n";print "tfont0 setfont\n";print "/title linkdest ti show\n";print "lmarg pageheight 2 mul 3 div 10 sub moveto\n";print "0 setlinecap 3 setlinewidth\n";print "pagewidth lmarg sub rmarg sub 0 rlineto currentpoint stroke moveto\n";print "hfont1 setfont sti stringwidth pop neg ", -$HeadFont{leading}, " rmoveto\n";print "sti show\n";# Print logo, if there is one# FIX: To be 100% correct, this should look for DocumentNeeded*# and DocumentFonts in the header of the EPSF and add those to the# global header.if ( defined($metadata{epslogo}) && sysopen(EPS, $metadata{epslogo}, O_RDONLY) ) { my @eps = (); my ($bbllx,$bblly,$bburx,$bbury) = (undef,undef,undef,undef); my $line; my $scale = 1; my $maxwidth = $psconf{pagewidth}-$psconf{lmarg}-$psconf{rmarg}; my $maxheight = $psconf{pageheight}/3-40; my $width, $height; my $x, $y; while ( defined($line = <EPS>) ) { last if ( $line =~ /^%%EOF/ ); if ( !defined($bbllx) && $line =~ /^\%\%BoundingBox\:\s*([0-9\.]+)\s+([0-9\.]+)\s+([0-9\.]+)\s+([0-9\.]+)/i ) { $bbllx = $1+0; $bblly = $2+0; $bburx = $3+0; $bbury = $4+0; } push(@eps,$line); } close(EPS); if ( defined($bbllx) ) { $width = $bburx-$bbllx; $height = $bbury-$bblly; if ( $width > $maxwidth ) { $scale = $maxwidth/$width; } if ( $height*$scale > $maxheight ) { $scale = $maxheight/$height; } $x = ($psconf{pagewidth}-$width*$scale)/2; $y = ($psconf{pageheight}-$height*$scale)/2; print "BeginEPSF\n"; print $x, ' ', $y, " translate\n"; print $scale, " dup scale\n" unless ( $scale == 1 ); print -$bbllx, ' ', -$bblly, " translate\n"; print "$bbllx $bblly moveto\n"; print "$bburx $bblly lineto\n"; print "$bburx $bbury lineto\n"; print "$bbllx $bbury lineto\n"; print "$bbllx $bblly lineto clip newpath\n"; print "%%BeginDocument: ",ps_string($metadata{epslogo}),"\n"; print @eps; print "%%EndDocument\n"; print "EndEPSF\n"; }}ps_end_page(0);# Emit the rest of the document (page 2 and on)$curpage = 2;ps_start_page();foreach $line ( @pslines ) { my $linfo = $line->[0]; if ( $$linfo[4] != $curpage ) { ps_end_page($curpage > 2); ps_start_page(); $curpage = $$linfo[4]; } print '['; my $curfont = 0; foreach my $c ( @{$line->[1]} ) { if ( $$c[0] >= 0 ) { if ( $curfont != $$c[0] ) { print ($curfont = $$c[0]); } print ps_string($$c[1]); } elsif ( $$c[0] == -1 ) { print '{el}'; # End link } elsif ( $$c[0] == -2 ) { print '{/',$$c[1],' xl}'; # xref link } elsif ( $$c[0] == -3 ) { print '{',ps_string($$c[1]),'wl}'; # web link } elsif ( $$c[0] == -4 ) { # Index anchor -- ignore } elsif ( $$c[0] == -5 ) { print '{/',$$c[1],' xa}'; #xref anchor } elsif ( $$c[0] == -6 ) { print ']['; # Start a new array $curfont = 0; } elsif ( $$c[0] == -7 ) { print '{/',$$c[1],' pl}'; # page link } else { die "Unknown annotation"; } } print ']'; if ( defined($$linfo[2]) ) { foreach my $x ( @{$$linfo[2]} ) { if ( $$x[0] == $AuxStr ) { print ps_string($$x[1]); } elsif ( $$x[0] == $AuxPage ) { print $ps_xref_page{$$x[1]},' '; } elsif ( $$x[0] == $AuxPageStr ) { print ps_string($ps_xref_page{$$x[1]}); } elsif ( $$x[0] == $AuxXRef ) { print '/',ps_xref($$x[1]),' '; } elsif ( $$x[0] == $AuxNum ) { print $$x[1],' '; } else { die "Unknown auxilliary data type"; } } } print ($psconf{pageheight}-$psconf{topmarg}-$$linfo[5]); print ' ', $$linfo[6] if ( defined($$linfo[6]) ); print ' ', $$linfo[0].$$linfo[1], "\n";}ps_end_page(1);print "%%EOF\n";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -