From c51296e843e35a3d133557000409674baae01b54 Mon Sep 17 00:00:00 2001 From: Reinhard Kotucha Date: Tue, 5 May 2015 21:26:28 +0000 Subject: texlua scripts revised pdfopt.tlu is using -dFastWebView now instead of pdfopt.ps git-svn-id: svn://tug.org/texlive/trunk@37204 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/scripts/tlgs/gswin32/eps2eps.tlu | 116 +- Master/texmf-dist/scripts/tlgs/gswin32/pdf2dsc.tlu | 32 +- Master/texmf-dist/scripts/tlgs/gswin32/pdfopt.tlu | 147 ++- .../texmf-dist/scripts/tlgs/gswin32/ps2ascii.tlu | 140 ++- Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf.tlu | 163 ++- .../texmf-dist/scripts/tlgs/gswin32/ps2pdf12.tlu | 163 ++- .../texmf-dist/scripts/tlgs/gswin32/ps2pdf13.tlu | 163 ++- .../texmf-dist/scripts/tlgs/gswin32/ps2pdf14.tlu | 163 ++- Master/texmf-dist/scripts/tlgs/gswin32/ps2ps.tlu | 117 +- Master/texmf-dist/scripts/tlgs/gswin32/ps2ps2.tlu | 79 -- Master/tlpkg/tlgs/lib/pdfopt.ps | 1272 -------------------- 11 files changed, 860 insertions(+), 1695 deletions(-) delete mode 100755 Master/texmf-dist/scripts/tlgs/gswin32/ps2ps2.tlu delete mode 100644 Master/tlpkg/tlgs/lib/pdfopt.ps (limited to 'Master') diff --git a/Master/texmf-dist/scripts/tlgs/gswin32/eps2eps.tlu b/Master/texmf-dist/scripts/tlgs/gswin32/eps2eps.tlu index 715e7c1ff25..43701447a0d 100755 --- a/Master/texmf-dist/scripts/tlgs/gswin32/eps2eps.tlu +++ b/Master/texmf-dist/scripts/tlgs/gswin32/eps2eps.tlu @@ -2,12 +2,22 @@ --*-Lua-*- -- $Id$ --- Copyright (C) 2008 Reinhard Kotucha. +-- Copyright (C) 2008-2015 Reinhard Kotucha. -- You may freely use, modify and/or distribute this file. -- Replacement for eps2eps.bat. -- 'Distill' Encapsulated PostScript. + +local function usage (progname) + local message= + 'Usage: '..progname..' [options] \n'.. + ' can be either a PS, EPS, PDF file, or stdin.\n'.. + ' A single hyphen (-) denotes stdin.\n' + return message +end + + function fixwin(args_unix) if os.type == 'windows' then local args_win={} -- new table @@ -21,41 +31,103 @@ function fixwin(args_unix) end end -if os.type == 'windows' then - gs='gswin32c' -else - gs='gs' + +local function push (t, ...) + local args={...} + for _,v in ipairs(args) do + if type(v) == 'table' then + for _,x in ipairs(v) do + t[#t+1]=x + end + else + t[#t+1]=v + end + end end -command={gs, '-q', '-sDEVICE=eps2write'} -if os.type=='unix' then - command[#command+1]='-sstdout=%stderr' +local function filename (file) + -- strip path + if string.find(file, '[/\\]') then + return string.match(file, '.*[/\\](.*)$') + else + return file + end end -for _,v in ipairs{'-dNOPAUSE', '-sOutputFile='..arg[#arg], - '-dBATCH', '-dSAFER', '-dDEVICEWIDTH=250000', - '-dDEVICEHEIGHT=250000'} do - command[#command+1]=v +local function basename (file) + -- strip extension + return string.match(filename(file), '(.*)%..*') end -files=0 +local function extension (file) + -- return extension if available, false otherwise. + local fn=filename(file) + if fn:find('%.') then + return string.match(fn, '.*%.(.*)') + else + return false + end +end + + +local function parse_cmdline () + local files={} + local options={} + + local progname + local basename=filename(arg[0]) + if basename:find('%.') then + progname=basename:match('(.*)%..*') + else + progname=basename + end -for i=1, #arg do - if not string.find(arg[i], '^%-') then - files=files+1 + for i=1, #arg do + if string.find(arg[i], '^%-.+') then + push(options, arg[i]) + else + push(files, arg[i]) + end end - command[#command+1]=arg[i] + files.input =files[1] + files.output=files[2] + + return progname, options, files end -if files < 2 then - io.stderr:write('Usage: eps2eps [options] input.eps output.eps\n') - os.exit(1) + +local function check_files (progname, files) + if #files < 2 then + io.stderr:write(usage(progname)) + os.exit(1) + end end -command[#command]=nil -- already processed at -sOutputFile +-- main -- + +-- parse command line +local progname, options, file=parse_cmdline() + +check_files (progname, file) + +-- setup command + +local command={} +if os.type == 'unix' then command={'gs'} else command={'gswin32c'} end + +push(command, '-q', '-sDEVICE=eps2write') + +if os.type=='unix' then push (command, '-sstdout=%stderr') end + +push(command, '-sOutputFile='..file.output, '-dNOPAUSE', + '-dBATCH', '-P-', '-dSAFER', '-dDEVICEWIDTH=250000', + '-dDEVICEHEIGHT=250000') + +push(command, options) +push(command, file.input) command=fixwin(command) @@ -63,7 +135,7 @@ command=fixwin(command) for i=0, #command do print (command[i]) end -os.exit(ret) +os.exit(0) --]] ret=os.spawn(command) diff --git a/Master/texmf-dist/scripts/tlgs/gswin32/pdf2dsc.tlu b/Master/texmf-dist/scripts/tlgs/gswin32/pdf2dsc.tlu index 25921db23ea..5a6cd479a7e 100755 --- a/Master/texmf-dist/scripts/tlgs/gswin32/pdf2dsc.tlu +++ b/Master/texmf-dist/scripts/tlgs/gswin32/pdf2dsc.tlu @@ -21,13 +21,22 @@ function fixwin (args_unix) end end -if os.type == 'windows' then - gs='gswin32c' -else - gs='gs' + +local function push (t, ...) + local args={...} + for _,v in ipairs(args) do + if type(v) == 'table' then + for _,x in ipairs(v) do + t[#t+1]=x + end + else + t[#t+1]=v + end + end end -if #arg == 0 or #arg > 2 then + +if #arg ~= 2 then io.stderr:write('Usage: pdf2dsc input.pdf [output.dsc]\n') os.exit(1) end @@ -39,9 +48,14 @@ else dscfile=string.gsub(pdffile, '%.%a+$', '.dsc') end -command={gs, '-q', '-dNODISPLAY', '-dSAFER', '-dDELAYSAFER', - '-sPDFname='..pdffile, '-sDSCname='..dscfile, 'pdf2dsc.ps', - '-c', 'quit'} +-- setup command + +local command={} +if os.type == 'unix' then command={'gs'} else command={'gswin32c'} end + +push(command, '-q', '-dNODISPLAY', '-dSAFER', '-dDELAYSAFER', + '-sPDFname='..pdffile, '-sDSCname='..dscfile, 'pdf2dsc.ps', + '-c', 'quit') command=fixwin(command) @@ -49,7 +63,7 @@ command=fixwin(command) for i=0, #command do print (command[i]) end -os.exit(ret) +os.exit(0) --]] ret=os.spawn(command) diff --git a/Master/texmf-dist/scripts/tlgs/gswin32/pdfopt.tlu b/Master/texmf-dist/scripts/tlgs/gswin32/pdfopt.tlu index d267d55f057..d694047cfff 100755 --- a/Master/texmf-dist/scripts/tlgs/gswin32/pdfopt.tlu +++ b/Master/texmf-dist/scripts/tlgs/gswin32/pdfopt.tlu @@ -2,13 +2,24 @@ --*-Lua-*- -- $Id$ --- Copyright (C) 2008 Reinhard Kotucha. +-- Copyright (C) 2008-2015 Reinhard Kotucha. -- You may freely use, modify and/or distribute this file. --- Replacement for pdfopt.bat. --- Linearize PDF +-- Generic wrapper for ps2pdf{,12,13,14} and pdfopt. -function fixwin (args_unix) + +local function usage (progname) + local message= + 'Usage: '..progname..' [options] \n\n'.. + ' can be either a PS, EPS, or PDF file.\n'.. + ' A single hyphen (-) denotes stdin.\n\n'.. + ' is required if is a PDF file\n'.. + ' or input is read from stdin.\n' + return message +end + + +local function fixwin (args_unix) if os.type == 'windows' then local args_win={} -- new table args_win[0]=args_unix[1] @@ -21,43 +32,133 @@ function fixwin (args_unix) end end -if os.type == 'windows' then - gs='gswin32c' -else - gs='gs' + +local function push (t, ...) + local args={...} + for _,v in ipairs(args) do + if type(v) == 'table' then + for _,x in ipairs(v) do + t[#t+1]=x + end + else + t[#t+1]=v + end + end +end + + +local function filename (file) + -- strip path + if string.find(file, '[/\\]') then + return string.match(file, '.*[/\\](.*)$') + else + return file + end +end + + +local function basename (file) + -- strip extension + return string.match(filename(file), '(.*)%..*') +end + + +local function extension (file) + -- return extension if available, false otherwise. + local fn=filename(file) + if fn:find('%.') then + return string.match(fn, '.*%.(.*)') + end end -command={gs, '-q', '-dNODISPLAY', '-dSAFER', '-dDELAYSAFER'} -files={} +local function parse_cmdline () + local files={} + local options={} -for i=1, #arg do - if string.find(arg[i], '^%-') then - command[#command+1]=arg[i] + local progname + local basename=filename(arg[0]) + if basename:find('%.') then + progname=basename:match('(.*)%..*') else - files[#files+1]=arg[i] + progname=basename end + + for i=1, #arg do + if string.find(arg[i], '^%-.+') then + push(options, arg[i]) + else + push(files, arg[i]) + end + end + files.input =files[1] + files.output=files[2] + return progname, options, files end -command[#command+1]='--' -command[#command+1]='pdfopt.ps' -if #files ~= 2 then - io.stderr:write('Usage: pdfopt [options] input.pdf output.pdf\n') - os.exit(1) -else - for i=1, #files do - command[#command+1]=files[i] +local function check_files (progname, files, default_output_ext) + if #files < 1 then + io.stderr:write(usage(progname)) + os.exit(1) + end + + if #files < 2 then + if extension(files.input) then + local ext=string.lower(extension(files.input)) + if ext:match(default_output_ext..'$') then + io.stderr:write('!Error: no output file specified.\n\n') + io.stderr:write(usage(progname)) + os.exit(1) + else + files.output=basename(files.input)..'.'..default_output_ext + end + else -- the input file has no extension + files.output=files.input..'.'..default_output_ext + end end end +-- main -- + +-- parse command line +local progname, options, file=parse_cmdline() + +check_files(progname, file, 'pdf') + +-- determine PDF level +local PDF_level='1.4' -- default, may be changed in the future +if progname == 'ps2pdf12' then PDF_level='1.2' +elseif progname == 'ps2pdf13' then PDF_level='1.3' +elseif progname == 'ps2pdf14' then PDF_level='1.4' +end + +-- setup command + +local command={} +if os.type == 'unix' then command={'gs'} else command={'gswin32c'} end + +push(command, '-P-', '-dSAFER', options, '-dCompatibilityLevel='..PDF_level) + +if progname == 'pdfopt' then push(command, '-dFastWebView=true') end + +push(command, '-q', '-P-', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite') + +if os.type == 'unix' then push(command, '-sstdout=%stderr') end + +push(command, '-sOutputFile='..file.output, '-P-', '-dSAFER') + +-- We have to include the options twice because -I only takes effect +-- if it appears before other options [see ps2pdfwr]. +push(command, options, '-c', '.setpdfwrite', '-f', file.input) + command=fixwin(command) --[[ prepend an additional hyphen to activate this code for i=0, #command do print (command[i]) end -os.exit(ret) +os.exit(0) --]] ret=os.spawn(command) diff --git a/Master/texmf-dist/scripts/tlgs/gswin32/ps2ascii.tlu b/Master/texmf-dist/scripts/tlgs/gswin32/ps2ascii.tlu index 2bc31ef26d9..d23c0458ea8 100755 --- a/Master/texmf-dist/scripts/tlgs/gswin32/ps2ascii.tlu +++ b/Master/texmf-dist/scripts/tlgs/gswin32/ps2ascii.tlu @@ -2,26 +2,55 @@ --*-Lua-*- -- $Id$ --- Copyright (C) 2008 Reinhard Kotucha. +-- Copyright (C) 2008-2015 Reinhard Kotucha. -- You may freely use, modify and/or distribute this file. -- Replacement for ps2ascii.bat. --- Convert PostScript to ASCII - -function fixwin (args_unix) - if os.type == 'windows' then - local args_win={} -- new table - args_win[0]=args_unix[1] - for i=1, #args_unix do - args_win[i]='"'..args_unix[i]..'"' + +-- Extract ASCII text from a PostScript file. Usage: +-- +-- ps2ascii [infile.ps [outfile.txt]] +-- +-- If outfile is omitted, output goes to stdout. +-- If both infile and outfile are omitted, ps2ascii acts as a filter, +-- reading from stdin and writing on stdout. + + +-- We have to pass the command as a string to os.execute() because we +-- need a shell for i/o-redirection. But we create a table first and +-- convert it to a string, just to make sure we don't miss any spaces. + +local function push (t, ...) + local args={...} + for _,v in ipairs(args) do + if type(v) == 'table' then + for _,x in ipairs(v) do + t[#t+1]=x + end + else + t[#t+1]=v end - return args_win + end +end + + +local function filename (file) + -- strip path + if string.find(file, '[/\\]') then + return string.match(file, '.*[/\\](.*)$') else - return args_unix + return file end end -function remove_tmpfiles (tmpfiles) + +local function remove_tmpfiles (tmpfiles) + -- The shell script contains + -- + -- trap "rm -f _temp_.err _temp_.out" 0 1 2 15 + -- + -- texlua doesn't support signals (yet). So we remove temporary files + -- if possible. for i=1, #tmpfiles do if lfs.isfile(tmpfiles[i]) then os.remove(tmpfiles[i]) @@ -29,46 +58,71 @@ function remove_tmpfiles (tmpfiles) end end -if os.type == 'windows' then - gs='gswin32c' -else - gs='gs' -end -command={gs, '-q', '-dNODISPLAY', '-dBATCH', '-dSAFER', '-dDELAYBIND', - '-dWRITESYSTEMDICT', '-dSIMPLE', '-c', 'save', - '-f', 'ps2ascii.ps'} +local function parse_cmdline () + local files={} + local options={} -if #arg < 2 then - if #arg == 0 then - command[#command+1]='-' - elseif #arg == 1 then - command[#command+1]=arg[1] + local progname + local basename=filename(arg[0]) + if basename:find('%.') then + progname=basename:match('(.*)%..*') + else + progname=basename end - command=fixwin(command) -elseif #arg == 2 then - -- We need a shell for I/O redirection. - command=gs..' -q -dNODISPLAY -dBATCH -dSAFER -dDELAYBIND '.. - '-dWRITESYSTEMDICT -dSIMPLE -c save '.. - '-f ps2ascii.ps "'..arg[1]..'" > "'..arg[2]..'"' -end ---[[ prepend an additional hyphen to activate this code -if type(command) == 'string' then - print(command) -else - for i=0, #command do - print (command[i]) + for i=1, #arg do + if string.find(arg[i], '^%-.+') then + push(options, arg[i]) + else + push(files, arg[i]) + end end + files.input =files[1] + files.output=files[2] + return progname, options, files end -os.exit(ret) ---]] -if type(command) == 'string' then - ret=os.execute(command) + +-- main -- + +local progname, options, files=parse_cmdline () + +-- setup command + +local command={gs} +if os.type == 'unix' then command={'gs'} else command={'gswin32c'} end + +push(command, {'-q', '-dNODISPLAY', '-P-', '-dSAFER', '-dDELAYBIND', + '-dWRITESYSTEMDICT', '-dSIMPLE'}) + +push(command, '-c', 'save', '-f', 'ps2ascii.ps') + +if #files == 0 then + push(command, '-') else - ret=os.spawn(command) + push(command, '"'..files.input..'"') end +push(command, '-c', 'quit') + +if #files > 1 then + push(command, '>', '"'..files.output..'"') +end + +local cmd_string=table.concat(command, ' ') + +--[[ prepend an additional hyphen to activate this code +print(cmd_string) +os.exit(0) +--]] + +ret=os.execute(cmd_string) + +-- The last character of the ASCII file is a form feed (^L). +-- Uncomment the following line if this confuses your terminal. +-- +-- if #files < 2 then io.stdout:write('\r') end + remove_tmpfiles{'_temp_.err', '_temp_.out'} os.exit(ret) diff --git a/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf.tlu b/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf.tlu index 7cb82173cfa..d694047cfff 100755 --- a/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf.tlu +++ b/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf.tlu @@ -2,13 +2,24 @@ --*-Lua-*- -- $Id$ --- Copyright (C) 2008 Reinhard Kotucha. +-- Copyright (C) 2008-2015 Reinhard Kotucha. -- You may freely use, modify and/or distribute this file. --- Replacement for ps2pdf*.bat. --- Convert PS to PDF +-- Generic wrapper for ps2pdf{,12,13,14} and pdfopt. -function fixwin (args_unix) + +local function usage (progname) + local message= + 'Usage: '..progname..' [options] \n\n'.. + ' can be either a PS, EPS, or PDF file.\n'.. + ' A single hyphen (-) denotes stdin.\n\n'.. + ' is required if is a PDF file\n'.. + ' or input is read from stdin.\n' + return message +end + + +local function fixwin (args_unix) if os.type == 'windows' then local args_win={} -- new table args_win[0]=args_unix[1] @@ -21,7 +32,23 @@ function fixwin (args_unix) end end -function filename (file) + +local function push (t, ...) + local args={...} + for _,v in ipairs(args) do + if type(v) == 'table' then + for _,x in ipairs(v) do + t[#t+1]=x + end + else + t[#t+1]=v + end + end +end + + +local function filename (file) + -- strip path if string.find(file, '[/\\]') then return string.match(file, '.*[/\\](.*)$') else @@ -29,75 +56,101 @@ function filename (file) end end -function basename (file) - return string.match(filename(file), '(.*)[%.].*') -end -if os.type == 'windows' then - gs='gswin32c' -else - gs='gs' +local function basename (file) + -- strip extension + return string.match(filename(file), '(.*)%..*') end -command={gs} -files={} -options={} - -PDF_level='1.4' -if string.find(filename(arg[0]), 'ps2pdf12') then - PDF_level='1.2' -elseif string.find(filename(arg[0]), 'ps2pdf13') then - PDF_level='1.3' -elseif string.find(filename(arg[0]), 'ps2pdf14') then - PDF_level='1.4' + +local function extension (file) + -- return extension if available, false otherwise. + local fn=filename(file) + if fn:find('%.') then + return string.match(fn, '.*%.(.*)') + end end -options[#options+1]='-dCompatibilityLevel='..PDF_level -for i=1, #arg do - if arg[i] == '-' then - files[#files+1]=arg[i] - elseif string.find(arg[i], '^%-') then - options[#options+1]=arg[i] +local function parse_cmdline () + local files={} + local options={} + + local progname + local basename=filename(arg[0]) + if basename:find('%.') then + progname=basename:match('(.*)%..*') else - files[#files+1]=arg[i] + progname=basename end -end -if #files < 1 or #files > 2 then - io.stderr:write('Usage: ps2pdf [options] (input.[e]ps|-) [output.pdf]\n') - os.exit(1) + for i=1, #arg do + if string.find(arg[i], '^%-.+') then + push(options, arg[i]) + else + push(files, arg[i]) + end + end + files.input =files[1] + files.output=files[2] + return progname, options, files end -if #files == 1 then - if files[1] == '-' then - outfile='-' - elseif string.find(filename(files[1]), '%.[eE]?[pP][sS]$') then - outfile=basename(files[1])..'.pdf' - else - outfile=filename(files[1])..'.pdf' + +local function check_files (progname, files, default_output_ext) + if #files < 1 then + io.stderr:write(usage(progname)) + os.exit(1) end -else - outfile=files[2] -end -for i=1, #options do - command[#command+1]=options[i] + if #files < 2 then + if extension(files.input) then + local ext=string.lower(extension(files.input)) + if ext:match(default_output_ext..'$') then + io.stderr:write('!Error: no output file specified.\n\n') + io.stderr:write(usage(progname)) + os.exit(1) + else + files.output=basename(files.input)..'.'..default_output_ext + end + else -- the input file has no extension + files.output=files.input..'.'..default_output_ext + end + end end -other_opts={'-q', '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite'} +-- main -- + +-- parse command line +local progname, options, file=parse_cmdline() + +check_files(progname, file, 'pdf') -for i=1, #other_opts do - command[#command+1]=other_opts[i] +-- determine PDF level +local PDF_level='1.4' -- default, may be changed in the future +if progname == 'ps2pdf12' then PDF_level='1.2' +elseif progname == 'ps2pdf13' then PDF_level='1.3' +elseif progname == 'ps2pdf14' then PDF_level='1.4' end -command[#command+1]='-sOutputFile='..outfile +-- setup command -other_opts={'-c', '.setpdfwrite', '-f', files[1]} +local command={} +if os.type == 'unix' then command={'gs'} else command={'gswin32c'} end -for i=1, #other_opts do - command[#command+1]=other_opts[i] -end +push(command, '-P-', '-dSAFER', options, '-dCompatibilityLevel='..PDF_level) + +if progname == 'pdfopt' then push(command, '-dFastWebView=true') end + +push(command, '-q', '-P-', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite') + +if os.type == 'unix' then push(command, '-sstdout=%stderr') end + +push(command, '-sOutputFile='..file.output, '-P-', '-dSAFER') + +-- We have to include the options twice because -I only takes effect +-- if it appears before other options [see ps2pdfwr]. +push(command, options, '-c', '.setpdfwrite', '-f', file.input) command=fixwin(command) @@ -105,7 +158,7 @@ command=fixwin(command) for i=0, #command do print (command[i]) end -os.exit(ret) +os.exit(0) --]] ret=os.spawn(command) diff --git a/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf12.tlu b/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf12.tlu index a35e3b0912a..d694047cfff 100755 --- a/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf12.tlu +++ b/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf12.tlu @@ -2,13 +2,24 @@ --*-Lua-*- -- $Id$ --- Copyright (C) 2008 Reinhard Kotucha. +-- Copyright (C) 2008-2015 Reinhard Kotucha. -- You may freely use, modify and/or distribute this file. --- Replacement for ps2pdf*.bat. --- Convert PS to PDF +-- Generic wrapper for ps2pdf{,12,13,14} and pdfopt. -function fixwin (args_unix) + +local function usage (progname) + local message= + 'Usage: '..progname..' [options] \n\n'.. + ' can be either a PS, EPS, or PDF file.\n'.. + ' A single hyphen (-) denotes stdin.\n\n'.. + ' is required if is a PDF file\n'.. + ' or input is read from stdin.\n' + return message +end + + +local function fixwin (args_unix) if os.type == 'windows' then local args_win={} -- new table args_win[0]=args_unix[1] @@ -21,7 +32,23 @@ function fixwin (args_unix) end end -function filename (file) + +local function push (t, ...) + local args={...} + for _,v in ipairs(args) do + if type(v) == 'table' then + for _,x in ipairs(v) do + t[#t+1]=x + end + else + t[#t+1]=v + end + end +end + + +local function filename (file) + -- strip path if string.find(file, '[/\\]') then return string.match(file, '.*[/\\](.*)$') else @@ -29,75 +56,101 @@ function filename (file) end end -function basename (file) - return string.match(filename(file), '(.*)[%.].*') -end -if os.type == 'windows' then - gs='gswin32c' -else - gs='gs' +local function basename (file) + -- strip extension + return string.match(filename(file), '(.*)%..*') end -command={gs} -files={} -options={} - -PDF_level='1.4' -if string.find(filename(arg[0]), 'ps2pdf12') then - PDF_level='1.2' -elseif string.find(filename(arg[0]), 'ps2pdf13') then - PDF_level='1.3' -elseif string.find(filename(arg[0]), 'ps2pdf14') then - PDF_level='1.4' + +local function extension (file) + -- return extension if available, false otherwise. + local fn=filename(file) + if fn:find('%.') then + return string.match(fn, '.*%.(.*)') + end end -options[#options+1]='-dCompatibilityLevel='..PDF_level -for i=1, #arg do - if arg[i] == '-' then - files[#files+1]=arg[i] - elseif string.find(arg[i], '^%-') then - options[#options+1]=arg[i] +local function parse_cmdline () + local files={} + local options={} + + local progname + local basename=filename(arg[0]) + if basename:find('%.') then + progname=basename:match('(.*)%..*') else - files[#files+1]=arg[i] + progname=basename end -end -if #files < 1 or #files > 2 then - io.stderr:write('Usage: ps2pdf [options] (input.[e]ps|-) [output.pdf]\n') - os.exit(1) + for i=1, #arg do + if string.find(arg[i], '^%-.+') then + push(options, arg[i]) + else + push(files, arg[i]) + end + end + files.input =files[1] + files.output=files[2] + return progname, options, files end -if #files == 1 then - if files[1] == '-' then - outfile='-' - elseif string.find(filename(files[1]), '%.[eE]?[pP][sS]$') then - outfile=basename(files[1])..'.pdf' - else - outfile=filename(files[1])..'.pdf' + +local function check_files (progname, files, default_output_ext) + if #files < 1 then + io.stderr:write(usage(progname)) + os.exit(1) end -else - outfile=files[2] -end -for i=1, #options do - command[#command+1]=options[i] + if #files < 2 then + if extension(files.input) then + local ext=string.lower(extension(files.input)) + if ext:match(default_output_ext..'$') then + io.stderr:write('!Error: no output file specified.\n\n') + io.stderr:write(usage(progname)) + os.exit(1) + else + files.output=basename(files.input)..'.'..default_output_ext + end + else -- the input file has no extension + files.output=files.input..'.'..default_output_ext + end + end end -other_opts={'-q', '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite'} +-- main -- + +-- parse command line +local progname, options, file=parse_cmdline() + +check_files(progname, file, 'pdf') -for i=1, #other_opts do - command[#command+1]=other_opts[i] +-- determine PDF level +local PDF_level='1.4' -- default, may be changed in the future +if progname == 'ps2pdf12' then PDF_level='1.2' +elseif progname == 'ps2pdf13' then PDF_level='1.3' +elseif progname == 'ps2pdf14' then PDF_level='1.4' end -command[#command+1]='-sOutputFile='..outfile +-- setup command -other_opts={'-c', '.setpdfwrite', '-f', files[1]} +local command={} +if os.type == 'unix' then command={'gs'} else command={'gswin32c'} end -for i=1, #other_opts do - command[#command+1]=other_opts[i] -end +push(command, '-P-', '-dSAFER', options, '-dCompatibilityLevel='..PDF_level) + +if progname == 'pdfopt' then push(command, '-dFastWebView=true') end + +push(command, '-q', '-P-', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite') + +if os.type == 'unix' then push(command, '-sstdout=%stderr') end + +push(command, '-sOutputFile='..file.output, '-P-', '-dSAFER') + +-- We have to include the options twice because -I only takes effect +-- if it appears before other options [see ps2pdfwr]. +push(command, options, '-c', '.setpdfwrite', '-f', file.input) command=fixwin(command) @@ -105,7 +158,7 @@ command=fixwin(command) for i=0, #command do print (command[i]) end -os.exit(ret) +os.exit(0) --]] ret=os.spawn(command) diff --git a/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf13.tlu b/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf13.tlu index a35e3b0912a..d694047cfff 100755 --- a/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf13.tlu +++ b/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf13.tlu @@ -2,13 +2,24 @@ --*-Lua-*- -- $Id$ --- Copyright (C) 2008 Reinhard Kotucha. +-- Copyright (C) 2008-2015 Reinhard Kotucha. -- You may freely use, modify and/or distribute this file. --- Replacement for ps2pdf*.bat. --- Convert PS to PDF +-- Generic wrapper for ps2pdf{,12,13,14} and pdfopt. -function fixwin (args_unix) + +local function usage (progname) + local message= + 'Usage: '..progname..' [options] \n\n'.. + ' can be either a PS, EPS, or PDF file.\n'.. + ' A single hyphen (-) denotes stdin.\n\n'.. + ' is required if is a PDF file\n'.. + ' or input is read from stdin.\n' + return message +end + + +local function fixwin (args_unix) if os.type == 'windows' then local args_win={} -- new table args_win[0]=args_unix[1] @@ -21,7 +32,23 @@ function fixwin (args_unix) end end -function filename (file) + +local function push (t, ...) + local args={...} + for _,v in ipairs(args) do + if type(v) == 'table' then + for _,x in ipairs(v) do + t[#t+1]=x + end + else + t[#t+1]=v + end + end +end + + +local function filename (file) + -- strip path if string.find(file, '[/\\]') then return string.match(file, '.*[/\\](.*)$') else @@ -29,75 +56,101 @@ function filename (file) end end -function basename (file) - return string.match(filename(file), '(.*)[%.].*') -end -if os.type == 'windows' then - gs='gswin32c' -else - gs='gs' +local function basename (file) + -- strip extension + return string.match(filename(file), '(.*)%..*') end -command={gs} -files={} -options={} - -PDF_level='1.4' -if string.find(filename(arg[0]), 'ps2pdf12') then - PDF_level='1.2' -elseif string.find(filename(arg[0]), 'ps2pdf13') then - PDF_level='1.3' -elseif string.find(filename(arg[0]), 'ps2pdf14') then - PDF_level='1.4' + +local function extension (file) + -- return extension if available, false otherwise. + local fn=filename(file) + if fn:find('%.') then + return string.match(fn, '.*%.(.*)') + end end -options[#options+1]='-dCompatibilityLevel='..PDF_level -for i=1, #arg do - if arg[i] == '-' then - files[#files+1]=arg[i] - elseif string.find(arg[i], '^%-') then - options[#options+1]=arg[i] +local function parse_cmdline () + local files={} + local options={} + + local progname + local basename=filename(arg[0]) + if basename:find('%.') then + progname=basename:match('(.*)%..*') else - files[#files+1]=arg[i] + progname=basename end -end -if #files < 1 or #files > 2 then - io.stderr:write('Usage: ps2pdf [options] (input.[e]ps|-) [output.pdf]\n') - os.exit(1) + for i=1, #arg do + if string.find(arg[i], '^%-.+') then + push(options, arg[i]) + else + push(files, arg[i]) + end + end + files.input =files[1] + files.output=files[2] + return progname, options, files end -if #files == 1 then - if files[1] == '-' then - outfile='-' - elseif string.find(filename(files[1]), '%.[eE]?[pP][sS]$') then - outfile=basename(files[1])..'.pdf' - else - outfile=filename(files[1])..'.pdf' + +local function check_files (progname, files, default_output_ext) + if #files < 1 then + io.stderr:write(usage(progname)) + os.exit(1) end -else - outfile=files[2] -end -for i=1, #options do - command[#command+1]=options[i] + if #files < 2 then + if extension(files.input) then + local ext=string.lower(extension(files.input)) + if ext:match(default_output_ext..'$') then + io.stderr:write('!Error: no output file specified.\n\n') + io.stderr:write(usage(progname)) + os.exit(1) + else + files.output=basename(files.input)..'.'..default_output_ext + end + else -- the input file has no extension + files.output=files.input..'.'..default_output_ext + end + end end -other_opts={'-q', '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite'} +-- main -- + +-- parse command line +local progname, options, file=parse_cmdline() + +check_files(progname, file, 'pdf') -for i=1, #other_opts do - command[#command+1]=other_opts[i] +-- determine PDF level +local PDF_level='1.4' -- default, may be changed in the future +if progname == 'ps2pdf12' then PDF_level='1.2' +elseif progname == 'ps2pdf13' then PDF_level='1.3' +elseif progname == 'ps2pdf14' then PDF_level='1.4' end -command[#command+1]='-sOutputFile='..outfile +-- setup command -other_opts={'-c', '.setpdfwrite', '-f', files[1]} +local command={} +if os.type == 'unix' then command={'gs'} else command={'gswin32c'} end -for i=1, #other_opts do - command[#command+1]=other_opts[i] -end +push(command, '-P-', '-dSAFER', options, '-dCompatibilityLevel='..PDF_level) + +if progname == 'pdfopt' then push(command, '-dFastWebView=true') end + +push(command, '-q', '-P-', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite') + +if os.type == 'unix' then push(command, '-sstdout=%stderr') end + +push(command, '-sOutputFile='..file.output, '-P-', '-dSAFER') + +-- We have to include the options twice because -I only takes effect +-- if it appears before other options [see ps2pdfwr]. +push(command, options, '-c', '.setpdfwrite', '-f', file.input) command=fixwin(command) @@ -105,7 +158,7 @@ command=fixwin(command) for i=0, #command do print (command[i]) end -os.exit(ret) +os.exit(0) --]] ret=os.spawn(command) diff --git a/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf14.tlu b/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf14.tlu index a35e3b0912a..d694047cfff 100755 --- a/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf14.tlu +++ b/Master/texmf-dist/scripts/tlgs/gswin32/ps2pdf14.tlu @@ -2,13 +2,24 @@ --*-Lua-*- -- $Id$ --- Copyright (C) 2008 Reinhard Kotucha. +-- Copyright (C) 2008-2015 Reinhard Kotucha. -- You may freely use, modify and/or distribute this file. --- Replacement for ps2pdf*.bat. --- Convert PS to PDF +-- Generic wrapper for ps2pdf{,12,13,14} and pdfopt. -function fixwin (args_unix) + +local function usage (progname) + local message= + 'Usage: '..progname..' [options] \n\n'.. + ' can be either a PS, EPS, or PDF file.\n'.. + ' A single hyphen (-) denotes stdin.\n\n'.. + ' is required if is a PDF file\n'.. + ' or input is read from stdin.\n' + return message +end + + +local function fixwin (args_unix) if os.type == 'windows' then local args_win={} -- new table args_win[0]=args_unix[1] @@ -21,7 +32,23 @@ function fixwin (args_unix) end end -function filename (file) + +local function push (t, ...) + local args={...} + for _,v in ipairs(args) do + if type(v) == 'table' then + for _,x in ipairs(v) do + t[#t+1]=x + end + else + t[#t+1]=v + end + end +end + + +local function filename (file) + -- strip path if string.find(file, '[/\\]') then return string.match(file, '.*[/\\](.*)$') else @@ -29,75 +56,101 @@ function filename (file) end end -function basename (file) - return string.match(filename(file), '(.*)[%.].*') -end -if os.type == 'windows' then - gs='gswin32c' -else - gs='gs' +local function basename (file) + -- strip extension + return string.match(filename(file), '(.*)%..*') end -command={gs} -files={} -options={} - -PDF_level='1.4' -if string.find(filename(arg[0]), 'ps2pdf12') then - PDF_level='1.2' -elseif string.find(filename(arg[0]), 'ps2pdf13') then - PDF_level='1.3' -elseif string.find(filename(arg[0]), 'ps2pdf14') then - PDF_level='1.4' + +local function extension (file) + -- return extension if available, false otherwise. + local fn=filename(file) + if fn:find('%.') then + return string.match(fn, '.*%.(.*)') + end end -options[#options+1]='-dCompatibilityLevel='..PDF_level -for i=1, #arg do - if arg[i] == '-' then - files[#files+1]=arg[i] - elseif string.find(arg[i], '^%-') then - options[#options+1]=arg[i] +local function parse_cmdline () + local files={} + local options={} + + local progname + local basename=filename(arg[0]) + if basename:find('%.') then + progname=basename:match('(.*)%..*') else - files[#files+1]=arg[i] + progname=basename end -end -if #files < 1 or #files > 2 then - io.stderr:write('Usage: ps2pdf [options] (input.[e]ps|-) [output.pdf]\n') - os.exit(1) + for i=1, #arg do + if string.find(arg[i], '^%-.+') then + push(options, arg[i]) + else + push(files, arg[i]) + end + end + files.input =files[1] + files.output=files[2] + return progname, options, files end -if #files == 1 then - if files[1] == '-' then - outfile='-' - elseif string.find(filename(files[1]), '%.[eE]?[pP][sS]$') then - outfile=basename(files[1])..'.pdf' - else - outfile=filename(files[1])..'.pdf' + +local function check_files (progname, files, default_output_ext) + if #files < 1 then + io.stderr:write(usage(progname)) + os.exit(1) end -else - outfile=files[2] -end -for i=1, #options do - command[#command+1]=options[i] + if #files < 2 then + if extension(files.input) then + local ext=string.lower(extension(files.input)) + if ext:match(default_output_ext..'$') then + io.stderr:write('!Error: no output file specified.\n\n') + io.stderr:write(usage(progname)) + os.exit(1) + else + files.output=basename(files.input)..'.'..default_output_ext + end + else -- the input file has no extension + files.output=files.input..'.'..default_output_ext + end + end end -other_opts={'-q', '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite'} +-- main -- + +-- parse command line +local progname, options, file=parse_cmdline() + +check_files(progname, file, 'pdf') -for i=1, #other_opts do - command[#command+1]=other_opts[i] +-- determine PDF level +local PDF_level='1.4' -- default, may be changed in the future +if progname == 'ps2pdf12' then PDF_level='1.2' +elseif progname == 'ps2pdf13' then PDF_level='1.3' +elseif progname == 'ps2pdf14' then PDF_level='1.4' end -command[#command+1]='-sOutputFile='..outfile +-- setup command -other_opts={'-c', '.setpdfwrite', '-f', files[1]} +local command={} +if os.type == 'unix' then command={'gs'} else command={'gswin32c'} end -for i=1, #other_opts do - command[#command+1]=other_opts[i] -end +push(command, '-P-', '-dSAFER', options, '-dCompatibilityLevel='..PDF_level) + +if progname == 'pdfopt' then push(command, '-dFastWebView=true') end + +push(command, '-q', '-P-', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite') + +if os.type == 'unix' then push(command, '-sstdout=%stderr') end + +push(command, '-sOutputFile='..file.output, '-P-', '-dSAFER') + +-- We have to include the options twice because -I only takes effect +-- if it appears before other options [see ps2pdfwr]. +push(command, options, '-c', '.setpdfwrite', '-f', file.input) command=fixwin(command) @@ -105,7 +158,7 @@ command=fixwin(command) for i=0, #command do print (command[i]) end -os.exit(ret) +os.exit(0) --]] ret=os.spawn(command) diff --git a/Master/texmf-dist/scripts/tlgs/gswin32/ps2ps.tlu b/Master/texmf-dist/scripts/tlgs/gswin32/ps2ps.tlu index 2d414700ebb..063fc76d0cc 100755 --- a/Master/texmf-dist/scripts/tlgs/gswin32/ps2ps.tlu +++ b/Master/texmf-dist/scripts/tlgs/gswin32/ps2ps.tlu @@ -5,8 +5,21 @@ -- Copyright (C) 2010 Reinhard Kotucha. -- You may freely use, modify and/or distribute this file. --- Replacement for ps2ps.bat. --- 'Distill' PostScript. +-- Replacement for ps2ps2.bat. +-- Converting PostScript 3 or PDF into PostScript 2 with the +-- Ghostscript 'ps2write' device. +-- This generates a PDF-style stream with an attached +-- PostScript program to interpret it. + + +local function usage (progname) + local message= + 'Usage: '..progname..' [options] \n\n'.. + ' can be either a PS, EPS, PDF file, or stdin.\n'.. + ' A single hyphen (-) denotes stdin.\n' + return message +end + function fixwin(args_unix) if os.type == 'windows' then @@ -21,47 +34,97 @@ function fixwin(args_unix) end end -if os.type == 'windows' then - gs='gswin32c' -else - gs='gs' -end +local function push (t, ...) + local args={...} + for _,v in ipairs(args) do + if type(v) == 'table' then + for _,x in ipairs(v) do + t[#t+1]=x + end + else + t[#t+1]=v + end + end +end -files={} -options={'-dNOPAUSE', '-dBATCH', '-dSAFER'} -for i=1, #arg do - if string.find(arg[i], '^%-$') then - files[#files+1]=arg[i] - elseif string.find(arg[i], '^%-') then - options[#options+1]=arg[i] +local function filename (file) + -- strip path + if string.find(file, '[/\\]') then + return string.match(file, '.*[/\\](.*)$') else - files[#files+1]=arg[i] + return file end end -if #files ~= 2 then - io.stderr:write('Usage: ps2ps [options] input.ps output.ps\n') - io.stderr:write(' e.g. ps2ps -sPAPERSIZE=a4 input.ps output.ps\n') - os.exit(1) +local function basename (file) + -- strip extension + return string.match(filename(file), '(.*)%..*') end -command={gs, '-q', '-sDEVICE=pswrite'} +local function extension (file) + -- return extension if available, false otherwise. + local fn=filename(file) + if fn:find('%.') then + return string.match(fn, '.*%.(.*)') + end +end + + +local function parse_cmdline () + local files={} + local options={} + + local progname + local basename=filename(arg[0]) + if basename:find('%.') then + progname=basename:match('(.*)%..*') + else + progname=basename + end -if os.type=='unix' then - command[#command+1]='-sstdout=%stderr' + for i=1, #arg do + if string.find(arg[i], '^%-.+') then + push(options, arg[i]) + else + push(files, arg[i]) + end + end + files.input =files[1] + files.output=files[2] + + return progname, options, files end -command[#command+1]='-sOutputFile='..files[2] -for i=1, #options do - command[#command+1]=options[i] +local function check_files (progname, files) + if #files < 2 then + io.stderr:write(usage(progname)) + os.exit(1) + end end -command[#command+1]=files[1] +-- main -- + +local progname, options, file=parse_cmdline() + +check_files (progname, file) + +-- setup command + +local command={} +if os.type == 'unix' then command={'gs'} else command={'gswin32c'} end + +push(command, '-q', '-sDEVICE=ps2write') + +if os.type=='unix' then push(command, '-sstdout=%stderr') end + +push(command, '-sOutputFile='..file.output) +push(command, '-dNOPAUSE', '-dBATCH', '-P-', '-dSAFER') +push(command, options, file.input) command=fixwin(command) @@ -69,7 +132,7 @@ command=fixwin(command) for i=0, #command do print (command[i]) end -os.exit(ret) +os.exit(0) --]] ret=os.spawn(command) diff --git a/Master/texmf-dist/scripts/tlgs/gswin32/ps2ps2.tlu b/Master/texmf-dist/scripts/tlgs/gswin32/ps2ps2.tlu deleted file mode 100755 index 5fa86abf0d2..00000000000 --- a/Master/texmf-dist/scripts/tlgs/gswin32/ps2ps2.tlu +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env texlua ---*-Lua-*- --- $Id$ - --- Copyright (C) 2010 Reinhard Kotucha. --- You may freely use, modify and/or distribute this file. - --- Replacement for ps2ps2.bat. --- Converting PostScript 3 or PDF into PostScript 2 with the --- Ghostscript 'ps2write' device. --- This generates a PDF-style stream with an attached --- PostScript program to interpret it. - -function fixwin(args_unix) - if os.type == 'windows' then - local args_win={} -- new table - args_win[0]=args_unix[1] - for i=1, #args_unix do - args_win[i]='"'..args_unix[i]..'"' - end - return args_win - else - return args_unix - end -end - -if os.type == 'windows' then - gs='gswin32c' -else - gs='gs' -end - - -files={} -options={'-dNOPAUSE', '-dBATCH', '-dSAFER'} - -for i=1, #arg do - if string.find(arg[i], '^%-$') then - files[#files+1]=arg[i] - elseif string.find(arg[i], '^%-') then - options[#options+1]=arg[i] - else - files[#files+1]=arg[i] - end -end - - -if #files ~= 2 then - io.stderr:write('Usage: ps2ps2 [options] input.ps output.ps\n') - io.stderr:write(' e.g. ps2ps2 -sPAPERSIZE=a4 input.ps output.ps\n') - os.exit(1) -end - - -command={gs, '-q', '-sDEVICE=ps2write'} - -if os.type=='unix' then - command[#command+1]='-sstdout=%stderr' -end - -command[#command+1]='-sOutputFile='..files[2] - -for i=1, #options do - command[#command+1]=options[i] -end - -command[#command+1]=files[1] - -command=fixwin(command) - ---[[ prepend an additional hyphen to activate this code -for i=0, #command do - print (command[i]) -end -os.exit(ret) ---]] - -ret=os.spawn(command) -os.exit(ret) diff --git a/Master/tlpkg/tlgs/lib/pdfopt.ps b/Master/tlpkg/tlgs/lib/pdfopt.ps deleted file mode 100644 index 88a8943f278..00000000000 --- a/Master/tlpkg/tlgs/lib/pdfopt.ps +++ /dev/null @@ -1,1272 +0,0 @@ -% Copyright (C) 2001-2012 Artifex Software, Inc. -% All Rights Reserved. -% -% This software is provided AS-IS with no warranty, either express or -% implied. -% -% This software is distributed under license and may not be copied, -% modified or distributed except as expressly authorized under the terms -% of the license contained in the file LICENSE in this distribution. -% -% Refer to licensing information at http://www.artifex.com or contact -% Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael, -% CA 94903, U.S.A., +1(415)492-9861, for further information. -% - -% PDF linearizer ("optimizer"). - -.currentglobal true .setglobal -/pdfoptdict 200 dict def -pdfoptdict begin - -% This linearizer is designed for simplicity, not for performance. -% See the main program (the last procedure in the file) for comments -% describing the main processing sequence. - -% ---------------- Utilities ---------------- % - -% ------ Data structures ------ % - -% Distinguish dictionaries, arrays, and everything else. -/ifdaelse { % ifdaelse - - 3 index type dup /dicttype eq { - pop pop pop - } { - dup /arraytype ne exch /packedarraytype ne and { - exch - } if pop exch pop - } ifelse exec -} bind def - -% Implement dynamically growable arrays using a dictionary. -/darray { % darray - dict -} bind def -/dadd { % dadd - - 1 index length exch put -} bind def -/daforall { % daforall - - /exch cvx /get cvx 3 -1 roll /exec cvx 5 packedarray cvx - 0 1 2 index 0 get length 1 sub 4 -1 roll for -} bind def -/dacontents { % dacontents - [ exch { } daforall ] -} bind def -/dacontstring { % dacontstring - 0 1 index { exch pop length add } forall string - dup /NullEncode filter - % Stack: darray str filter - 3 -1 roll { 1 index exch writestring } daforall - closefile -} bind def - -% Force an object, mapping it if it is a reference. -/omforcenew { % omforce - dup oforce 2 copy eq { pop true } { exch 0 get omapnew exch pop } ifelse -} bind def -/omforce { % omforce - omforcenew pop -} bind def -/omget { % omget - get omforce -} bind def -% Visit an entire tree. -/omvisit { % omvisit - - omforcenew { - { { omvisit omvisit } forall } - { { omvisit } forall } - { pop } - ifdaelse - } { - pop - } ifelse -} bind def -% Visit a tree, stopping at references to Page objects. -% (This is only needed for the OpenAction in the Catalog.) -/omvisitnopage { % omvisitnopage - - dup oforce dup type /dicttype eq { - /Type .knownget { /Page eq } { false } ifelse - } { - pop false - } ifelse { - pop % Page reference - } { - omforcenew { - { { omvisitnopage omvisitnopage } forall } - { { omvisitnopage } forall } - { pop } - ifdaelse - } { - pop - } ifelse - } ifelse -} bind def - -% Collect the list of currently mapped object numbers, in order. -/omapped { % - omapped - RMap ld_length larray exch lgrowto - RMap { - 2 index 3 1 roll 1 sub exch lput - } ld_forall -} bind def - -% Collect the list of object numbers passed to omap by a procedure. -/visited { % visited - false currentomap 2 .execn - omapped exch setomap -} bind def - -% ------ Output ------ % - -% Provide a framework for closure-based streams. -.currentglobal false .setglobal -userdict /clostreams 20 dict put % stream -> [data endproc] -.setglobal -% Create a closure-based stream. -/clostream { % clostream - 2 index 3 -1 roll /exec load 3 packedarray cvx - /NullEncode filter - % Stack: data endproc stream - clostreams 1 index 5 -2 roll 2 array astore put -} bind def -% Close a closure-based stream. -/closend { % closend - dup closefile clostreams exch - 2 copy get 3 1 roll undef aload pop exec -} bind def - -% Implement in-memory output streams. -/msproc { % msproc - 3 -1 roll dadd { 100 string } { () } ifelse -} bind def -/mstream { % - mstream - 10 darray {msproc} {dacontstring} clostream -} bind def -/mcontents { % mcontents - closend -} bind def - -% Implement a stream that only keeps track of its position. -% (All streams should do this, but the PLRM doesn't require it.) -/posbuf 100 string def -/posproc { % posproc - 0 2 copy get 5 -1 roll length add put - pop //posbuf -} bind def -/postream { % - postream - [0] {posproc} {0 get} clostream -} bind def -/poslength { % poslength - closend -} bind def - -% Implement streams with variable-bit-width data. -% Note that these are dictionary objects, not stream objects. -/bitstream { % bitstream - 4 dict begin /S exch def /N 8 def /B 0 def - currentdict end -} bind def -/bitwrite { % bitwrite - - PDFOPTDEBUG { ( ) print 1 index =only (:) print dup = } if - 3 -1 roll begin - N exch sub dup 0 ge { - /N exch def N bitshift B add - } { - 2 copy bitshift B add S exch write - % Stack: value -left - { 8 add dup 0 ge { exit } if - 2 copy bitshift 255 and S exch write - } loop - /N 1 index def bitshift 255 and - } ifelse /B exch def - end -} bind def -/bitflush { % bitflush - - begin N 8 ne { S B write /B 0 def /N 8 def } if end -} bind def - -/bwn { % bwn - - 2 copy % v w v w - 2 exch exp ge { % v w v>=2**w - /bwn cvx /rangecheck signalerror - } if - bits 3 1 roll bitwrite -} def - -% Capture OFile output on the temporary file, in memory, or just as a length. -/totemp { % totemp - TFile fileposition OFile - /OFile TFile def 3 .execn - /OFile exch def - TFile fileposition -} bind def -/tomemory { % tomemory - OFile /OFile mstream def 2 .execn - OFile mcontents exch /OFile exch def -} bind def -/tolength { % tolength - OFile /OFile postream def 2 .execn - OFile poslength exch /OFile exch def -} bind def - -% Copy a range of bytes from TFile to OFile. -/copyrange { % copybytes - - TFile 2 index setfileposition - exch sub 1024 string exch { - % Stack: buf left - 2 copy 1 index length .min 0 exch getinterval - TFile exch readstring pop OFile exch writestring - 1 index length sub dup 0 le { exit } if - } loop pop pop -} bind def - -% Pad with blanks to a specified position. -/padto { % padto - - OFile fileposition sub - dup 0 lt { - (ERROR: file position incorrect by ) print = - /padto cvx /rangecheck signalerror - } { - { ( ) ows } repeat - } ifelse -} bind def - -% ---------------- Read objects into memory ---------------- % - -/touch { % touch - - { - { touch touch } forall - } { - dup xcheck { - % Executable array, must be an indirect object. - dup 0 get resolved? { pop pop } { oforce touch } ifelse - } { - { touch } forall - } ifelse - } { - pop - } ifdaelse -} bind def - -% ---------------- Replace references with referents ---------------- % - -/replaceable? { % replaceable? - dup type /integertype eq exch xcheck not and -} bind def -/replacement { % replacement - dup oforce dup replaceable? { exch } if pop -} bind def - -/replacerefs { % replacerefs - { - dup { - 2 index 2 index undef - exch replacement exch replacement - 2 index 3 1 roll put - } forall - } { - 0 1 2 index length 1 sub { - 1 index exch 2 copy get replacement put - } for - } { - } ifdaelse -} bind def - -/replaceReferences { % - replaceReferences - - Objects { replacerefs pop } lforall - % Delete replaced objects. - 0 1 Objects llength 1 sub { - Objects 1 index lget replaceable? { - PDFOPTDEBUG { (Deleting ) print dup = } if - Generations 1 index 0 lput - } if pop - } for -} bind def - -% ---------------- Create new objects ---------------- % - -/createObjects { % [...] createObjects - Objects llength dup - dup 3 index length add growPDFobjects - % Stack: objects objn objn - 3 1 roll exch { - Objects 2 index 3 -1 roll lput - Generations 1 index 1 lput - 1 add - } forall pop -} bind def - -% ---------------- Propagate attributes ---------------- % - -/nopropattrs << - % Never propagate these. - /Type dup /Kids dup /Count dup /Parent dup - % Handle Resources specially. - /Resources dup ->> def - -% Merge Resources. -/mergeres { % mergeres - - % Values in todict take priority over fromdict. - 1 index /Resources .knownget { - 1 index /Resources .knownget { - % Stack: fromdict todict fromres tores - exch oforce exch oforce - % todict's Resources may be shared, so make a copy. - dup length dict .copydict - exch { - % Stack: fromdict todict tores' fromkey fromvalue - 2 index 2 index knownoget { - % Stack: fromdict todict tores' fromkey fromvalue tovalue - exch oforce exch - % ProcSet is an array, other types are dictionaries. - dup type /dicttype eq { - % Dictionary, not ProcSet. - exch dup length 2 index length add dict .copydict .copydict - } { - % Array or packed array, ProcSet. - % Use dictionaries to do the merge. - dup length 2 index length add dict begin - exch { dup def } forall { dup def } forall - mark currentdict end { pop } forall .packtomark - } ifelse - } if - 2 index 3 1 roll put - } forall - } if /Resources exch put pop - } { - pop pop - } ifelse -} bind def - -% Merge attributes other than Resources. -/mergeattrs { % mergeattrs - % Values in todict take priority over fromdict. - 1 index { - % Stack: fromdict todict fromkey fromvalue - //nopropattrs 2 index known { - pop pop - } { - 2 index 2 index known { pop pop } { 2 index 3 1 roll put } ifelse - } ifelse - } forall -} bind def - -% Propagate attributes to a subtree. -/proppage { % proppage - - % We should be able to tell when we reach a leaf - % by finding a Type unequal to /Pages. Unfortunately, - % some files distributed by Adobe lack the Type key - % in some of the Pages nodes! Instead, we check for Kids. - dup /Kids knownoget { - % Accumulate inherited values. - 3 1 roll - % Stack: kids attrs pagesnode - dup length dict .copydict mergeattrs - dup 3 1 roll mergeres - exch { oforce 1 index exch proppage } forall pop - } { - % Merge inherited values into the leaf. - mergeattrs mergeres - } ifelse -} bind def - -% Propagate attributes to all pages. -/propagateAttributes { % - propagateAttributes - - 0 dict Trailer /Root oget /Pages oget proppage -} bind def - -% ---------------- Identify document-level objects ---------------- % - -/identifyDocumentObjects { % - identifyDocumentObjects - { - Trailer /Root omget - dup /PageMode .knownget { omvisit } if - % Don't allow omvisit to trace references to Page objects. - dup /OpenAction .knownget { omvisitnopage } if - Trailer /Encrypt .knownget { omvisit } if - dup /Threads .knownget { - omforce dup //null ne { { omvisitnopage } forall } { pop } ifelse - } if - dup /AcroForm .knownget { omvisitnopage } if - pop - } visited -} bind def - -% ---------------- Identify the objects of each page ---------------- % - -/identifyfont { % identifyfont - - omforce { - exch /FontDescriptor eq { - omforce dup /Flags .knownget { 32 and 0 ne } { false } ifelse - exch { - exch dup dup /FontFile eq exch /FontFile2 eq or - exch /FontFile3 eq or 2 index and { - fontfiles exch dadd - } { - omvisit - } ifelse - } forall pop - } { - omvisit - } ifelse - } forall -} bind def - -% Collect all the objects referenced from a page. The first object number -% (which may not be the smallest one) is that of the page object itself. -/identifyPageObjects { % identifyPageObjects - PDFOPTDEBUG { - (%Objects for page: ) print dup = - } if - pdffindpageref - dup 0 get 3 1 roll - 4 dict begin - /filter_params 10 darray def - /images 10 darray def - /fontfiles 10 darray def - { - omforce - % Stack: pageobj# extra page - % Visit any extra objects if applicable. - exch omvisitnopage - % Visit Annots, if any. - % We don't try to defer the drawing information. - dup /Annots .knownget { omvisitnopage } if - % Visit beads. - dup /B .knownget { omvisitnopage } if - % Visit resources dictionaries. - dup /Resources .knownget { - omforce dup { - % Visit the first-level Resource dictionaries. - omforce pop pop - } forall { - % Visit the resources themselves. - % Skip Image XObjects, and FontFile streams if the - % FontDescriptor Flags have bit 6 set. - % We don't try to visit the resources in the order in which - % the Contents stream(s) reference(s) them. - exch dup /XObject eq { - pop oforce { - dup oforce /Subtype get /Image eq { - dup oforce /DecodeParms .knownget { - oforce { - exch /JBIG2Globals eq { - filter_params exch dadd - } { - pop - } ifelse - } forall - } if - images exch dadd - } { - omvisit - } ifelse pop - } forall - } { - /Font eq { - oforce { identifyfont pop } forall - } { - oforce omvisit - } ifelse - } ifelse - } forall - } if - % Visit the Contents stream(s). - dup /Contents .knownget { omvisit } if - % Visit Image XObjects. We don't try to visit them in - % reference order. - filter_params { omvisit } daforall - images { omvisit } daforall - % Visit FontFile streams. We don't try to visit them in - % reference order. - fontfiles { omvisit } daforall - pop - } visited end - % Stack: pageobj# obj#s_larray - [ 3 1 roll { - 2 copy eq { pop } { exch } ifelse - } lforall counttomark 1 roll ] - PDFOPTDEBUG { - (%Objects = ) print dup === flush - } if -} bind def - -% Identify the objects of the first page. -/identifyFirstPageObjects { % - identifyFirstPageObjects - Trailer /Root oget null - 1 index /PageMode knownoget { - /UseOutlines eq { - 1 index /Outlines knownoget { exch pop } if - } if - } if exch pop - 1 identifyPageObjects -} bind def - -% Identify the non-shared objects of the other pages, and the shared objects. -% Note that the page objects themselves may appear to be shared, because of -% references from Dest entries in annotations, but they must be treated as -% non-shared. Note also that some objects referenced on the first page may -% also be referenced from other pages. -/identifyOtherPageObjects { % - identifyOtherPageObjects [ ...] - % - 4 dict begin - /marks lstring Objects llength lgrowto def - % Collect objects of other pages and identify sharing. - [ 2 1 pdfpagecount { null exch identifyPageObjects } for ] - dup { - { marks exch 2 copy lget 1 add 254 .min lput } forall - } forall - % Mark document-level and first page objects. - CatalogNs { marks exch 255 lput } lforall - FirstPageNs { marks exch 255 lput } forall - % Mark the page objects themselves as non-shared. - dup { - 0 get marks exch 1 lput - } forall - % Collect the non-shared objects of each page. - dup - [ exch { - [ exch { - marks 1 index lget 1 ne { pop } if - } forall ] - } forall ] - % Collect the shared objects of each page. - exch - [ exch { - [ exch { - marks 1 index lget dup 1 le exch 255 eq or { pop } if - } forall ] - } forall ] - - % Collect the shared objects. - [ 1 1 marks llength 1 sub { - marks 1 index lget dup 1 le exch 255 eq or { pop } if - } for ] - - end -} bind def - -% Identify objects not associated with any page. -/identifyNonPageObjects { % - identifyNonPageObjects - 4 dict begin - /marks lstring Objects llength lgrowto def - - LPDictN marks exch 1 lput - PHSN marks exch 1 lput - CatalogNs { marks exch 1 lput } lforall - FirstPageNs { marks exch 1 lput } forall - SharedNs { marks exch 1 lput } forall - OtherPageNs { { marks exch 1 lput } forall } forall - - %****** PUT THESE IN A REASONABLE ORDER ****** - /npobj larray - 0 - 1 1 Objects llength 1 sub { - marks 1 index lget 0 eq { - Generations exch lget 0 ne { 1 add } if - } { - pop - } ifelse - } for - lgrowto def - - 0 - 1 1 Objects llength 1 sub { - marks 1 index lget 0 eq { - % i - Generations 1 index lget 0 ne { - % i - npobj 2 index % i nobj 0 - 3 -1 roll % nobj 0 i - lput 1 add - } { - pop - } ifelse - } { - pop - } ifelse - } for - pop - - npobj - end -} bind def - -% ---------------- Assign object numbers ---------------- % - -% Assign object numbers to all objects that will be copied. -% Return the first (translated) object number in the First Page xref table. -/assignObjectNumbers { % - assignObjectNumbers - - OtherPageNs { { omap pop } forall } forall - SharedNs { omap pop } forall - NonPageNs { omap pop } lforall - % Assign object numbers for the First Page xref table last. - LPDictN omap % don't pop, this is the return value - CatalogNs { omap pop } lforall - FirstPageNs { omap pop } forall - PHSN omap pop -} bind def - -% ---------------- Create the LPDict ---------------- % - -% Create the contents of the LPDict. -/createLPDict { % - % createLPDict - - LPDict - dup /Linearized 1 put - dup /L 4 -1 roll put % filelength - dup /T 4 -1 roll put % xref0start - dup /E 4 -1 roll put % firstpageend - dup /H 5 -2 roll 1 index sub 2 array astore put % phsstart, end-start - dup /O 1 pdffindpageref 0 get omap put - /N pdfpagecount put -} bind def - -% ---------------- Adjust object positions ---------------- % - -/adjustObjectPositions { % - % adjustObjectPositions - - % Objects fall into 4 categories: LPDict, PHS, Catalog, and others. - % We handle the first two as special cases. - XRef { - % Stack: bdy below above key loc - dup 5 index ge { 2 } { 3 } ifelse index add - XRef 3 1 roll ld_put - } ld_forall pop pop pop - XRef LPDictN omap HeaderLength ld_put - XRef PHSN omap PHSStart ld_put -} bind def - -% ---------------- Write the output file ---------------- % - -% Write objects identified by object number. -/writeobjn { % writeobjn - - Generations 1 index lget pdfwriteobj -} bind def -/writeobjns { % writeobjns - - { writeobjn } forall -} bind def -/lwriteobjns { % writeobjns - - { writeobjn } lforall -} bind def - -% Write a part of the output file. -/writePart { %