summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xMaster/texmf-dist/scripts/tlgs/gswin32/eps2eps.tlu116
-rwxr-xr-xMaster/texmf-dist/scripts/tlgs/gswin32/pdf2dsc.tlu32
-rwxr-xr-xMaster/texmf-dist/scripts/tlgs/gswin32/pdfopt.tlu147
-rwxr-xr-xMaster/texmf-dist/scripts/tlgs/gswin32/ps2ascii.tlu140
-rwxr-xr-xMaster/texmf-dist/scripts/tlgs/gswin32/ps2pdf.tlu163
-rwxr-xr-xMaster/texmf-dist/scripts/tlgs/gswin32/ps2pdf12.tlu163
-rwxr-xr-xMaster/texmf-dist/scripts/tlgs/gswin32/ps2pdf13.tlu163
-rwxr-xr-xMaster/texmf-dist/scripts/tlgs/gswin32/ps2pdf14.tlu163
-rwxr-xr-xMaster/texmf-dist/scripts/tlgs/gswin32/ps2ps.tlu117
-rwxr-xr-xMaster/texmf-dist/scripts/tlgs/gswin32/ps2ps2.tlu79
-rw-r--r--Master/tlpkg/tlgs/lib/pdfopt.ps1272
11 files changed, 860 insertions, 1695 deletions
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] <inputfile> <outputfile>\n'..
+ ' <inputfile> 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] <inputfile> <outputfile>\n\n'..
+ ' <inputfile> can be either a PS, EPS, or PDF file.\n'..
+ ' A single hyphen (-) denotes stdin.\n\n'..
+ ' <outputfile> is required if <inputfile> 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] <inputfile> <outputfile>\n\n'..
+ ' <inputfile> can be either a PS, EPS, or PDF file.\n'..
+ ' A single hyphen (-) denotes stdin.\n\n'..
+ ' <outputfile> is required if <inputfile> 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] <inputfile> <outputfile>\n\n'..
+ ' <inputfile> can be either a PS, EPS, or PDF file.\n'..
+ ' A single hyphen (-) denotes stdin.\n\n'..
+ ' <outputfile> is required if <inputfile> 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] <inputfile> <outputfile>\n\n'..
+ ' <inputfile> can be either a PS, EPS, or PDF file.\n'..
+ ' A single hyphen (-) denotes stdin.\n\n'..
+ ' <outputfile> is required if <inputfile> 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] <inputfile> <outputfile>\n\n'..
+ ' <inputfile> can be either a PS, EPS, or PDF file.\n'..
+ ' A single hyphen (-) denotes stdin.\n\n'..
+ ' <outputfile> is required if <inputfile> 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] <inputfile> <outputfile>\n\n'..
+ ' <inputfile> 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 { % <obj> <dictproc> <arrayproc> <otherproc> 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 { % <size> darray <darray>
- dict
-} bind def
-/dadd { % <darray> <value> dadd -
- 1 index length exch put
-} bind def
-/daforall { % <darray> <proc> 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 { % <darray> dacontents <array>
- [ exch { } daforall ]
-} bind def
-/dacontstring { % <darray> dacontstring <string>
- 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 { % <obj> omforce <obj'> <notseen>
- dup oforce 2 copy eq { pop true } { exch 0 get omapnew exch pop } ifelse
-} bind def
-/omforce { % <obj> omforce <obj'>
- omforcenew pop
-} bind def
-/omget { % <dict|array> <key> omget <obj>
- get omforce
-} bind def
-% Visit an entire tree.
-/omvisit { % <obj> 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 { % <obj> 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 <obj#s>
- 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 { % <proc> visited <obj#s>
- 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 { % <data> <proc> <endproc> clostream <stream>
- 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 { % <stream> closend <result>
- dup closefile clostreams exch
- 2 copy get 3 1 roll undef aload pop exec
-} bind def
-
-% Implement in-memory output streams.
-/msproc { % <data> <more> <accum> msproc <scratch>
- 3 -1 roll dadd { 100 string } { () } ifelse
-} bind def
-/mstream { % - mstream <mstream>
- 10 darray {msproc} {dacontstring} clostream
-} bind def
-/mcontents { % <mstream> mcontents <string>
- 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 { % <data> <more> <accum> posproc <scratch>
- 0 2 copy get 5 -1 roll length add put
- pop //posbuf
-} bind def
-/postream { % - postream <postream>
- [0] {posproc} {0 get} clostream
-} bind def
-/poslength { % <postream> poslength <pos>
- closend
-} bind def
-
-% Implement streams with variable-bit-width data.
-% Note that these are dictionary objects, not stream objects.
-/bitstream { % <stream> bitstream <bstream>
- 4 dict begin /S exch def /N 8 def /B 0 def
- currentdict end
-} bind def
-/bitwrite { % <bstream> <value> <width> 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 { % <bstream> bitflush -
- begin N 8 ne { S B write /B 0 def /N 8 def } if end
-} bind def
-
-/bwn { % <value> <width> 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 { % <proc> totemp <start> <end>
- TFile fileposition OFile
- /OFile TFile def 3 .execn
- /OFile exch def
- TFile fileposition
-} bind def
-/tomemory { % <proc> tomemory <string>
- OFile /OFile mstream def 2 .execn
- OFile mcontents exch /OFile exch def
-} bind def
-/tolength { % <proc> tolength <string>
- OFile /OFile postream def 2 .execn
- OFile poslength exch /OFile exch def
-} bind def
-
-% Copy a range of bytes from TFile to OFile.
-/copyrange { % <start> <end> 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 { % <pos> 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 { % <object> 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? { % <value> replaceable? <bool>
- dup type /integertype eq exch xcheck not and
-} bind def
-/replacement { % <obj|ref> replacement <obj'>
- dup oforce dup replaceable? { exch } if pop
-} bind def
-
-/replacerefs { % <object> replacerefs <object>
- {
- 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 { % [<obj>...] createObjects <firstobj#>
- 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 { % <fromdict> <todict> 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 { % <fromdict> <todict> mergeattrs <fromdict> <todict>
- % 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 { % <attrs> <subtree> 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 <obj#s>
- {
- 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 { % <fontref> 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 { % <extra> <page#> identifyPageObjects <obj#s>
- 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 <obj#s>
- 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 [<pageobj#s> ...]
- % <sharedobj#s>
- 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 <obj#s>
- 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 { % <phsstart> <phsend> <firstpageend>
- % <xref0start> <filelength> 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 { % <boundary> <deltabelow> <deltaabove>
- % 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 { % <obj#> writeobjn -
- Generations 1 index lget pdfwriteobj
-} bind def
-/writeobjns { % <obj#s> writeobjns -
- { writeobjn } forall
-} bind def
-/lwriteobjns { % <obj#s> writeobjns -
- { writeobjn } lforall
-} bind def
-
-% Write a part of the output file.
-/writePart { % <proc> <label> writePart -
- PDFOPTDEBUG {
- dup print ( count=) print count =only ( start=) print
- OFile { .fileposition } stopped { pop (???) } if =
- 2 .execn
- print ( end=) print
- OFile { .fileposition } stopped { pop (???) } if =
- } {
- pop exec
- } ifelse
-} bind def
-
-% Write the header.
-/writePart1 { % - writePart1 -
- {
- pdfwriteheader
- } (part1) writePart
-} bind def
-
-% Write the linearization parameters dictionary.
-/writePart2 { % - writePart2 -
- {
- LPDictN writeobjn
- } (part2) writePart
-} bind def
-
-% Write the First Page xref table and trailer.
-% Free variables: FirstPageXN.
-/writePart3 { % <xrefstart> writePart3 -
- {
- FirstPageXN NObjects 1 add 1 index sub pdfwritexref
- Trailer dup length 1 add dict copy Trailer xcheck { cvx } if
- dup /Size NObjects 1 add put
- dup /Prev 4 -1 roll put
- pdfwritetrailer
- 0 pdfwritestartxref
- } (part3) writePart
-} bind def
-
-% Write the Catalog and other required document-level objects.
-% Free variables: CatalogNs.
-/writePart4 { % - writePart4 -
- {
- CatalogNs lwriteobjns
- } (part4) writePart
-} bind def
-
-% Write the Primary Hint Stream.
-/writePart5 { % - writePart5 -
- {
- PHSN writeobjn
- } (part5) writePart
-} bind def
-
-% Write the First Page's objects.
-% Free variables: FirstPageNs.
-/writePart6 { % - writePart6 -
- {
- FirstPageNs writeobjns
- } (part6) writePart
-} bind def
-
-% Write the objects of other pages (Page + non-shared objects).
-% Free variables: OtherPageNs.
-/writePart7 { % - writePart7 <lengths>
- {
- [ OtherPageNs {
- OFile fileposition exch
- writeobjns OFile fileposition exch sub
- } forall ]
- } (part7) writePart
-} bind def
-
-% Write the shared objects of other pages.
-% Free variables: SharedNs.
-/writePart8 { % - writePart8 -
- {
- SharedNs writeobjns
- } (part8) writePart
-} bind def
-
-% Write the other objects not associated with pages.
-% Free variables: NonPageNs.
-/writePart9 { % - writePart9 -
- {
- NonPageNs { writeobjn } lforall
- } (part9) writePart
-} bind def
-
-% Write the main xref table and trailer.
-% Free variables: FirstPageXN.
-/writePart11xref { % writePart11 -
- {
- 0 FirstPageXN pdfwritexref
- } (part11xref) writePart
-} bind def
-/writePart11rest { % <part3start> writePart11rest -
- {
- << /Size FirstPageXN >> pdfwritetrailer
- pdfwritestartxref
- } (part11rest) writePart
-} bind def
-
-% ---------------- Write hint tables ---------------- %
-
-/bitsneeded { % <maxvalue> bitsneeded <#bits>
- 0 exch { dup 0 eq { pop exit } if exch 1 add exch 2 idiv } loop
-} bind def
-
-% Find the start and end of objects in the output.
-/omstart { % <obj#> omstart <pos>
- PDFOPTDEBUG { (start\() print dup =only } if
- omap
- PDFOPTDEBUG { (=>) print dup =only } if
- XRef exch ld_get
- PDFOPTDEBUG { (\) = ) print dup = } if
-} bind def
-/omend { % <obj#> omend <pos>
- % The end of an object is the start of the next object.
- % The caller must be sure that this object is not the last one
- % in part 9.
- PDFOPTDEBUG { (end\() print dup =only } if
- omap
- PDFOPTDEBUG { (=>) print dup =only } if
- 1 add
- % Check that the requested object wasn't the last one in part 6:
- % the next object in the output file is the first in part 7.
- PHSN omap 1 index eq { pop 1 } if
- XRef exch ld_get
- PDFOPTDEBUG { (\) = ) print dup = } if
-} bind def
-/omlength { % <obj#> omlength <length>
- dup omend exch omstart sub
-} bind def
-
-% Find the Contents of a page.
-/contentsobjects { % <pagedict> contentsobjects <firstobj#> <lastobj#> true
- % <pagedict> contentsobjects false
- /Contents .knownget {
- dup oforce % ref []
- dup type /dicttype eq {
- pop 0 get dup true % ref ref
- } {
- exch pop % []
- dup length 0 ne {
- dup 0 get 0 get % [] 1st
- exch dup % 1st [] []
- length 1 sub get 0 get % 1st last
- true
- } {
- pop false
- } ifelse
- } ifelse
- } {
- false
- } ifelse
-} bind def
-
-/contentsstart { % <pagedict> contentsstart <pos> true
- % <pagedict> contentsstart false
- contentsobjects { pop omstart true } { false } ifelse
-} bind def
-
-/contentslength { % <pagedict> contentslength <length>
- contentsobjects { omend exch omstart sub } { 0 } ifelse
-} bind def
-
-/writePageOffsetHints {
- PDFOPTDEBUG { /writePageOffsetHints == } if
- 20 dict begin
- /bits OFile bitstream def
-
- % Calculate least length of a page.
- FirstPageLength OtherPageLengths { .min } forall
- /minpl exch def
-
- % Calculate least contents length.
- FirstPageNs 0 get Objects exch lget contentslength
- OtherPageNs { 0 get Objects exch lget contentslength .min } forall
- /mincl exch def
-
- % The Adobe documentation says that all versions of Acrobat
- % require item 8 (mincl) to be zero. Patch this here.
- /mincl 0 def
-
- % Calculate bits needed to represent greatest page length.
- FirstPageLength OtherPageLengths { .max } forall
- minpl sub bitsneeded /maxplbits exch def
- % Calculate bits needed to represent the greatest Contents length.
- FirstPageNs 0 get Objects exch lget contentslength
- OtherPageNs { 0 get Objects exch lget contentslength .max } forall
- mincl sub bitsneeded /maxclbits exch def
-
- % Per Adobe documentation, Acrobat requires that item 5 (maxplbits)
- % be equal to item 9 (maxclbits). Set both to the max of the two.
- maxplbits maxclbits .max /maxplbits 1 index def /maxclbits exch def
-
- % Mapping from object number to shared object reference
- /shared_id_dict FirstPageNs length SharedNs length add dict begin
- 0 FirstPageNs { 1 index def 1 add } forall
- SharedNs { 1 index def 1 add } forall
- pop
- currentdict end def
-
- % Table F.3 Page offset hint table, header section
-
- % 1: Least number of objects in a page:
- FirstPageNs length OtherPageNs { length .min } forall
- /minnop 1 index def 32 bwn
- % 2: Location of first page's Page object:
- FirstPageNs 0 get omap XRef exch ld_get 32 bwn
- % 3: Bits needed to represent greatest # of objects in a page:
- FirstPageNs length OtherPageNs { length .max } forall
- minnop sub bitsneeded /maxnopbits 1 index def 16 bwn
- % 4: Least length of a page:
- minpl 32 bwn
- % 5: Bits needed to represent the greatest page length:
- maxplbits 16 bwn
- % 6: Least start of Contents offset:
- 0 % (Acrobat requires that this be 0.)
- /minsco 1 index def 32 bwn
- % 7: Bits needed to represent the greatest start of Contents
- % offset:
- 0 % (Acrobat ignores this.)
- /maxscobits 1 index def 16 bwn
- % 8: Least contents length:
- mincl 32 bwn
- % 9: Bits needed to represent the greatest Contents length:
- maxclbits 16 bwn
- % 10: Bits needed to represent the greatest number of Shared
- % Object references:
- FirstPageNs length SharedPageNs { length .max } forall bitsneeded
- /maxsorbits 1 index def 16 bwn
- % 11: Bits needed to identify a Shared Object:
- FirstPageNs length SharedNs length add bitsneeded
- /sobits 1 index def 16 bwn
- % 12: Bits needed to represent numerator of fraction:
- 2
- /numfbits 1 index def 16 bwn
- % 13: Denominator of fraction:
- 1
- /denf 1 index def 16 bwn
-
- % Table F.4 Page offset hint table, per-page entry
-
- % 1: Number of objects in pages:
- FirstPageNs length minnop sub maxnopbits bwn
- OtherPageNs {
- length minnop sub maxnopbits bwn
- } forall
- bits bitflush
-
- % 2: Total length of pages in bytes;
- FirstPageLength minpl sub maxplbits bwn
- OtherPageLengths {
- minpl sub maxplbits bwn
- } forall
- bits bitflush
-
- % 3: Number of shared objects referenced from page:
- FirstPageNs length maxsorbits bwn
- SharedPageNs { length maxsorbits bwn } forall
- bits bitflush
- % 4: A shared object identifier:
- FirstPageNs { shared_id_dict exch get sobits bwn } forall
- SharedPageNs {
- { shared_id_dict exch get sobits bwn
- } forall
- } forall
- bits bitflush
-
- % 5: Numerator of fractional position for each shared object:
- FirstPageNs { pop 0 numfbits bwn } forall
- SharedPageNs {
- { pop 0 numfbits bwn
- } forall
- } forall
- bits bitflush
-
- % 6: Contents offsets:
- % Following Implementation Note 133 section 6 is empty.
- maxscobits 0 gt {
- [FirstPageNs OtherPageNs aload pop] {
- 0 get Objects exch lget contentsstart { minsco sub } { 0 } ifelse
- maxscobits bwn
- } forall
- bits bitflush
- } if
-
- % 7: Contents lengths:
- [FirstPageNs OtherPageNs aload pop] {
- 0 get Objects exch lget contentslength mincl sub maxclbits bwn
- } forall
- bits bitflush
-
- end
-
-} bind def
-
-/writeSharedObjectHints {
- PDFOPTDEBUG { /writeSharedObjectHints == } if
- 20 dict begin
- /bits OFile bitstream def
- /obj_count SharedNs length FirstPageNs length add def
-
- % Table F.5 Shared object hint table, header section
-
- % 1: Object number of first object in Shared Objects section
- 0 32 bwn
- % 2: Location of first object in Shared Objects section:
- % If there are no shared objects,
- % Acrobat sets this to the location of linearization
- % parameters object (the very first object).
- { pdfwriteheader } tomemory length 32 bwn
- % 3: Number of Shared Object entries for first page:
- FirstPageNs length 32 bwn
- % 4: Number of Shared Object entries for Shared Objects
- % section
- obj_count 32 bwn
- % 5: Bits needed to represent the greatest number of objects
- % in a shared object group (always 0, because all groups
- % have only 1 object):
- 0 16 bwn
- % 6: Least length of a Shared Object Group in bytes:
- 16#7fffffff FirstPageNs { omlength .min } forall
- SharedNs { omlength .min } forall
- /minsol 1 index def 32 bwn
- % 7: Bits needed to represent the greatest length of a
- % Shared Object Group:
- 0 FirstPageNs { omlength .max } forall
- SharedNs { omlength .max } forall
- minsol sub bitsneeded
- /maxsolbits 1 index def 16 bwn
-
- % Table F.6 Shared object hint table, shared object group entry
-
- % 1: Lengths of shared object groups:
- FirstPageNs { omlength minsol sub maxsolbits bwn } forall
- SharedNs { omlength minsol sub maxsolbits bwn } forall
- bits bitflush
- % 2: MD5 flag:
- obj_count { 0 1 bwn } repeat
- bits bitflush
- % 3: No MD5 shared object signatures.
-
- % 4: No number_number_of_objects_in_the_group - 1
- end
-} bind def
-
-% ---------------- Main program ---------------- %
-
-/pdfOptimize { % <infile> <outfile> pdfOptimize -
- realtime 3 1 roll
- exch pdfdict begin pdfopenfile dup begin
- 40 dict begin
- /IDict exch def
- /OFile exch def
- % Disable check for the max object number because pdfopt adds new objects.
- /NumObjects 16#7fffffff store
- /starttime exch def
- /ToWrite 100 dict def
- /now {
- QUIET { pop } { print (, t = ) print realtime starttime sub = flush } ifelse
- } def
- omapinit
-
- % Create and open a temporary file.
- % Because of .setsafe, we have to open it as read-write, rather than
- % opening for writing, then closing it and reopening it for reading.
-
- null (w+) .tempfile /TFile exch def /TFileName exch def
- .setsafe
-
- % Read all objects into memory.
-
- Trailer touch
- (Read objects) now
-
- % Encrypted files are not yet supported.
- Trailer /Encrypt known {
- (ERROR: Encrypted files are not yet supported.) = flush
- /pdfOptimize cvx /limitcheck signalerror
- } if
-
- % Replace indirect references to numbers. This is needed
- % for the Length of streams, and doesn't hurt anything else.
-
- replaceReferences
- (Replaced references) now
-
- % Create the two new objects: the linearization parameter
- % dictionary, and the Primary Hint Stream.
-
- /LPDict 10 dict def
- /PHS 10 dict cvx def % executable = stream
- [LPDict PHS] createObjects
- /LPDictN 1 index def 1 add
- /PHSN exch def
- PDFOPTDEBUG { << /LPDictN LPDictN /PHSN PHSN >> === } if
-
- % Count the number of objects in the output.
-
- 0 0 1 Objects llength 1 sub {
- Generations exch lget 0 ne { 1 add } if
- } for
- /NObjects exch def
- QUIET not { NObjects =only ( objects total) = flush } if
-
- % Propagate inherited attributes down the page tree.
-
- propagateAttributes
- (Propagated attributes) now
-
- % Identify the document-level objects (part 4).
-
- identifyDocumentObjects /CatalogNs exch def
- QUIET not { CatalogNs === flush } if
- (Identified Catalog) now
-
- % Identify the first page's objects (part 6),
- % including the Outlines tree if appropriate.
-
- pdfopencache
- /FirstPageNs identifyFirstPageObjects def
- QUIET not { FirstPageNs === flush } if
- (Identified first page) now
-
- % Identify shared vs. non-shared objects for remaining pages
- % (parts 7 and 8).
-
- identifyOtherPageObjects
- /SharedNs exch def
- /SharedPageNs exch def
- /OtherPageNs exch def
- QUIET not { OtherPageNs === flush SharedNs === flush } if
- (Identified other pages) now
-
- % Identify objects not associated with any page (part 9).
-
- /NonPageNs identifyNonPageObjects def
- QUIET not { NonPageNs { === } forall flush } if
- (Identified non-pages) now
-
- % Assign final object numbers to all the objects.
- % (The omap is currently empty.)
-
- /FirstPageXN assignObjectNumbers def
- (Assigned objects #s) now
-
- % Write the document-level objects (part 4).
-
- { writePart4 } totemp
- /CatalogTempEnd exch def /CatalogTempStart exch def
- (Wrote Catalog) now
-
- % Write the first page's objects (part 6).
-
- { writePart6 } totemp
- /FirstPageTempEnd exch def /FirstPageTempStart exch def
- (Wrote first page) now
-
- % Write the non-shared objects for other pages (part 7).
-
- { writePart7 /OtherPageLengths exch def } totemp
- /OtherPageTempEnd exch def /OtherPageTempStart exch def
- (Wrote other pages) now
-
- % Write the shared objects for other pages (part 8).
-
- { writePart8 } totemp
- /SharedTempEnd exch def /SharedTempStart exch def
- (Wrote shared objects) now
-
- % Write the objects not associated with pages (part 9).
-
- { writePart9 } totemp
- /NonPageTempEnd exch def /NonPageTempStart exch def
-
- % Compute conservative lengths of parts 2,3,5,11 of the output.
- % It's OK for these to be too large, but not too small.
-
- % Make dummy XRef entres for LPDict and PHS.
- XRef LPDictN omap 0 ld_put
- XRef PHSN omap 0 ld_put
-
- /HeaderLength { % this is exact
- writePart1 % part 1
- } tolength def
- /CatalogLength % this is exact
- CatalogTempEnd CatalogTempStart sub def % part 4
- /FirstPageLength % this is exact
- FirstPageTempEnd FirstPageTempStart sub def % part 6
- /OtherObjectsLength % this is exact
- NonPageTempEnd OtherPageTempStart sub def % parts 7,8,9
- /ObjectsLength % this is exact
- CatalogLength FirstPageLength add OtherObjectsLength add def
- /XrefLength { % part 11
- % The LPDict must end within the first 1024 bytes,
- % so the start of the FirstPage xref table can't exceed 1024.
- writePart11xref 1024 writePart11rest
- } tolength def
- /NominalFileLength % Make a generous allowance for parts 2,3,5.
- HeaderLength ObjectsLength 3 mul add 10000 add 99999 .max def
- /FirstPageXrefLength { % part 3
- NominalFileLength writePart3
- } tolength def
- /LPDictLength { % part 2
- NominalFileLength dup 2 mul 2 copy add 1 index dup createLPDict writePart2
- } tolength def
-
- % Compute a few additional values from the above.
-
- /XrefBeginLength {
- (xref\n0 ) ows
- OFile FirstPageXN write=
- } tolength def
- HeaderLength LPDictLength add
- /FirstPageXrefStart 1 index def
- FirstPageXrefLength add
- /CatalogStart 1 index def
- CatalogLength add % phsstart
- /PHSStart exch def
-
- % Adjust the object positions ignoring PHS.
- % (Writing the PHS needs these.)
-
- 0 0 CatalogStart CatalogTempStart sub adjustObjectPositions
- % Make a temporary XRef entry for the PHS, for the benefit of omend.
- XRef PHSN omap CatalogStart ld_put
- (Adjusted positions) now
-
- % Construct the hint tables (part 5).
-
- { writePageOffsetHints } totemp
- pop /PHSTempStart exch def
- { writeSharedObjectHints } totemp
- exch PHSTempStart sub PHS /S 3 -1 roll put
- PHSTempStart sub /PHSTempLength exch def
- (Wrote hints) now
-
- % Prepare to read TFile.
-% TFile closefile
-% /TFile TFileName (r) file def
-
- PHS
- dup /File TFile put
- dup /FilePosition PHSTempStart put
- dup /Length PHSTempLength put
- pop
- /PHSLength { writePart5 } tolength def
-
- % Construct the linearization parameter dictionary (part 2).
-
- PHSStart
- dup PHSLength add % phsend
- /FirstPageStart 1 index def
- dup FirstPageLength add % firstpageend
- dup OtherObjectsLength add
- /XrefStart 1 index def
- XrefBeginLength add % xref0start
- dup XrefBeginLength sub XrefLength add % fileend
- % Because of a bug, Acrobat Reader doesn't recognize any file
- % shorter than 1K as linearized. Patch this here.
- % Acrobat 9 insists on 4KB
- 4096 .max
- /FileLength 1 index def
- createLPDict
-
- % Adjust the object positions again, taking the PHS into account.
-
- PHSStart 0 PHSLength adjustObjectPositions
- (Readjusted positions) now
-
- % Finally, write the output file.
-
- writePart1
- writePart2
- FirstPageXrefStart padto
- XrefStart writePart3
- CatalogStart padto
- CatalogTempStart CatalogTempEnd copyrange % part 4
- writePart5
- FirstPageStart padto
- FirstPageTempStart NonPageTempEnd copyrange % parts 6,7,8,9
- % No Overflow Hint Stream (part 10).
- XrefStart padto
- writePart11xref
- { FirstPageXrefStart writePart11rest } tomemory
- FileLength 1 index length sub padto ows
- (Wrote output file) now
-
- % Wrap up.
-
- TFile closefile TFileName deletefile
- end % temporary dict
- end % IDict
-} bind def
-
-end % pdfoptdict
-.setglobal
-
-% Check for command line arguments.
-[ shellarguments {
- ] dup length 2 eq {
- % Load the pdfwrite utilities if necessary.
- /omapinit where { pop } { (pdfwrite.ps) runlibfile } ifelse
- save exch
- aload pop exch (r) file exch (w) file
- 3000000 setvmthreshold
- 0 setobjectformat
- pdfoptdict begin pdfOptimize end
- restore
- } {
- (Usage: gs -dNODISPLAY -- pdfopt.ps input.pdf output.pdf) = flush quit
- } ifelse
-} {
- pop
-} ifelse