summaryrefslogtreecommitdiff
path: root/Master/texmf-dist
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r--Master/texmf-dist/doc/epspdf/COPYING339
-rw-r--r--Master/texmf-dist/doc/epspdf/default.css56
-rw-r--r--Master/texmf-dist/doc/epspdf/epspdf.install285
-rw-r--r--Master/texmf-dist/doc/epspdf/epspdf_UG.html185
-rw-r--r--Master/texmf-dist/doc/epspdf/images/config_mac.pngbin0 -> 27971 bytes
-rw-r--r--Master/texmf-dist/doc/epspdf/images/dia_save.pngbin0 -> 29314 bytes
-rw-r--r--Master/texmf-dist/doc/epspdf/images/greenbroccoli.pngbin0 -> 71686 bytes
-rw-r--r--Master/texmf-dist/doc/epspdf/images/main_w32.pngbin0 -> 6111 bytes
-rw-r--r--Master/texmf-dist/doc/epspdf/index.html312
-rwxr-xr-xMaster/texmf-dist/scripts/epspdf/epspdf3
-rw-r--r--Master/texmf-dist/scripts/epspdf/epspdf.help155
-rwxr-xr-xMaster/texmf-dist/scripts/epspdf/epspdf.rb1123
-rw-r--r--Master/texmf-dist/scripts/epspdf/epspdfboot.rb40
-rwxr-xr-xMaster/texmf-dist/scripts/epspdf/epspdfrc.rb507
-rwxr-xr-xMaster/texmf-dist/scripts/epspdf/epspdftk7
-rwxr-xr-xMaster/texmf-dist/scripts/epspdf/epspdftk.rb958
-rw-r--r--Master/texmf-dist/scripts/epspdf/makegray.pro29
17 files changed, 3999 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/epspdf/COPYING b/Master/texmf-dist/doc/epspdf/COPYING
new file mode 100644
index 00000000000..3c69bb94fa5
--- /dev/null
+++ b/Master/texmf-dist/doc/epspdf/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Master/texmf-dist/doc/epspdf/default.css b/Master/texmf-dist/doc/epspdf/default.css
new file mode 100644
index 00000000000..0b1cdd46c3a
--- /dev/null
+++ b/Master/texmf-dist/doc/epspdf/default.css
@@ -0,0 +1,56 @@
+body {
+ color: black;
+ background-color: #ffffff;
+ margin-left: 15px;
+ margin-right: 9px;
+ font-family: serif;
+}
+h1 {
+ font-size: xx-large;
+ font-weight: bold;
+ margin-top: 12px;
+ margin-bottom: 6px;
+}
+h1.display {
+ text-align: center
+}
+h2 {
+ font-size: x-large;
+ font-weight: bold;
+ margin-top: 12px;
+ margin-bottom: 6px;
+}
+h3 {
+ font-weight: bold;
+ margin-top: 9px;
+ margin-bottom: 3px;
+}
+p {
+ margin-top: 6px;
+ margin-bottom: 3px;
+}
+p.display {
+ text-align: center
+}
+.fineprint {
+ font-size: x-small;
+}
+table {
+ border-width: 0px;
+ margin-left: 0px;
+ margin-right: 6px;
+}
+ul {
+ margin-top: 9px;
+ margin-bottom: 9px;
+}
+ul li {
+ margin-top: 3px;
+ margin-bottom: 3px;
+ margin-left: -6px
+}
+pre {
+ margin-top: 3px;
+ margin-bottom: 3px;
+ margin-left: 0px;
+} \ No newline at end of file
diff --git a/Master/texmf-dist/doc/epspdf/epspdf.install b/Master/texmf-dist/doc/epspdf/epspdf.install
new file mode 100644
index 00000000000..759cebde26e
--- /dev/null
+++ b/Master/texmf-dist/doc/epspdf/epspdf.install
@@ -0,0 +1,285 @@
+ Epspdf and epspdftk
+
+ A multiplatform GUI- and command-line converter for [e]ps and pdf.
+
+ Siep Kroonenberg,
+ siepo at cybercomm dot nl
+
+ [1]Current online version of this page
+
+Table of Contents
+
+ * [2]Features
+ * [3]Prerequisites
+ * [4]Installation
+ * [5]Preview programs
+ * [6]Files
+ * [7]Supporting software
+ * [8]Releases
+ * [9]To do
+ * [10]User Guide
+
+Features
+
+ * Distiller
+ * Works both for documents and for graphics
+ * Single-page selection
+ * Also converts from pdf back to PostScript and eps
+ * Removal of preview headers from eps files
+ * Cropping extra whitespace
+ * Grayscaling (sometimes)
+ * GUI- and command-line version
+ * GUI-configurable preferences
+ * Multiplatform: works unchanged on Windows, Unix/Linux and Mac OS X
+
+ Epspdf has been created with TeX users in mind. For them, eps and pdf are
+ the preferred graphics formats.
+
+ Ghostscript can convert PostScript to pdf. However, few people are
+ prepared to deal with the ghostscript command-line. Several command-line
+ utilities try to help out, e.g. epstopdf, a2ping, and the convert utility
+ from ImageMagick. But for most users this is still not good enough.
+
+ Epspdftk adds a GUI, with buttons to select options and with dialogs for
+ opening and saving files.
+
+ A lot more can be done if you can round-trip between PostScript and pdf.
+ Although Ghostscript can go from pdf to PostScript, pdftops does a much
+ better job. This opens several new possibilities: grayscaling and
+ computing a better boundingbox for either eps- or pdf graphics, and page
+ selection from multipage PostScript- and pdf documents. Epspdf will use
+ pdftops if it can find it, and silently does whatever back-and-forth
+ conversions are necessary.
+
+ The command-line program epspdf is written in Ruby. Epspdftk, its GUI
+ companion, in Ruby/Tk.
+
+Prerequisites
+
+ Windows with setup progrogam
+
+ Download Ghostscript and GSview from the [11]Ghostscript site. Ghostscript
+ and GSview each come with a standard Windows setup program.
+
+ You can get pdftops as part of the xpdf suite from the [12]xpdf site.
+ Download the zipfile with Windows binaries and unpack it in a location of
+ your choice. The Configure screen of epspdftk lets you browse for this
+ location. You only have to do this once. Xpdf itself is not in this zip
+ file.
+
+ The necessary Ruby components are already included in the setup program.
+
+ Windows zipfile with separately installed Ruby
+
+ For Ghostscript, GSview and the xpdf suite, see above.
+
+ You can get a [13]one-click Ruby installer from [14]Rubyforge. For Ruby
+ version 1.8.4 and later you have to download and install Tcl/Tk
+ separately, in the form of [15]ActiveTcl. If you are only interested in
+ the command-line version then you can leave out ActiveTcl.
+
+ Unix/Linux
+
+ You need Ghostscript, preferably xpdf/pdftops, Ruby (version at least 1.8)
+ and for GUI use also Ruby/Tk. These will almost certainly be available as
+ packages from your distribution.
+
+ Mac OS X
+
+ Ghostscript and xpdf are available via the [16]Fink Project, in the Text
+ section.
+
+ If you don't (want to) use Fink, you can download and install Gerben
+ Wierda's i-Installer from the [17]i-Installer Home Page and then use the
+ i-Installer to download and install the Ghostscript i-package.
+
+ There is a [18]package for the xpdf suite at
+ [19]http://users.phg-online.de/tk/MOSXS/. Or you can compile it yourself.
+ You can download the source from the [20]xpdf site. For compilation, you
+ need to have XCode installed, but nothing else, I think, at least not
+ under Tiger. You can safely omit the xpdf- and pdftoppm components if
+ configure says that they will not be compiled because of missing
+ libraries.
+
+ Ruby 1.8.2 and Ruby/Tk are part of Mac OS X Tiger. X11 needs to be
+ installed, although Ruby/Tk is not an X11 application. For earlier
+ versions of Mac OS X, you are on your own.
+
+Installation
+
+ Windows with setup program
+
+ Download the [21]epspdftk setup program. You can run it in the usual way,
+ by double-clicking. The setup program will create entries in your start
+ menu for epspdftk and for the user manual.
+
+ Windows zipfile
+
+ Download the [22]epspdf zip file, unpack it somewhere and create a
+ shortcut for epspdftk.rbw. If you plan to use the command-line version,
+ put a batchfile in a directory on your path with the line
+
+ "<path_to_ruby.exe>" "<path_to_epspdf.rb>" %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+ Epspdf[tk] has been tested with Windows 2000 and Windows XP.
+
+ Unix/Linux
+
+ Download the [23]tar.gz archive and unpack it in some directory. All files
+ should be in the same directory; that is how they find each other. If you
+ plan to use epspdf.rb from the command-line, then you may want to create a
+ shell script epspdf such as
+
+ #!/bin/sh
+ <path_to_epspdf>/epspdf.rb $*
+
+ and put it somewhere on your path.
+
+ You can do the same for epspdftk. The first command-line parameter will be
+ interpreted as startup directory for the file browser.
+
+ Mac OS X
+
+ Install as for Unix/Linux. Here, too, all files should be in the same
+ directory.
+
+ You can try to start epspdftk.rb from the dock or by doubleclicking. If
+ that doesn't work out, give the [24]epspdf.app applet a try. After
+ unpacking, move the file epspdf.app to the same directory as the .rb
+ files. The zipfile also includes this file in text format
+ (epspdf.applescript).
+
+ Epspdf mostly duplicates functionality of Preview. But having an alternate
+ conversion engine means that you can have another shot at problem files.
+
+Preview programs
+
+ Windows
+
+ Epspdftk will use the default Windows viewers for PostScript and pdf.
+ Without GSview, you probably won't be able to view PostScript files.
+
+ Unix/Linux
+
+ Supported PostScript viewers include evince, gv, ggv and kghostview. These
+ are also listed as pdf viewers. Additional pdf viewers are xpdf, gpdf and
+ acroread/Adobe Reader. If you think that I omitted a PostScript- or pdf
+ viewer, let me know and I'll probably add it in the next release.
+
+ Mac OS X
+
+ Epspdftk will always use Preview as viewer under OS X.
+
+Files
+
+ * [25]epspdf.0.2.12.tgz preferred for Unix and Mac OS X
+ * [26]epspdf.0.2.12.zip preferred for Windows
+ * [27]epspdf.0.2.12.exe Windows setup program, including Ruby/Tk subset
+ * [28]epspdf_app.0.2.01.zip Mac OS X applet for starting epspdftk.rb
+
+ Older releases
+
+ * [29]epspdf.0.2.11.tgz for Unix and Mac OS X
+ * [30]epspdf.0.2.11.zip for Windows
+ * [31]epspdf.0.2.11.exe Windows setup program
+ * [32]epspdf.0.2.01.tgz for Unix and Mac OS X
+ * [33]epspdf.0.2.01.zip for Windows
+ * [34]epspdf.0.2.exe, Windows setup program
+
+Supporting software
+
+ * [35]Ghostscript and GSview
+ * [36]XPDF
+ * [37]OS X binary for xpdf/pdftops
+ * [38]Ruby one-click installer
+ * [39]Ruby Home Page
+ * [40]ActiveTcl
+
+Releases
+
+ 0.2.12
+ Current version. Bug fixes: log rotation now works. Under Windows,
+ sometimes boundingboxes couldn't be calculated. This was caused by
+ double quotes within backquotes. This is now avoided by using
+ short filenames within backquotes. Minor changes in user guide.
+
+ 0.2.11
+ Minor fixes. Changes in documentation.
+
+ 0.2.10
+ A computed boundingbox is now expanded by one point in all
+ directions. This should prevent too-tight cropping. There is no
+ interface for changing this amount; it can only be changed by
+ hand-editing the bb_spread option in the .epspdfrc file or in the
+ HKCU\software\epspdf registry key.
+ The File Open dialog remembers the last directory visited (between
+ calls, not between program sessions).
+ Changes in documentation.
+
+ 0.2.01
+ Fixes to the Applescript applet epspdf.app for starting up
+ epspdftk under Mac OS X. It picks up the terminal search path and
+ no longer requires correct settings in
+ $HOME/.MacOSX/environment.plist.
+ Epspdf.app is now [41]packaged separately, under Mac OS X, and now
+ has an intact resource fork. It has been removed from the other
+ archives.
+
+ 0.2
+ Original release
+
+To do
+
+ * Artwork
+ * GUI for some pdftops options
+ * Proper help
+ * Support for bitmapped formats (maybe)
+
+ --------------------------------------------------------------------------
+
+ Last revised: November 20, 2006
+
+References
+
+ Visible links
+ 1. http://tex.aanhet.net/epspdf/
+ 2. http://tex.aanhet.net/epspdf/index.html#features
+ 3. http://tex.aanhet.net/epspdf/index.html#prerequisites
+ 4. http://tex.aanhet.net/epspdf/index.html#install
+ 5. http://tex.aanhet.net/epspdf/index.html#preview
+ 6. http://tex.aanhet.net/epspdf/index.html#files
+ 7. http://tex.aanhet.net/epspdf/index.html#supporting
+ 8. http://tex.aanhet.net/epspdf/index.html#releases
+ 9. http://tex.aanhet.net/epspdf/index.html#todo
+ 10. http://tex.aanhet.net/epspdf/epspdf_UG.html
+ 11. http://www.cs.wisc.edu/~ghost/
+ 12. http://www.foolabs.com/xpdf/
+ 13. http://rubyforge.org/projects/rubyinstaller/
+ 14. http://rubyforge.org/
+ 15. http://activestate.com/Products/ActiveTcl/
+ 16. http://fink.sourceforge.net/
+ 17. http://ii2.sourceforge.net/
+ 18. http://users.phg-online.de/tk/MOSXS/xpdf-tools-3.dmg
+ 19. http://users.phg-online.de/tk/MOSXS/
+ 20. http://www.foolabs.com/xpdf/
+ 21. http://tex.aanhet.net/epspdf/epspdf.0.2.12.exe
+ 22. http://tex.aanhet.net/epspdf/epspdf.0.2.12.zip
+ 23. http://tex.aanhet.net/epspdf/epspdf.0.2.12.tgz
+ 24. http://tex.aanhet.net/epspdf/epspdf_app.0.2.01.zip
+ 25. http://tex.aanhet.net/epspdf/epspdf.0.2.12.tgz
+ 26. http://tex.aanhet.net/epspdf/epspdf.0.2.12.zip
+ 27. http://tex.aanhet.net/epspdf/epspdf.0.2.12.exe
+ 28. http://tex.aanhet.net/epspdf/epspdf_app.0.2.01.zip
+ 29. http://tex.aanhet.net/epspdf/epspdf.0.2.11.tgz
+ 30. http://tex.aanhet.net/epspdf/epspdf.0.2.11.zip
+ 31. http://tex.aanhet.net/epspdf/epspdf.0.2.11.exe
+ 32. http://tex.aanhet.net/epspdf/epspdf.0.2.01.tgz
+ 33. http://tex.aanhet.net/epspdf/epspdf.0.2.01.zip
+ 34. http://tex.aanhet.net/epspdf/epspdf.0.2.exe
+ 35. http://www.cs.wisc.edu/~ghost/
+ 36. http://www.foolabs.com/xpdf/
+ 37. http://users.phg-online.de/tk/MOSXS/
+ 38. http://rubyforge.org/projects/rubyinstaller/
+ 39. http://ruby-lang.org/
+ 40. http://activestate.com/Products/ActiveTcl/
+ 41. http://tex.aanhet.net/epspdf/epspdf_app.0.2.01.zip
diff --git a/Master/texmf-dist/doc/epspdf/epspdf_UG.html b/Master/texmf-dist/doc/epspdf/epspdf_UG.html
new file mode 100644
index 00000000000..27a7d96626a
--- /dev/null
+++ b/Master/texmf-dist/doc/epspdf/epspdf_UG.html
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC
+"-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+
+<link rel="stylesheet" href="default.css" type="text/css"/>
+
+<title>Epspdf and epspdftk User Guide</title>
+
+</head><body>
+
+<h1 class="display">Epspdf and epspdftk User Guide</h1>
+
+<p class="display">A multiplatform GUI- and command-line converter
+for [e]ps and pdf.</p>
+
+<p class="display"><i>Siep Kroonenberg,<br/><tt>siepo at cybercomm
+dot nl</tt></i></p>
+
+<h2>Overview</h2>
+
+<p>Epspdftk converts files between eps, pdf and general
+PostScript. The main screen lets you open a file, select some options
+and convert the file.</p>
+
+<p>When opening a file, epspdf tries to find out file type and, in
+the case of a pdf file, the number of pages. This information is
+displayed in the box in the upper half of the screen.</p>
+
+<p class="display"><img src="images/main_w32.png" alt=""/></p>
+
+<h2>Viewing</h2>
+
+<p>The View button at the bottom of the screen calls an appropriate
+external viewer. For Windows this is determined by the default Open
+command, for OS X it is always Preview, and under Linux it is
+configurable; see below under <a href="#configure">The Configuration
+screen.</a></p>
+
+<p>The View button is grayed if epspdf thinks that there is no
+previewer for the current file.</p>
+
+<p class="display"><img src="images/greenbroccoli.png" alt=""/></p>
+
+<h2>Conversion options</h2>
+
+<p><a name="gray"><i>Grayscaling:</i></a> Simple color figures can
+be converted to grayscale. Grayscaling will fail for bitmapped data
+and for advanced color models. 'Try harder to grayscale' will handle
+a few more cases, but may take longer and still won't handle
+bitmaps.</p>
+
+<p><i>Call for assistance:</i> If a PostScript color expert is
+reading this: please have a look at makegray.pro and see whether you
+can come up with something that handles more color models.</p>
+
+<p><i>Compute tight boundingbox:</i> This option is only available
+if a single page is converted.</p>
+
+<p><i>Page selection:</i> The only possibilities are selecting a
+single page or selecting all pages. When converting to eps you are
+restricted to a single page.</p>
+
+<p>For general PostScript files, there is no quick way to determine
+the number of pages, so the program won't check beforehand whether
+you picked an existing page. If you picked a non-existent page, the
+program will abort. If you don't like that, convert the entire
+document to pdf first - which will be done behind the scenes
+anyhow.</p>
+
+<p>Specifying options such as grayscaling or page selection may
+require several roundtrips between PostScript or eps and pdf. If
+epspdf cannot use pdftops then some combinations of options will not
+be available.</p>
+
+<h2>Converting</h2>
+
+<p>The Convert and save... button calls up a file save dialog, with
+appropriate default extension. After a successful conversion, the
+result becomes the new current file, so you can judge the result by
+pressing the View button again.</p>
+
+<p class="display"><img src="images/dia_save.png" alt=""/></p>
+
+<h2><a name="configure">The configuration screen</a></h2>
+
+<p>Epspdftk also has a configuration screen. The settings here are
+preserved between sessions. Pay particular attention to 'Intended
+use' under PDF CONVERSION. Choose 'prepress' for pdfs which are
+intended for commercial printing. This option will try to embed all
+fonts, among other things. More and more often, printshops insist on
+this. With luck, Ghostscript fonts and system fonts will be used for
+fonts which were not originally embedded.</p>
+
+<p>Under Windows, this screen also lets you tell the program where
+to find pdftops.exe. Under Linux, it lets you pick PostScript- and
+pdf previewers.</p>
+
+<p class="display"><img src="images/config_mac.png" alt=""/></p>
+
+<h2>Adding standard fonts to an existing pdf</h2>
+
+<p>You can add standard fonts such as Times and Helvetica to an
+existing pdf: first, convert to ps, with 'Convert all pages'
+selected. Then, make sure that in the configuration screen 'Intended
+use' is set to prepress, then convert back to pdf.</p>
+
+<p>If this option is set to screen, then standard fonts will be
+removed instead of added. This option may also affect the resolution
+of bitmaps.</p>
+
+<h2>Eps preview headers</h2>
+
+<p>Preview headers are quietly stripped from eps files. These
+preview headers are used by e.g. desktop-publishing software to
+represent eps files on screen without having to interpret the
+PostScript code itself. Epspdf currently has no option to preserve
+or add them.</p>
+
+<h2>Exporting PostScript from Windows programs</h2>
+
+<p>Often, the only way to get EPS or PostScript from a Windows
+program is by 'printing' to a PostScript file. From some programs,
+you can print a selection. A suitable driver which comes with
+Windows is Generic / MS Publisher Imagesetter. Pay attention to the
+printer properties: avoid the 'Optimize for speed' setting and choose
+Outline for font downloading. These options can be found under the
+Advanced button.</p>
+
+<p>Other possibilities are the TpX and wmf2eps programs, which both
+have options to write clipboard contents to an emf file. Wmf2eps
+uses a printer driver in the background. For faithful conversion,
+pick wmf2eps; for subsequent editing, choose TpX. Both programs are
+availbable from <a href="http://www.tug.org/ctan.html">CTAN</a>.</p>
+
+<h2>Command-line use</h2>
+
+<p>Epspdf.rb, the library for epspdftk.rb, does double duty as
+command-line version of epspdftk.rb. Type <tt>epspdf.rb -h</tt> for
+help. It shares configuration settings with epspdftk.</p>
+
+<h2>Troubleshooting</h2>
+
+<h3>Grayscaling fails</h3>
+
+<p>See above, under <a href="#gray">Grayscaling.</a> Epspdf is
+limited by what can be done by the backend tools, i.e. Ghostscript
+and pdftops.</p>
+
+<h3>Part of the graphic gets cut off</h3>
+
+<p>I have seen this happen with eps files generated by printing
+landscape PowerPoint slides to PostScript with the Encapsulated
+PostScript output option. Using the Archive output option instead
+solved the problem. In general, experiment a bit in generating
+your PostScript.</p>
+
+<h3>Resources for troubleshooting</h3>
+
+<p><i>Logfile.</i> Epspdf and epspdftk maintain a log file
+epspdf.log in your home directory or, in case of Windows, your
+profile directory. This profile directory may be c:\Documents and
+Settings\&lt;your user name>. Otherwise, open a DOS box and type
+'<tt>echo %USERPROFILE%</tt>', which will produce this
+information.</p>
+
+<p>This logfile lists all Ghostscript- and pdftops program
+calls plus error information. 'EPCallError' is probably a program
+error. 'EPSystemError' is more likely caused by a faulty file, but
+may be a program error as well.</p>
+
+<p><i>Temporary files.</i> The temporary files may give clues as
+well. They will be deleted at the end of the session (for the
+command-line version, give a -d parameter to keep the temporary
+files). Check the logfile which temporary files have been
+created.</p>
+
+<h3><a href="index.html">Main page...</a></h3>
+
+<hr/>
+<p class="fineprint">Last revised: Noverber 20, 2006</p>
+</body></html>
diff --git a/Master/texmf-dist/doc/epspdf/images/config_mac.png b/Master/texmf-dist/doc/epspdf/images/config_mac.png
new file mode 100644
index 00000000000..0ad0c855509
--- /dev/null
+++ b/Master/texmf-dist/doc/epspdf/images/config_mac.png
Binary files differ
diff --git a/Master/texmf-dist/doc/epspdf/images/dia_save.png b/Master/texmf-dist/doc/epspdf/images/dia_save.png
new file mode 100644
index 00000000000..ea56dbcab0e
--- /dev/null
+++ b/Master/texmf-dist/doc/epspdf/images/dia_save.png
Binary files differ
diff --git a/Master/texmf-dist/doc/epspdf/images/greenbroccoli.png b/Master/texmf-dist/doc/epspdf/images/greenbroccoli.png
new file mode 100644
index 00000000000..64883e00d47
--- /dev/null
+++ b/Master/texmf-dist/doc/epspdf/images/greenbroccoli.png
Binary files differ
diff --git a/Master/texmf-dist/doc/epspdf/images/main_w32.png b/Master/texmf-dist/doc/epspdf/images/main_w32.png
new file mode 100644
index 00000000000..579e64f0db9
--- /dev/null
+++ b/Master/texmf-dist/doc/epspdf/images/main_w32.png
Binary files differ
diff --git a/Master/texmf-dist/doc/epspdf/index.html b/Master/texmf-dist/doc/epspdf/index.html
new file mode 100644
index 00000000000..476deff50c9
--- /dev/null
+++ b/Master/texmf-dist/doc/epspdf/index.html
@@ -0,0 +1,312 @@
+<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC
+"-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+
+<link rel="stylesheet" href="default.css" type="text/css"/>
+
+<title>Epspdf and epspdftk</title>
+
+</head><body>
+
+<h1 class="display">Epspdf and epspdftk</h1>
+
+<p class="display">A multiplatform GUI- and command-line converter
+for [e]ps and pdf.</p>
+
+<p class="display"><i>Siep Kroonenberg,<br/><tt>siepo at cybercomm
+dot nl</tt></i></p>
+
+<p><a href="http://tex.aanhet.net/epspdf/">Current online version of
+this page</a></p>
+
+<h2>Table of Contents</h2>
+
+<ul>
+<li><a href="#features">Features</a></li>
+<li><a href="#prerequisites">Prerequisites</a></li>
+<li><a href="#install">Installation</a></li>
+<li><a href="#preview">Preview programs</a></li>
+<li><a href="#files">Files</a></li>
+<li><a href="#supporting">Supporting software</a></li>
+<li><a href="#releases">Releases</a></li>
+<li><a href="#todo">To do</a></li>
+<li><a href="epspdf_UG.html">User Guide</a></li>
+</ul>
+
+<h2><a name="features"/>Features</h2>
+
+<ul>
+<li>Distiller</li>
+<li>Works both for documents and for graphics</li>
+<li>Single-page selection</li>
+<li>Also converts from pdf back to PostScript and eps</li>
+<li>Removal of preview headers from eps files</li>
+<li>Cropping extra whitespace</li>
+<li>Grayscaling (sometimes)</li>
+<li>GUI- and command-line version</li>
+<li>GUI-configurable preferences</li>
+<li>Multiplatform: works unchanged on Windows, Unix/Linux and Mac OS X</li>
+</ul>
+
+<p>Epspdf has been created with TeX users in mind. For them, eps and
+pdf are the preferred graphics formats.</p>
+
+<p>Ghostscript can convert PostScript to pdf. However, few people
+are prepared to deal with the ghostscript command-line. Several
+command-line utilities try to help out, e.g. epstopdf, a2ping, and
+the convert utility from ImageMagick. But for most users this is
+still not good enough.</p>
+
+<p>Epspdftk adds a GUI, with buttons to select options and with
+dialogs for opening and saving files.</p>
+
+<p>A lot more can be done if you can round-trip between PostScript
+and pdf. Although Ghostscript can go from pdf to PostScript, pdftops
+does a much better job. This opens several new possibilities:
+grayscaling and computing a better boundingbox for either eps- or pdf
+graphics, and page selection from multipage PostScript- and pdf
+documents. Epspdf will use pdftops if it can find it, and silently
+does whatever back-and-forth conversions are necessary.</p>
+
+<p>The command-line program epspdf is written in Ruby. Epspdftk,
+its GUI companion, in Ruby/Tk.</p>
+
+<h2><a name="prerequisites"/>Prerequisites</h2>
+
+<h3>Windows with setup progrogam</h3>
+
+<p>Download Ghostscript and GSview from the <a
+href="http://www.cs.wisc.edu/~ghost/">Ghostscript site.</a>
+Ghostscript and GSview each come with a standard Windows setup
+program.</p>
+
+<p>You can get pdftops as part of the xpdf suite from the <a
+href="http://www.foolabs.com/xpdf/">xpdf site.</a> Download the
+zipfile with Windows binaries and unpack it in a location of your
+choice. The Configure screen of epspdftk lets you browse for this
+location. You only have to do this once. Xpdf itself is not in this
+zip file.</p>
+
+<p>The necessary Ruby components are already included in the setup
+program.</p>
+
+<h3>Windows zipfile with separately installed Ruby</h3>
+
+<p>For Ghostscript, GSview and the xpdf suite, see above.</p>
+
+<p>You can get a <a
+href="http://rubyforge.org/projects/rubyinstaller/">one-click Ruby
+installer</a> from <a href="http://rubyforge.org/">Rubyforge.</a>
+For Ruby version 1.8.4 and later you have to download and install
+Tcl/Tk separately, in the form of <a
+href="http://activestate.com/Products/ActiveTcl/">ActiveTcl.</a> If
+you are only interested in the command-line version then you can
+leave out ActiveTcl.</p>
+
+<h3>Unix/Linux</h3>
+
+<p>You need Ghostscript, preferably xpdf/pdftops, Ruby (version at
+least 1.8) and for GUI use also Ruby/Tk. These will almost certainly
+be available as packages from your distribution.</p>
+
+<h3>Mac OS X</h3>
+
+<p>Ghostscript and xpdf are available via the <a
+href="http://fink.sourceforge.net/">Fink Project</a>, in the Text
+section.</p>
+
+<p>If you don't (want to) use Fink, you can download and
+install Gerben Wierda's i-Installer from the <a
+href="http://ii2.sourceforge.net/">i-Installer Home Page</a> and
+then use the i-Installer to download and install the Ghostscript
+i-package.</p>
+
+<p>There is
+a <a
+href="http://users.phg-online.de/tk/MOSXS/xpdf-tools-3.dmg">package</a>
+for the xpdf suite
+at <a
+href="http://users.phg-online.de/tk/MOSXS/">http://users.phg-online.de/tk/MOSXS/.</a>
+Or you can compile it yourself. You can download the source from
+the <a href="http://www.foolabs.com/xpdf/">xpdf site</a>. For
+compilation, you need to have XCode installed, but nothing else, I
+think, at least not under Tiger. You can safely omit the xpdf- and
+pdftoppm components if configure says that they will not be compiled
+because of missing libraries.</p>
+
+<p>Ruby 1.8.2 and Ruby/Tk are part of Mac OS X Tiger. X11 needs to
+be installed, although Ruby/Tk is <i>not</i> an X11 application. For
+earlier versions of Mac OS X, you are on your own.</p>
+
+<h2><a name="install"/>Installation</h2>
+
+<h3>Windows with setup program</h3>
+
+<p>Download the <a href="epspdf.0.2.12.exe">epspdftk setup
+program.</a> You can run it in the usual way, by double-clicking. The
+setup program will create entries in your start menu for epspdftk
+and for the user manual.</p>
+
+<h3>Windows zipfile</h3>
+
+<p>Download the <a href="epspdf.0.2.12.zip">epspdf zip file</a>,
+unpack it somewhere and create a shortcut for epspdftk.rbw. If you
+plan to use the command-line version, put a batchfile in a directory
+on your path with the line</p>
+
+<pre>
+"&lt;path_to_ruby.exe>" "&lt;path_to_epspdf.rb>" %1 %2 %3 %4 %5 %6 %7 %8 %9
+</pre>
+
+<p>Epspdf[tk] has been tested with Windows 2000 and Windows XP.</p>
+
+<h3>Unix/Linux</h3>
+
+<p>Download the <a href="epspdf.0.2.12.tgz">tar.gz archive</a> and
+unpack it in some directory. All files should be in the same
+directory; that is how they find each other. If you plan to use
+epspdf.rb from the command-line, then you may want to create a shell
+script <tt>epspdf</tt> such as</p>
+
+<pre>
+#!/bin/sh
+&lt;path_to_epspdf>/epspdf.rb $*
+</pre>
+
+<p>and put it somewhere on your path.</p>
+
+<p>You can do the same for epspdftk. The first command-line
+parameter will be interpreted as startup directory for the file
+browser.</p>
+
+<h3>Mac OS X</h3>
+
+<p>Install as for Unix/Linux. Here, too, all files should be in the
+same directory.</p>
+
+<p>You can try to start epspdftk.rb from the dock or by
+doubleclicking. If that doesn't work out, give the <a
+href="epspdf_app.0.2.01.zip">epspdf.app</a> applet a try. After
+unpacking, move the file <tt>epspdf.app</tt> to the same directory
+as the .rb files. The zipfile also includes this file in text format
+(<tt>epspdf.applescript</tt>).</p>
+
+<p>Epspdf mostly duplicates functionality of Preview. But having an
+alternate conversion engine means that you can have another shot at
+problem files.</p>
+
+<h2><a name="preview"/>Preview programs</h2>
+
+<h3>Windows</h3>
+
+<p>Epspdftk will use the default Windows viewers for PostScript and
+pdf. Without GSview, you probably won't be able to view PostScript
+files.</p>
+
+<h3>Unix/Linux</h3>
+
+<p>Supported PostScript viewers include evince, gv, ggv and
+kghostview. These are also listed as pdf viewers. Additional pdf
+viewers are xpdf, gpdf and acroread/Adobe Reader. If you think that
+I omitted a PostScript- or pdf viewer, let me know and I'll probably
+add it in the next release.</p>
+
+<h3>Mac OS X</h3>
+
+<p>Epspdftk will always use Preview as viewer under OS X.</p>
+
+<h2><a name="files"/>Files</h2>
+
+<ul>
+<li><a href="epspdf.0.2.12.tgz">epspdf.0.2.12.tgz</a> preferred for Unix
+and Mac OS X</li>
+
+<li><a href="epspdf.0.2.12.zip">epspdf.0.2.12.zip</a> preferred for
+Windows</li>
+
+<li><a href="epspdf.0.2.12.exe">epspdf.0.2.12.exe</a> Windows setup
+ program, including Ruby/Tk subset</li>
+
+<li><a href="epspdf_app.0.2.01.zip">epspdf_app.0.2.01.zip</a> Mac OS X
+applet for starting epspdftk.rb</li>
+</ul>
+
+<h3>Older releases</h3>
+<ul>
+<li><a href="epspdf.0.2.11.tgz">epspdf.0.2.11.tgz</a> for Unix
+and Mac OS X</li>
+<li><a href="epspdf.0.2.11.zip">epspdf.0.2.11.zip</a> for
+Windows</li>
+<li><a href="epspdf.0.2.11.exe">epspdf.0.2.11.exe</a> Windows setup
+ program</li>
+<li><a href="epspdf.0.2.01.tgz">epspdf.0.2.01.tgz</a> for Unix
+ and Mac OS X</li>
+<li><a href="epspdf.0.2.01.zip">epspdf.0.2.01.zip</a> for
+ Windows</li>
+<li><a href="epspdf.0.2.exe">epspdf.0.2.exe</a>, Windows setup
+ program</li>
+</ul>
+
+<h2><a name="supporting"/>Supporting software</h2>
+
+<ul>
+<li><a href="http://www.cs.wisc.edu/~ghost/">Ghostscript and
+ GSview</a></li>
+<li><a href="http://www.foolabs.com/xpdf/">XPDF</a></li>
+<li><a href="http://users.phg-online.de/tk/MOSXS/">OS X
+ binary for xpdf/pdftops</a></li>
+<li><a href="http://rubyforge.org/projects/rubyinstaller/">Ruby one-click
+ installer</a></li>
+<li><a href="http://ruby-lang.org/">Ruby Home Page</a></li>
+<li><a
+href="http://activestate.com/Products/ActiveTcl/">ActiveTcl</a></li>
+</ul>
+
+<h2><a name="releases"/>Releases</h2>
+
+<dl>
+<dt>0.2.12</dt><dd>Current version. Bug fixes: log rotation now
+works. Under Windows, sometimes boundingboxes couldn't be
+calculated. This was caused by double quotes within backquotes. This
+is now avoided by using short filenames within backquotes. Minor
+changes in user guide.</dd>
+
+<dt>0.2.11</dt><dd> Minor fixes. Changes in documentation.</dd>
+
+<dt>0.2.10</dt><dd>A computed boundingbox is now expanded by one
+point in all directions. This should prevent too-tight
+cropping. There is no interface for changing this amount; it can
+only be changed by hand-editing the bb_spread
+option in the .epspdfrc file or in the HKCU\software\epspdf registry
+key.</dd> <dd>The File Open dialog remembers the last directory
+visited (between calls, not between program
+sessions).</dd><dd>Changes in documentation.</dd>
+
+<dt>0.2.01</dt><dd>Fixes to the Applescript applet epspdf.app for
+starting up epspdftk under Mac OS X. It picks up the terminal search
+path and no longer requires correct settings in
+$HOME/.MacOSX/environment.plist.</dd><dd>Epspdf.app is now <a
+href="epspdf_app.0.2.01.zip">packaged separately</a>, under Mac OS
+X, and now has an intact resource fork. It has been removed from the
+other archives.</dd>
+
+<dt>0.2</dt><dd>Original release</dd>
+</dl>
+
+<h2><a name="todo"/>To do</h2>
+
+<ul>
+<li>Artwork</li>
+<li>GUI for some pdftops options</li>
+<li>Proper help</li>
+<li>Support for bitmapped formats (maybe)</li>
+</ul>
+
+<hr/>
+
+<p class="fineprint">Last revised: November 20, 2006</p>
+</body></html>
diff --git a/Master/texmf-dist/scripts/epspdf/epspdf b/Master/texmf-dist/scripts/epspdf/epspdf
new file mode 100755
index 00000000000..4492608f398
--- /dev/null
+++ b/Master/texmf-dist/scripts/epspdf/epspdf
@@ -0,0 +1,3 @@
+#!/bin/sh
+script=`kpsewhich -format=texmfscripts epspdf.rb`
+"$script" $*
diff --git a/Master/texmf-dist/scripts/epspdf/epspdf.help b/Master/texmf-dist/scripts/epspdf/epspdf.help
new file mode 100644
index 00000000000..90d9c795a0d
--- /dev/null
+++ b/Master/texmf-dist/scripts/epspdf/epspdf.help
@@ -0,0 +1,155 @@
+ Epspdf and epspdftk User Guide
+
+ A multiplatform GUI- and command-line converter for [e]ps and pdf.
+
+ Siep Kroonenberg,
+ siepo at cybercomm dot nl
+
+Overview
+
+ Epspdftk converts files between eps, pdf and general PostScript. The main
+ screen lets you open a file, select some options and convert the file.
+
+ When opening a file, epspdf tries to find out file type and, in the case
+ of a pdf file, the number of pages. This information is displayed in the
+ box in the upper half of the screen.
+
+Viewing
+
+ The View button at the bottom of the screen calls an appropriate external
+ viewer. For Windows this is determined by the default Open command, for OS
+ X it is always Preview, and under Linux it is configurable; see below
+ under [1]The Configuration screen.
+
+ The View button is grayed if epspdf thinks that there is no previewer for
+ the current file.
+
+Conversion options
+
+ Grayscaling: Simple color figures can be converted to grayscale.
+ Grayscaling will fail for bitmapped data and for advanced color models.
+ 'Try harder to grayscale' will handle a few more cases, but may take
+ longer and still won't handle bitmaps.
+
+ Call for assistance: If a PostScript color expert is reading this: please
+ have a look at makegray.pro and see whether you can come up with something
+ that handles more color models.
+
+ Compute tight boundingbox: This option is only available if a single page
+ is converted.
+
+ Page selection: The only possibilities are selecting a single page or
+ selecting all pages. When converting to eps you are restricted to a single
+ page.
+
+ For general PostScript files, there is no quick way to determine the
+ number of pages, so the program won't check beforehand whether you picked
+ an existing page. If you picked a non-existent page, the program will
+ abort. If you don't like that, convert the entire document to pdf first -
+ which will be done behind the scenes anyhow.
+
+ Specifying options such as grayscaling or page selection may require
+ several roundtrips between PostScript or eps and pdf. If epspdf cannot use
+ pdftops then some combinations of options will not be available.
+
+Converting
+
+ The Convert and save... button calls up a file save dialog, with
+ appropriate default extension. After a successful conversion, the result
+ becomes the new current file, so you can judge the result by pressing the
+ View button again.
+
+The configuration screen
+
+ Epspdftk also has a configuration screen. The settings here are preserved
+ between sessions. Pay particular attention to 'Intended use' under PDF
+ CONVERSION. Choose 'prepress' for pdfs which are intended for commercial
+ printing. This option will try to embed all fonts, among other things.
+ More and more often, printshops insist on this. With luck, Ghostscript
+ fonts and system fonts will be used for fonts which were not originally
+ embedded.
+
+ Under Windows, this screen also lets you tell the program where to find
+ pdftops.exe. Under Linux, it lets you pick PostScript- and pdf previewers.
+
+Adding standard fonts to an existing pdf
+
+ You can add standard fonts such as Times and Helvetica to an existing pdf:
+ first, convert to ps, with 'Convert all pages' selected. Then, make sure
+ that in the configuration screen 'Intended use' is set to prepress, then
+ convert back to pdf.
+
+ If this option is set to screen, then standard fonts will be removed
+ instead of added. This option may also affect the resolution of bitmaps.
+
+Eps preview headers
+
+ Preview headers are quietly stripped from eps files. These preview headers
+ are used by e.g. desktop-publishing software to represent eps files on
+ screen without having to interpret the PostScript code itself. Epspdf
+ currently has no option to preserve or add them.
+
+Exporting PostScript from Windows programs
+
+ Often, the only way to get EPS or PostScript from a Windows program is by
+ 'printing' to a PostScript file. From some programs, you can print a
+ selection. A suitable driver which comes with Windows is Generic / MS
+ Publisher Imagesetter. Pay attention to the printer properties: avoid the
+ 'Optimize for speed' setting and choose Outline for font downloading.
+ These options can be found under the Advanced button.
+
+ Other possibilities are the TpX and wmf2eps programs, which both have
+ options to write clipboard contents to an emf file. Wmf2eps uses a printer
+ driver in the background. For faithful conversion, pick wmf2eps; for
+ subsequent editing, choose TpX. Both programs are availbable from [2]CTAN.
+
+Command-line use
+
+ Epspdf.rb, the library for epspdftk.rb, does double duty as command-line
+ version of epspdftk.rb. Type epspdf.rb -h for help. It shares
+ configuration settings with epspdftk.
+
+Troubleshooting
+
+ Grayscaling fails
+
+ See above, under [3]Grayscaling. Epspdf is limited by what can be done by
+ the backend tools, i.e. Ghostscript and pdftops.
+
+ Part of the graphic gets cut off
+
+ I have seen this happen with eps files generated by printing landscape
+ PowerPoint slides to PostScript with the Encapsulated PostScript output
+ option. Using the Archive output option instead solved the problem. In
+ general, experiment a bit in generating your PostScript.
+
+ Resources for troubleshooting
+
+ Logfile. Epspdf and epspdftk maintain a log file epspdf.log in your home
+ directory or, in case of Windows, your profile directory. This profile
+ directory may be c:\Documents and Settings\<your user name>. Otherwise,
+ open a DOS box and type 'echo %USERPROFILE%', which will produce this
+ information.
+
+ This logfile lists all Ghostscript- and pdftops program calls plus error
+ information. 'EPCallError' is probably a program error. 'EPSystemError' is
+ more likely caused by a faulty file, but may be a program error as well.
+
+ Temporary files. The temporary files may give clues as well. They will be
+ deleted at the end of the session (for the command-line version, give a -d
+ parameter to keep the temporary files). Check the logfile which temporary
+ files have been created.
+
+ [4]Main page...
+
+ --------------------------------------------------------------------------
+
+ Last revised: Noverber 20, 2006
+
+References
+
+ Visible links
+ 1. http://tex.aanhet.net/epspdf/epspdf_UG.html#configure
+ 2. http://www.tug.org/ctan.html
+ 3. http://tex.aanhet.net/epspdf/epspdf_UG.html#gray
+ 4. http://tex.aanhet.net/epspdf/index.html
diff --git a/Master/texmf-dist/scripts/epspdf/epspdf.rb b/Master/texmf-dist/scripts/epspdf/epspdf.rb
new file mode 100755
index 00000000000..fb391b6dde6
--- /dev/null
+++ b/Master/texmf-dist/scripts/epspdf/epspdf.rb
@@ -0,0 +1,1123 @@
+#!/usr/bin/env ruby
+
+# epspdf conversion utility, main source
+
+#####
+# Copyright (C) 2006 Siep Kroonenberg
+# n dot s dot kroonenberg at rug dot nl
+#
+# This program is free software, licensed under the GNU GPL, >=2.0.
+# This software comes with absolutely NO WARRANTY. Use at your own risk!
+#####
+
+# Operations on a PostScript- or pdf file.
+# The focus is on converting between eps and pdf.
+
+# Code is organized as a set of single-step conversion methods plus an
+# any-to-any conversion.
+
+# `Target' is not a parameter; all conversions write to a new temp
+# file. Conversions can be chained: object.conversion1( params
+# ).conversion2( params ) ... The final temp file is moved or copied to
+# the desired destination by the main program (which can be epspdf
+# itself).
+
+# The use of exception handling makes it unnecessary to inspect return
+# values.
+
+# Limitation
+# HiRes boundingboxes are ignored.
+# Two reasons:
+# - they get lost anyhow on conversion to pdf
+# - They are not required so when you find one you have to make sure
+# that it doesn't refer to an included eps. This would
+# require additional logic.
+
+###########################################
+
+# some initialization in case this file is used as main program
+
+if __FILE__ == $0
+
+ # epspdfboot.rb: modify loadpath in a way which works both
+ # with a full Ruby and with a custom subset ruby
+
+ require __FILE__.sub( /epspdf\.rb/, 'epspdfboot.rb' )
+
+ # turn on warnings
+ #$VERBOSE = 1
+
+end # if main program
+
+###########################################
+
+# Error handling
+
+# internal error: method should not have been called
+# under the current conditions
+class EPCallError < StandardError; end
+
+# Can't get a valid boundingbox for an eps file
+class EPBBError < StandardError; end
+
+# system call failed
+class EPSystemError < StandardError; end
+
+###########################################
+
+# PostScript header file for grayscaling
+
+$GRAYHEAD = File.join( File.dirname( __FILE__ ), "makegray.pro" )
+
+###########################################
+
+# handle auto-detected and saved settings
+
+require 'epspdfrc'
+
+###########################################
+
+# Transient options. These will never be saved.
+# We set default values here.
+
+$options = {
+ 'type' => nil,
+ 'page' => nil,
+ 'bbox' => false,
+ 'gray' => false,
+ 'gRAY' => false,
+ 'info' => false
+}
+
+class << $options
+
+ # create shortcut methods $options.x and $options.x=
+ # for reading and writing hash elements.
+
+ $options.each_key { |k|
+ eval "def #{k} ; self[\'#{k}\'] ; end"
+ eval "def #{k}=(v) ; self[\'#{k}\']=v ; end"
+ }
+
+end # class
+
+###########################################
+
+def hash_prn( h )
+ if h.empty?
+ s = "No parameters" + $/
+ else
+ s = "Parameters were:" + $/
+ h.each_key { |k| s = s + ' ' + k.to_s + ' => ' + h[ k ].to_s + $/ }
+ end
+ s
+end
+
+###########################################
+
+require 'fileutils'
+#include FileUtils::Verbose
+include FileUtils
+
+###########################################
+
+# Mode strings for file i/o
+
+if ARCH == 'w32'
+ $W = 'wb'
+ $A = 'ab'
+ $R = 'rb'
+else
+ $W = 'w'
+ $A = 'a'
+ $R = 'r'
+end
+
+###########################################
+
+# copy a slice of a file; is there no such standard function?
+# some eps files are very large; don't slurp the file at one go.
+# Mode: can be set to append 'a' rather than write 'w'.
+
+def sliceFile( source, dest, len, offs, mode=$W )
+ buffer = ''
+ File.open( source ) do |s|
+ s.binmode if ARCH == 'w32'
+ s.seek( offs, IO::SEEK_SET )
+ if s.pos == offs
+ File.open( dest, mode ) do |d|
+ d.binmode if ARCH == 'w32'
+ tocopy = len
+ while tocopy>0 and s.read( [ tocopy, 16384 ].min, buffer )
+ tocopy = tocopy - d.write( buffer )
+ end # while
+ end # |d| (automatic closing)
+ end # if s.seek
+ end # |s| (automatic closing)
+ # return value true if anything has been copied
+ File.size?( dest ) # nil if zero-length
+end # def
+
+# write our own file copy, to bypass bug in FileUtils.cp
+
+def ccp( source, dest )
+ sliceFile( source, dest, File.size( source ), 0, $W )
+end
+
+###########################################
+
+# logging
+
+def write_log( s )
+ if test( ?e, LOGFILE ) and File.size( LOGFILE ) > 100000
+ rm( LOGFILE_OLD ) if test( ?e, LOGFILE_OLD )
+ ccp( LOGFILE, LOGFILE_OLD )
+ File.truncate( LOGFILE, 0 )
+ end
+ File.open( LOGFILE, 'a' ) { |f|
+ f.print( "#{$$} #{Time.now.strftime('%Y/%m/%d %H:%M:%S')} #{s}\n" )
+ }
+end
+
+###########################################
+
+require 'tmpdir'
+
+#$DEBUG=1
+
+# save filenames for cleanup at end
+$tempfiles = []
+
+def mktemp( ext )
+ isdone = nil
+ (0..99).each do |i|
+ fname = Dir.tmpdir + File::SEPARATOR + \
+ sprintf( '%d_%02d.%s', $$, i, ext ) # $$ is process id
+ next if test( ?e, fname )
+ File.open( fname, 'w' ) do |f|; end # creates empty file
+ isdone = 1
+ $tempfiles.unshift( fname )
+ return fname
+ end # each do |i|
+ fail StandardError, "Cannot create temp file" unless isdone
+end # def
+
+def cleantemp
+ write_log( "Cleaning tempfiles" + $/ + $tempfiles.join( $/ ) )
+ $tempfiles.each{ |tf|; rm( tf ) }
+end
+
+###########################################
+
+# identifying file type
+
+# EPS with preview starts with 0xC5D0D3C6
+# Encapsulated PostScript starts with %!PS-Adobe-n.n EPSF-n.n
+# but %!PS-Adobe-n.n will also be identified as Encapsulated PostScript
+# if the filename extension suggests it.
+# PostScript starts with %!
+# PDF starts with %PDF-version
+
+def identify( path )
+ filestart = nil
+ File.open( path, $R ) do |f|
+ filestart = f.read( 23 )
+ end # this syntax automatically closes the file at end of block
+ case filestart
+ when /^\xc5\xd0\xd3\xc6/
+ 'epsPreview'
+ when /^%!PS-Adobe-\d\.\d EPSF-\d\.\d/
+ 'eps'
+ when /^%!PS-Adobe-\d\.\d/
+ ( path =~ /\.ep(i|s|si|sf)$/i ) ? 'eps' : 'ps'
+ when /^%!/
+ 'ps'
+ when /^%PDF/
+ 'pdf'
+ else
+ 'other'
+ end # case
+end # def
+
+###########################################
+
+# Boundingboxes
+
+BB_PAT = /^\s*%%BoundingBox:\s*(-?\d+)((\s+-?\d+){3})\s*$/
+BB_END = /^\s*%%BoundingBox:\s*\(\s*atend\s*\)\s*$/
+# for multiline matching:
+BB_PAT1 = /%%BoundingBox:\s*(-?\d+)((\s+-?\d+){3})/m
+BB_END1 = /%%BoundingBox:\s*\(\s*atend\s*\)/m
+
+class Bb
+
+ attr_accessor :llx, :lly, :urx, :ury
+
+ def initialize( llx, lly, urx, ury )
+ @llx, @lly, @urx, @ury = llx, lly, urx, ury
+ [@llx, @lly, @urx, @ury].each { |l| l = l.to_i.to_s }
+ end
+
+ def Bb.from_bbcomment( s )
+ return nil unless s =~ BB_PAT
+ llx, lly, urx, ury =
+ s.sub( /^\s*%%BoundingBox:\s*/, '' ).split( /\s+/ )
+ Bb.new( llx, lly, urx, ury )
+ end
+
+ def height
+ ( @ury.to_i - @lly.to_i ).to_s
+ end
+
+ def width
+ ( @urx.to_i - @llx.to_i ).to_s
+ end
+
+ def valid
+ @llx.to_i < @urx.to_i and @lly.to_i < @ury.to_i
+ end
+
+ def non_negative
+ valid and @llx.to_i >= 0 and @lly.to_i >= 0
+ end
+
+ def copy
+ Bb.new( @llx, @lly, @urx, @ury )
+ end
+
+ def prn
+ "#{@llx} #{@lly} #{@urx} #{@ury}"
+ end
+
+ def expand
+ i = ( $settings.bb_spread ).to_i
+ return if i <= 0
+ @llx = ( [ 0, @llx.to_i - i ].max ).to_s
+ @lly = ( [ 0, @lly.to_i - i ].max ).to_s
+ @urx = ( @urx.to_i + i ).to_s
+ @ury = ( @ury.to_i + i ).to_s
+ end
+
+ ##################
+
+ # wrapper code for a boundingbox;
+ # moves lower left corner of eps to (0,0)
+ # and defines a page size identical to the eps width and height.
+ # The gsave in the wrapper code should be matched by
+ # a grestore at the end of the PostScript code.
+ # This grestore can be specified on the Ghostscript command-line.
+
+ def wrapper
+ fail EPBBError, prn unless valid
+ fname = mktemp( 'ps' )
+ File.open( fname, $W ) do |f|
+ f.binmode if ARCH == 'w32'
+ f.write( "%%BoundingBox: 0 0 #{width} #{height}\n" +
+ "<< /PageSize [#{width} #{height}] >>" +
+ " setpagedevice\n" +
+ "gsave #{(-(@llx.to_i)).to_s} #{(-(@lly.to_i)).to_s}" +
+ " translate\n" ) > 0
+ end # open
+ return fname
+ end # wrapper
+
+ ##################
+
+ # convert boundingbox to boundingbox comment
+
+ def bbcomment
+ fail EPBBError, prn unless valid
+ "%%BoundingBox: #{@llx} #{@lly} #{@urx} #{@ury}"
+ end
+
+end # class Bb
+
+###########################################
+
+# PsPdf class definition
+
+class PsPdf
+
+ protected
+
+ SAFESIZE = 16000
+
+ public
+
+ # class methods ###
+
+ def PsPdf.pdf_options
+ "-dPDFSETTINGS=/#{$settings.pdf_target}" + \
+ ( $settings.pdf_version == 'default' ? '' : \
+ " -dCompatibilityLevel=#{$settings.pdf_version}" ) + \
+ ($settings.pdf_custom ? ' ' + $settings.pdf_custom : '')
+ end
+
+ def PsPdf.gs_options
+ "-dNOPAUSE -dBATCH -q -dSAFER"
+ end
+
+ def PsPdf.ps_options( sep )
+ # the sep(arable_color) option forces a cmyk color model,
+ # which should improve chances of grayscaling later on.
+ if sep
+ case $settings.ps_options
+ when /-level\dsep\b/
+ $settings.ps_options
+ when /-level\d\b/
+ $settings.ps_options.sub( /(-level\d)/, '\1sep' )
+ else
+ $settings.ps_options + " -level2sep"
+ end # case
+ else
+ $settings.ps_options
+ end # ifthenelse sep
+ end
+
+ # instance methods ###
+
+ attr_accessor :path, :bb, :type, :npages, :atfront
+
+ ##################
+
+ def initialize( params={} )
+
+ ext = params[ 'ext' ]
+ file = params[ 'file' ]
+
+ if not ext and not file
+ @path = nil
+ @type = nil
+ elsif not file
+ @path = mktemp( ext )
+ @type = case ext.downcase
+ when 'pdf'
+ 'pdf'
+ when 'eps'
+ 'eps'
+ when 'ps'
+ 'ps'
+ else
+ 'other'
+ end
+ else
+ @path = file
+ @type = identify( file )
+ end
+ end # initialize
+
+ ##################
+
+ # debug string for EPCallError
+
+ def buginfo( params = nil )
+ b = "Source was: " + @path + $/
+ b = b + hash_prn( params ) if params
+ b
+ end
+
+ ##################
+
+ # Find boundingbox, simple case.
+ # We shall call this method only for eps PsPdf objects which were
+ # converted by pdftops or Ghostscript, so we can be sure that
+ # the boundingbox is not (atend). The file is not rewritten.
+
+ def find_bb_simple
+
+ fail EPCallError, buginfo unless @type == 'eps'
+ @bb = nil
+ slurp = ''
+ File.open( @path, $R ) do |fl|
+ slurp = fl.read( [File.size(@path), SAFESIZE].min )
+ end
+ lines = slurp.split( /\r\n?|\n/ )
+ lines.each do |l|
+ if l =~ BB_PAT
+ @bb = Bb.from_bbcomment( l )
+ break
+ end
+ end # do |l|
+ fail EPBBError, @path unless @bb and @bb.valid
+
+ end # def find_bb_simple
+
+ ##################
+
+ def pdf_pages
+
+ fail EPCallError, buginfo unless @type == 'pdf'
+
+ @npages = nil
+
+ # get n. of pages; the Ghostscript pdf2dsc.ps script will
+ # create a list of pages. It seems to ignore logical p. numbers.
+
+ dsc = mktemp( "dsc" )
+ cmd = "\"#{$settings.gs_prog}\" -dNODISPLAY -q" +
+ " -sPDFname=\"#{@path}\" -sDSCname=\"#{dsc}\" pdf2dsc.ps"
+ write_log cmd # if $DEBUG
+ fail EPSystemError, cmd unless system( cmd ) and test( ?s, dsc )
+ lines = []
+ File.open( dsc, $R ) do |f|
+ lines = f.read( SAFESIZE ).split( /\r\n?|\n/ )
+ end
+ lines.each do |l|
+ if l =~ /^%%Pages:\s+(\d+)\s*$/
+ @npages = $1.to_i
+ break
+ end # if =~
+ end # do |l|
+
+ return @npages
+
+ end # pdf_pages
+
+ #############################################################
+
+ # direct conversions. These methods return a PsPdf object,
+ # and raise an exception in case of failure.
+ # Direct conversions convert at most once between PostScript and pdf.
+ # They always write to a temporary file.
+
+ ##################
+
+ # eps_clean: write source eps to an eps without preview, and
+ # with a boundingbox in the header.
+ # the eps is always written to a new file.
+
+ def eps_clean
+
+ fail EPCallError, buginfo if @type != 'eps' and @type != 'epsPreview'
+ atend = nil
+ slurp = ''
+ offset, ps_len = nil, nil
+ if @type == 'eps'
+ offset = 0
+ ps_len = File.size( @path )
+ else
+ # read ToC; see Adobe EPS spec
+ File.open( @path, $R ) do |fl|
+ # bug workaround for unpack
+ if "\001\000\000\000".unpack( 'V' )[0] == 1
+ dummy, offset, ps_len = fl.read( 12 ).unpack( 'VVV' )
+ else
+ dummy, offset, ps_len = fl.read( 12 ).unpack( 'NNN' )
+ end
+ end # File
+ end # ifthenelse @type
+
+ # boundingbox unknown and possibly atend
+ @bb, @atfront = nil, nil
+
+ # limit search for boundingbox comments.
+ # For very large eps files, we don't want to scan the entire file.
+ # A boundingbox comment should be in the header or trailer,
+ # so scanning the first and last few KB should be plenty.
+
+ File.open( @path, $R ) do |fl|
+ fl.seek( offset, IO::SEEK_SET )
+ slurp = fl.read( [ps_len,SAFESIZE].min )
+ end
+
+ # We capture both lines and separators, as an easy way to
+ # keep track of how many bytes have been read.
+ # It is not necessary to treat lines and separators differently.
+
+ lines = slurp.split( /(\r\n?|\n)/ )
+ pre_block = ''
+ post_block = ''
+ bb_comment = ''
+ lines.each do |l|
+ pre_block = pre_block + l
+ if l =~ BB_PAT
+ @bb = Bb.from_bbcomment( l )
+ @atfront = true
+ break
+ elsif l =~ BB_END
+ atend = true
+ break
+ end # =~ BB_PAT
+ end # do |l|
+ if atend
+ if ps_len > SAFESIZE
+ File.open( @path, $R ) do |fl|
+ fl.seek( offset + ps_len - SAFESIZE, IO::SEEK_SET )
+ slurp = fl.read( SAFESIZE )
+ end
+ lines = slurp.split( /(\r\n?|\n)/ )
+ end
+ lines.reverse_each do |l|
+ post_block = l + post_block
+ if l =~ BB_PAT
+ bb_comment = l
+ @bb = Bb.from_bbcomment( bb_comment )
+ break
+ end # if
+ end # do
+ end # if atend
+ fail EPBBError, @path unless @bb.valid
+ retVal = PsPdf.new( 'ext' => 'eps' )
+ if @type == 'eps' and @atfront # simple copy
+ ccp( @path, retVal.path )
+ elsif @atfront # copy a slice
+ sliceFile( @path, retVal.path, ps_len, offset )
+ elsif atend # relocate boundingbox
+ File.open( retVal.path, $W ) do |fl|
+ fl.write( pre_block.sub( BB_END1, bb_comment ))
+ end
+ sliceFile( @path, retVal.path,
+ ps_len - pre_block.length - post_block.length,
+ offset + pre_block.length, $A )
+ File.open( retVal.path, $A ) do |fl|
+ fl.write( post_block.sub( BB_PAT1, '%' ))
+ end
+ end # if atend
+ retVal.bb = @bb.copy
+ retVal.atfront = true
+ return retVal
+
+ end # eps_clean
+
+ ##################
+
+ # Use the Ghostscript bbox device to give an eps a tight boundingbox.
+ # Newer versions of Ghostscript can do that by themselves, but
+ # for the time being we just assume a bbox device.
+ # The eps should already have been cleaned up by eps_clean
+ # and the current boundingbox should not contain negative coordinates,
+ # otherwise the bbox output device may give incorrect results.
+ # Maybe we should test whether gs' bbox device can handle
+ # nonnegative coordinates.
+ # The boundingbox in the eps is rewritten, but the eps is
+ # not otherwise converted.
+ # We don't create a new PsPdf object.
+
+ def fix_bb
+
+ fail EPCallError, buginfo \
+ unless @type == 'eps' and @bb.non_negative
+ cmd = "#{short_name($settings.gs_prog)} #{PsPdf.gs_options}" +
+ " -sDEVICE=bbox #{short_name(@path)} 2>&1"
+ write_log cmd # if $DEBUG
+ bb_output = `#{cmd}`
+ fail EPSystemError, cmd unless $? == 0 and bb_output
+ bb_output.split(/\r\n?|\n/).each do |b|
+ if b =~ BB_PAT
+ bb_temp = Bb.from_bbcomment( b )
+ fail EPBBError, bb_output unless bb_temp.valid
+ bb_temp.expand
+ @bb = bb_temp.copy
+ # write a new eps file with a new boundingbox comment
+ ps_len = File.size( @path )
+ slurp = ''
+ File.open( @path, $R ) do |fl|
+ slurp = fl.read( [ps_len,SAFESIZE].min )
+ end
+ lines = slurp.split( /(\r\n?|\n)/ )
+ pre_block = ''
+ pre_length = 0
+ lines.each do |l|
+ pre_length = pre_length + l.length
+ if l =~ BB_PAT
+ pre_block = pre_block + bb_temp.bbcomment
+ oldpath = @path
+ @path = mktemp( 'eps' )
+ File.open( @path, $W ) { |fl| fl.write( pre_block ) }
+ sliceFile( oldpath, @path, \
+ ps_len - pre_length, pre_length, $A )
+ return self
+ else
+ pre_block = pre_block + l
+ end
+ end # do |l|
+ fail EPBBError, bb_output
+ end # if =~ BB_PAT
+ end # do |b|
+ fail EPBBError, bb_output
+
+ end # fix_bb
+
+ ##################
+
+ # Convert eps to pdf.
+ # The eps should already have a boundingbox in the header.
+ # When fix_bbox, let Ghostscript calculate a tight boundingbox.
+ # For this, we require non-negative boundingbox coordinates.
+
+ def eps_to_pdf( params={} )
+
+ gray = params[ 'gray' ]
+
+ fail EPCallError, buginfo( params ) unless @type == 'eps' and @atfront
+
+ wrp = @bb.wrapper
+
+ retVal = PsPdf.new( 'ext' => 'pdf' )
+ cmd = "\"#{$settings.gs_prog}\" #{PsPdf.gs_options}" +
+ " -sDEVICE=pdfwrite #{PsPdf.pdf_options}" +
+ " -sOutputFile=\"#{retVal.path}\"" +
+ ( gray ? (' "' + $GRAYHEAD + '"') : "" ) +
+ " \"#{wrp}\" \"#{@path}\" -c grestore"
+ write_log cmd # if $DEBUG
+ fail EPSystemError, cmd \
+ unless system( cmd ) and test( ?s, retVal.path )
+ retVal.npages = 1
+ return retVal
+
+ end # eps_to_pdf
+
+ ##################
+
+ # Convert source pdf to eps.
+ # The option sep_color is ignored if pdftops is not available.
+
+ def pdf_to_eps( params={} )
+
+ page = params[ 'page' ] ? params[ 'page' ].to_i : 1
+ sep = params[ 'sep' ]
+
+ fail EPCallError, buginfo( params ) unless @type == 'pdf'
+ fail EPCallError, buginfo( params ) \
+ unless page > 0 and page <= @npages
+ retVal = PsPdf.new( 'ext' => 'eps' )
+ if $settings.pdftops_prog and $settings.use_pdftops
+ cmd = "\"#{$settings.pdftops_prog}\"" +
+ " #{PsPdf.ps_options( sep )}" +
+ " -eps -f #{page} -l #{page}" +
+ " \"#{@path}\" \"#{retVal.path}\""
+ else
+ cmd = "\"#{$settings.gs_prog}\" -sDEVICE=epswrite" +
+ " #{PsPdf.gs_options}" +
+ " -dFirstPage=#{page}" +
+ " -dLastPage=#{page}" +
+ " -sOutputFile=\"#{retVal.path}\" \"#{@path}\""
+ end
+ write_log cmd # if $DEBUG
+ fail EPSystemError, cmd unless \
+ system( cmd ) and test( ?s, retVal.path )
+ retVal.atfront = 1
+ retVal.find_bb_simple
+ return retVal
+
+ end # pdf_to_eps
+
+ ##################
+
+ def ps_to_pdf( params={} )
+
+ gray = params[ 'gray' ]
+
+ fail EPCallError, buginfo( params ) \
+ unless @type == 'ps'
+
+ retVal = PsPdf.new( 'ext' => 'pdf' )
+ cmd = "\"#{$settings.gs_prog}\" #{PsPdf.gs_options}" +
+ " -sDEVICE=pdfwrite #{PsPdf.pdf_options}" +
+ " -sOutputFile=\"#{retVal.path}\"" +
+ ( gray ? (' "' + $GRAYHEAD + '"') : "" ) + " \"#{@path}\""
+ write_log cmd # if $DEBUG
+ fail EPSystemError, cmd \
+ unless system( cmd ) and test( ?s, retVal.path )
+
+ retVal.pdf_pages
+ return retVal
+
+ end # def ps_to_pdf
+
+ ##################
+
+ def pdf_to_ps( params={} )
+
+ sep = params[ 'sep' ]
+ page = params[ 'page' ] ? params[ 'page' ].to_s : nil
+
+ fail EPCallError, buginfo( params ) unless \
+ $settings.pdftops_prog and $settings.use_pdftops and @type == 'pdf'
+ retVal = PsPdf.new( 'ext' => 'ps' )
+ cmd = "\"#{$settings.pdftops_prog}\" #{PsPdf.ps_options( sep )}" +
+ ( page ? " -f #{page} -l #{page}" : '' ) +
+ " -paper match \"#{@path}\" \"#{retVal.path}\""
+ write_log cmd # if $DEBUG
+ fail EPSystemError, cmd unless \
+ system( cmd ) and test( ?s, retVal.path )
+ return retVal
+
+ end # pdf_to_ps
+
+ ##################
+
+ # all possible conversions, as concatenations of direct conversions.
+
+ def any_to_any( params={} )
+
+ type = params[ 'type' ]
+ page = params[ 'page' ]
+ bbox = params[ 'bbox' ]
+ gray = params[ 'gray' ]
+ gRAY = params[ 'gRAY' ] # try harder to grayscale
+ gray = 1 if gRAY
+ bbox = nil if type == 'ps'
+
+ fail EPCallError, buginfo( params ) \
+ unless ( type=='eps' or type=='pdf' or type=='ps' )
+ fail EPCallError, buginfo( params ) \
+ if @type=='other'
+ fail EPCallError, buginfo( params ) \
+ if type=='ps' and bbox
+ fail EPCallError, buginfo( params ) \
+ if @type=='eps' and type=='ps'
+
+ # gRAY tries harder to grayscale, by converting color first to cmyk
+ # even if it requires an additional eps - pdf - eps roundtrip.
+ # Normally, conversion to cmyk is done only if it doesn't take
+ # an extra roundtrip.
+ # The separable color conversion is an option of pdftops.
+
+ gRAY = nil unless \
+ ( $settings.pdftops_prog and $settings.use_pdftops )
+
+ pp = self
+
+ pp = pp.eps_clean if pp.type == 'epsPreview'
+ pp = pp.eps_clean if pp.type == 'eps' and \
+ not ( pp.bb and pp.atfront )
+ pp.pdf_pages if pp.type == 'pdf' and not pp.npages
+
+ case pp.type
+ when 'eps'
+
+ # in some cases extra eps => pdf => eps roundtrip:
+ # roundtrip guarantees bb.non_negative, necessary for fix_bb.
+ # pdf_to_ps( sep ) improves chances of grayscaling.
+
+ pp = pp.eps_to_pdf.pdf_to_eps( 'sep' => gray ) \
+ if gRAY or ( bbox and not pp.bb.non_negative )
+
+ case type
+ when 'eps'
+ pp = pp.eps_to_pdf( 'gray' => gray ).pdf_to_eps if gray
+ pp = pp.fix_bb if bbox
+ return pp
+
+ when 'pdf'
+ pp = pp.fix_bb if bbox
+ return pp.eps_to_pdf( 'gray' => gray )
+
+ end # case type
+
+ when 'pdf'
+
+ case type
+ when 'eps'
+ if not gray
+ pp = pp.pdf_to_eps( 'page' => page )
+ pp = pp.fix_bb if bbox
+ return pp
+ else
+ pp = pp.pdf_to_eps( 'page' => page, 'sep' => 1 )
+ pp = pp.fix_bb if bbox
+ pp = pp.eps_to_pdf( 'gray' => 1 )
+ return pp.pdf_to_eps
+ end
+
+ when 'pdf'
+ return pp unless ( gray or bbox or page )
+ if bbox or not $settings.pdftops_prog
+ pp = pp.pdf_to_eps( 'page' => page, 'sep' => gray )
+ pp = pp.fix_bb if bbox
+ return pp.eps_to_pdf( 'gray' => gray )
+ else
+ pp = pp.pdf_to_ps( 'page' => page, 'sep' => gray )
+ return pp.ps_to_pdf( 'gray' => gray )
+ end
+
+ when 'ps'
+ if gray
+ pp = pp.pdf_to_ps( 'sep' => 1 )
+ pp = pp.ps_to_pdf( 'gray' => 1 )
+ end
+ return pp.pdf_to_ps
+
+ end # case type
+
+ when 'ps'
+
+ case type
+ when 'eps'
+ if gRAY
+ pp = pp.ps_to_pdf.pdf_to_eps( 'page' => page, 'sep' => 1 )
+ pp = pp.eps_to_pdf( 'gray' => 1 )
+ pp = pp.pdf_to_eps
+ else
+ pp = pp.ps_to_pdf( 'gray' => gray )
+ pp = pp.pdf_to_eps( 'page' => page )
+ end
+ return pp.fix_bb
+
+ when 'pdf'
+ if bbox
+ pp = pp.ps_to_pdf( 'sep' => gray )
+ pp = pp.pdf_to_eps( 'page' => page )
+ pp = pp.fix_bb
+ return pp = pp.eps_to_pdf( 'gray' => gray )
+ elsif page
+ pp = pp.ps_to_pdf( 'sep' => gray )
+ pp = pp.pdf_to_ps( 'page' => page )
+ return pp = pp.ps_to_pdf( 'gray' => gray )
+ else
+ pp = pp.ps_to_pdf.pdf_to_ps( 'sep' => 1 ) if gRAY
+ return pp.ps_to_pdf( 'gray' => gray )
+ end
+
+ when 'ps'
+ return pp unless page or gray
+ if gRAY
+ pp = pp.ps_to_pdf.pdf_to_ps( 'page' => page, 'sep' => 1 )
+ return pp.ps_to_pdf( 'gray' => 1 ).pdf_to_ps
+ else
+ pp = pp.ps_to_pdf( 'gray' => gray )
+ return pp = pp.pdf_to_ps( 'page' => page )
+ end
+
+ end # case type
+
+ end # case pp.type
+
+ fail "Unsupported conversion"
+
+ end # any_to_any
+
+end # class PsPdf
+
+#################################
+# main program when not called from GUI
+
+if __FILE__ == $0
+
+require 'optparse'
+
+# create a pause to examine temp files
+def abortt( msg )
+ if $DEBUG
+ $stderr.puts msg + "\nPress <enter> to finish"
+ $stdin.gets
+ end
+ fail
+end
+
+begin # outer rescue block
+
+save_settings = false
+
+opts = OptionParser.new do |opts|
+ # for help output
+ opts.banner = "Convert between [e]ps and pdf formats"
+ opts.separator "Usage: epspdf.rb [options] infile [outfile]"
+ opts.separator ""
+ opts.separator "Default for outfile is file.pdf" +
+ " if infile is file.eps or file.ps"
+ opts.separator "Default for outfile is file.eps" +
+ " if infile is file.pdf"
+ opts.separator ""
+
+ opts.on( "-I",
+ "Ignore pdftops even if available",
+ "(default: use if available)" ) do |opt|
+ $settings.ignore_pdftops = '1'
+ end
+
+ opts.on( "-U",
+ "Use pdftops if available",
+ "(overrides previous -I setting)" ) do |opt|
+ $settings.ignore_pdftops = '0'
+ end
+
+ opts.on( "-T TARGET", "--target=TARGET", PDF_TARGETS,
+ "Target use of pdf; one of",
+ "#{PDF_TARGETS.join( ', ' )}" ) do |opt|
+ $settings.pdf_target = opt
+ end
+
+ opts.on( "-V VERSION", "--version=VERSION", PDF_VERSIONS,
+ "Pdf version to be generated;",
+ "one of #{PDF_VERSIONS.join( ', ' )}" ) do |opt|
+ $settings.pdf_version = opt
+ end
+
+ opts.on( "-C CUSTOMOPTIONS", "--custom=CUSTOMOPTIONS",
+ "Custom options for conversion to pdf,",
+ "view Use.htm and ps2pdf.htm from",
+ "the Ghostscript documentation set" ) do |opt|
+ $settings.pdf_custom = opt
+ end
+
+ opts.on( "-P PSOPTIONS", "--psoptions=PSOPTIONS",
+ "Options for pdftops; default -level2,",
+ "don't include -eps or page number options;",
+ "these will be generated by the program" ) do |opt|
+ $settings.ps_options = opt
+ end
+
+ opts.on( "-p PAGENUMBER", "--pagenumber=PAGENUMBER",
+ "Page to be converted or selected", Integer ) do |opt|
+ $options.page = opt
+ end
+
+ opts.on( "-b", "--bbox", "--BoundingBox",
+ "Compute tight boundingbox" ) do |opt|
+ $options.bbox = true
+ end
+
+ opts.on( "-g", "--gray", "--grey",
+ "Convert to grayscale;",
+ "success not guaranteed" ) do |opt|
+ $options.gray = true
+ end
+
+ opts.on( "-G", "--GRAY", "--GREY",
+ "Try harder to convert to grayscale;",
+ "success still not guaranteed" ) do |opt|
+ $options.gRAY = true
+ end
+
+ opts.on( "-i", "--info",
+ "Info: display detected filetype" ) do |opt|
+ $options.info = true
+ end
+
+ opts.on( "-s",
+ "Save (some) settings" ) do |opt|
+ save_settings = true
+ end
+
+ opts.on( "-d", "Debug: don't remove temp files" ) do |opt|
+ $DEBUG = 1
+ end
+
+ opts.separator ""
+
+ opts.on_tail("-h", "--help", "Show this message") do
+ puts opts
+ exit
+ end
+
+ # opts.on_tail("--version", "Show version") do
+ # puts OptionParser::Version.join('.')
+ # exit
+ # end
+end # opts
+
+# parse options destructively
+
+opts.parse!( ARGV )
+
+$options.page = 1 if $options.bbox and not $options.page
+
+$settings.write_settings if save_settings
+
+if ARGV.length < 1
+ puts opts if not save_settings # help output
+ # puts "Settings:"
+ # $settings.each_key do |k|
+ # puts "key #{k} value #{$settings[k].val}"
+ # end
+ abort
+elsif $options.info
+ puts "File type of #{ARGV[0]} is #{PsPdf.new( 'file' => ARGV[0] ).type}"
+ exit
+elsif ARGV.length > 1 and
+ File.expand_path( ARGV[0] ) == File.expand_path( ARGV[1] )
+ abort " Input and output files should be different."
+else
+ infile = ARGV[0]
+ abort( infile + " not found or empty" ) unless test( ?s, infile )
+end
+
+# done with options
+
+########################################
+
+source = PsPdf.new( 'file' => infile )
+
+# We aren't finicky about the extension of the input file,
+# but still want to check whether pdf is pdf.
+
+case source.type
+when 'eps', 'epsPreview', 'ps'
+ abort "Wrong extension; input is not in pdf format" \
+ if infile =~ /\.pdf$/i
+when 'pdf'
+ abort "Wrong extension; input is in pdf format" \
+ if infile !~ /\.pdf$/i
+else
+ abort "Invalid input file type; not [e]ps or pdf" \
+ if source.type == 'other'
+end # case source.type
+
+# find or construct output file name
+if ARGV.length > 1
+ outfile = ARGV[1]
+else
+ case source.type
+ when 'eps', 'epsPreview', 'ps'
+ outfile = infile.sub( /\.[^.]+$/, '.pdf' )
+ when 'pdf'
+ outfile = infile.sub( /\.[^.]+$/, '.eps' )
+ end # case
+end # ifthenelse ARGV.length
+outfile = File.expand_path( outfile )
+
+$options.type = case outfile
+when /\.pdf$/i
+ "pdf"
+when /\.ps$/i
+ "ps"
+when /\.eps$/i
+ "eps"
+else
+ nil
+end # case outfile
+
+abort "Unknown or unsupported output file extension" \
+ unless $options.type
+abort "Output format not supported without xpdf utilities" \
+ if outfile == 'ps' and not $settings.pstopdf_prog
+
+pp = PsPdf.new( 'file' => infile )
+
+begin # inner rescue block
+ pp = pp.any_to_any( $options )
+rescue EPCallError => exc
+ mess =
+ "Wrong method call or conversion not supported or wrong page number" +
+ $/ + exc.message + $/ + exc.backtrace.join( $/ )
+ write_log( mess )
+ puts mess
+ fail StandardError
+rescue EPBBError => exc
+ mess = "Boundingbox problem" + $/ +
+ exc.message + $/ + exc.backtrace.join( $/ )
+ write_log( mess )
+ puts mess
+ fail StandardError
+rescue EPSystemError => exc
+ mess = "Problem with system call" + $/ +
+ exc.message + $/ + exc.backtrace.join( $/ )
+ write_log( mess )
+ puts mess
+ fail StandardError
+end # rescue block
+
+ccp( pp.path, outfile )
+
+cleantemp unless $DEBUG == 1
+
+rescue => detail
+write_log detail.backtrace.join( $/ )
+puts detail.backtrace.join( $/ )
+exit
+end # outer rescue block
+
+end # if called as main program
+__END__
diff --git a/Master/texmf-dist/scripts/epspdf/epspdfboot.rb b/Master/texmf-dist/scripts/epspdf/epspdfboot.rb
new file mode 100644
index 00000000000..bdcebb77b26
--- /dev/null
+++ b/Master/texmf-dist/scripts/epspdf/epspdfboot.rb
@@ -0,0 +1,40 @@
+# Manipulate library path and maybe search path.
+
+# Problem to be solved:
+
+# We don't want to require Windows users to install Ruby and Tcl/Tk so
+# we offer a package with a built-in Ruby subset. This subset is
+# slightly modified from the subset created by rubyscript2exe
+# (http://www.erikveen.dds.nl/rubyscript2exe/).
+
+# The rubyscript2exe directory structure is simplified compared to the
+# original Ruby directory structure, so we need to modify the library
+# search path and also the general search path.
+
+# Assumptions:
+
+# - The script itself is at the root or in a toplevel subdirectory.
+# - If an rbconfig.rb is found at the root or in
+# a toplevel directory then there is a Ruby subset.
+# If that is the Ruby which is used
+# then it needs help to find its files.
+
+dir = File.expand_path( File.dirname( __FILE__ ) )
+parent = File.dirname( dir )
+parent_sl = parent.dup + ( parent =~ /[\\\/]$/ ? '' : '/' )
+dir_sl = dir.dup + ( parent =~ /[\\\/]$/ ? '' : '/' )
+spath = ENV['PATH'].dup
+
+if test( ?e, parent_sl + 'lib/rbconfig.rb' )
+ root_sl = parent_sl
+elsif test( ?e, dir_sl + 'lib/rbconfig.rb' )
+ root_sl = dir_sl
+else
+ root_sl = nil
+end
+
+if root_sl
+ $: << "#{root_sl}lib"
+end
+
+$:.unshift( dir )
diff --git a/Master/texmf-dist/scripts/epspdf/epspdfrc.rb b/Master/texmf-dist/scripts/epspdf/epspdfrc.rb
new file mode 100755
index 00000000000..f75d65b5339
--- /dev/null
+++ b/Master/texmf-dist/scripts/epspdf/epspdfrc.rb
@@ -0,0 +1,507 @@
+# epspdf conversion utility, configuration module
+
+#####
+# Copyright (C) 2006, 2008 Siep Kroonenberg
+# n dot s dot kroonenberg at rug dot nl
+#
+# This program is free software, licensed under the GNU GPL, >=2.0.
+# This software comes with absolutely NO WARRANTY. Use at your own risk!
+#####
+
+# This version has been adapted for TeX Live. The adaptations only
+# concern Windows. If TL is set then pdftops and
+# ghostscript are set to the version included in TeXLive, settings are
+# stored in HKCU\software\epspdftl (rather than epspdf) and the logfile
+# is %USERPROFILE%\epspdftl.log, rather than epspdf.log.
+# A future version should offer a dynamic way of settingt his option.
+
+# Settings are stored in a settings hash, with some methods added
+# for less unwieldy notation.
+#
+# In phase 1, some programs (converters, viewers) are autodetected.
+# In phase 2, user preferences are read from the epspdf configuration.
+#
+# For unix/osx, configuration info is stored in $HOME/.epspdfrc.
+# For w32, configuration info is stored in HKCU\software\epspdf.
+#
+# The UIs for settings are not here; they are:
+# 1. the epspdf.rb command-line if epspdf.rb is run as
+# a stand-alone program, and
+# 2. a configuration screen in epspdftk.rb.
+
+require 'rbconfig'
+include Config
+
+# for notational convenience, we keep ARCH separate
+
+ARCH = case CONFIG['arch']
+when /win32|mingw/
+ 'w32'
+when /darwin/
+ 'osx'
+else
+ 'unix'
+end
+
+TL = ENV.has_key?('TLROOT')
+if ARCH == 'w32'
+ require 'dl/win32'
+ require 'win32/registry'
+ include Win32 # this lets us abbreviate Win32::Registry to Registry
+ ShortPName = Win32API.new(
+ 'kernel32', 'GetShortPathName', ['P','P','N'], 'N' )
+ TLROOT = ENV['TLROOT']
+end
+
+# for Windows, use short names within backquotes
+# to avoid quotes within backquotes
+
+def short_name( fn )
+ return fn if ARCH != 'w32'
+ fn.gsub!( /\\/, '/' )
+ buffer = ' ' * 260
+ length = ShortPName.call( fn, buffer, buffer.size )
+ return ( length > 0 ) ? buffer.slice(0..length-1) : fn
+end
+
+# system-dependent location of logfile
+
+LOGFILE = case ARCH
+when 'w32'
+ TL ? "#{ENV['USERPROFILE']}\\epspdftl.log" :
+ "#{ENV['USERPROFILE']}\\epspdf.log"
+else
+ "#{ENV['HOME']}//epspdf.log"
+end
+LOGFILE_OLD = LOGFILE + '.old'
+
+# system-dependent locations of saved settings
+
+RC_FILE = "#{ENV['HOME']}/.epspdfrc"
+REG_K = TL ? 'epspdftl' : 'epspdf'
+REG_KEY = TL ? 'SOFTWARE\\epspdftl' : 'SOFTWARE\\epspdf'
+
+# hash of saved settings from rc file or registry
+
+$rc_settings = {}
+
+# find open command for extension (w32 only)
+
+def open_with( ext )
+ ext = '' unless ext
+ answer = nil
+ if ARCH == 'w32'
+ begin # open cl = HKCR\ext safely
+ Registry::HKEY_CLASSES_ROOT.open(
+ (ext =~ /^\./ ? ext : '.'+ext) ) do |cl|
+ begin # read ftype safely
+ ftype = cl.read_s( nil )
+ begin # open cmd = HKCR\ftype\shell... safely
+ Registry::HKEY_CLASSES_ROOT.open(
+ ftype + '\\shell\\open\\command' ) do |cmd|
+ begin # read answer safely
+ answer = cmd.read_s( nil )
+ if answer =~ /^"([^"]+)".*/
+ answer = $1
+ elsif answer =~ /^([^ ]+) .*/
+ answer = $1
+ end
+ answer = nil unless answer and test( ?s, answer )
+ rescue # answer not read
+ end # read answer safely
+ end # HKCR\ftype\shell... do |cmd|
+ rescue # cmd not opened
+ end # open cmd = HKCR\ftype\shell... safely
+ rescue # ftype not read
+ end # read ftype safely
+ end # HKCR\ext do |cl|
+ rescue # cl not opened
+ end # open cl = HKCR\ext safely
+ end # w32
+ answer
+end
+
+# test whether a string is a valid program call
+# 'which' also works with explicit paths.
+# 'which' returns an error for non-executable files.
+
+def is_a_program( s )
+ case ARCH
+ when 'w32'
+ nil
+ else
+ ( system "which #{s} >/dev/null" ) ? 1 : nil
+ end
+end # is_a_program
+
+# Parse version info from a prog from the xpdf suite.
+# This is used as validity test.
+
+def xpdf_version( arg )
+ retval = nil
+ arg = short_name( arg ) if ARCH == 'w32'
+ version_output = `#{arg} -v 2>&1`
+ if version_output and not version_output.empty?
+ vo = version_output.split(/\r\n?|\n/)
+ vo.grep(/version/i) { |a|
+ a =~ /^\D*(\d+\.\w*)\b/
+ retval = $& # matched part; nil if no match
+ }
+ end
+ retval
+end
+
+class Setting
+ attr_reader :val, :type, :comment
+ attr_writer :val
+
+ def initialize( v, t, c )
+ @val = v
+ @type = t
+ @comment = c
+ end
+end
+
+PDF_TARGETS = [ 'default', 'printer', 'prepress', 'screen', 'ebook' ]
+PDF_VERSIONS = [ '1.2', '1.3', '1.4', 'default' ]
+
+$settings = {
+ # converters
+ 'gs_prog' => Setting.new( nil, 'auto', nil ),
+ 'gs_version' => Setting.new( nil, 'auto', nil ),
+ 'pdftops_prog' => Setting.new( nil, ARCH=='w32' ? 'config' : 'auto', nil ),
+ # viewers
+ 'pdf_viewers' => Setting.new( nil, ARCH=='unix' ? 'auto' : nil, nil ),
+ 'ps_viewers' => Setting.new( nil, ARCH=='unix' ? 'auto' : nil, nil ),
+ 'pdf_viewer' => Setting.new( nil, ARCH=='unix' ? 'config' : 'auto', nil ),
+ 'ps_viewer' => Setting.new( nil, ARCH=='unix' ? 'config' : 'auto', nil ),
+ # conversion options
+ 'ignore_pdftops' => Setting.new( '0', 'config',
+ 'Ignore pdftops even if available; 1=yes, empty or 0=no(default)' ),
+ 'pdf_target' => Setting.new( 'prepress', 'config',
+ 'Target: screen, ebook, print, prepress (default) or default' ),
+ 'pdf_version' => Setting.new( '1.4', 'config',
+ 'Pdf version: e.g 1.4 or 1.2 (fewer features, more compatibility)' +
+ ' or unspecified' ),
+ 'pdf_custom' => Setting.new( '', 'config',
+ 'additional options for [e]ps to pdf conversion' ),
+ 'ps_options' => Setting.new( '-level2', 'config',
+ 'options for pdftops; default -level2' ),
+ 'bb_spread' => Setting.new( '1', 'config',
+ 'margin to be added to computed boundingbox; default 1' )
+}
+
+class << $settings
+
+ # create shortcut methods $settings.x and $settings.x=
+ # for reading and writing hash elements.
+
+ $settings.each_key { |k|
+ eval "def #{k} ; self[\'#{k}\'].val ; end"
+ eval "def #{k}=(v) ; self[\'#{k}\'].val=v ; end"
+ }
+
+ # use_pdftops is a boolean counterpart and inverse
+ # of the stored string attribute ignore_pdftops
+
+ def use_pdftops
+ case self['ignore_pdftops'].val
+ when /t(rue)?|y(es)?|1/i
+ false
+ when /f(alse)?|n(o)?|0/i
+ true
+ when 1
+ false
+ when 0
+ true
+ else
+ true
+ end
+ end
+
+ # we want use_pdftops = nil = default = true but
+ # we also want use_pdftops = nil <=> use_pdftops = false
+ # we give the second one priority.
+
+ def use_pdftops=( x )
+ self['ignore_pdftops'].val = case x
+ when /t(rue)?|y(es)?|1/i
+ '0'
+ when /f(alse)?|n(o)?|0/i
+ '1'
+ when 1
+ '0'
+ when 0
+ '1'
+ when false
+ '1'
+ when nil # try to avoid this assignment
+ '1'
+ when true
+ '0'
+ else
+ '1'
+ end
+ end
+
+ def accept_pdf_viewer( s )
+ if ARCH == 'unix'
+ if is_a_program( s )
+ self.pdf_viewer = s
+ self.pdf_viewers.unshift( s ) unless self.pdf_viewers.index( s )
+ return 1
+ else
+ return nil
+ end
+ else
+ return nil
+ end
+ end # accept_pdf_viewer
+
+ def accept_ps_viewer( s )
+ if ARCH == 'unix'
+ if is_a_program( s )
+ self.ps_viewer = s
+ self.pdf_viewer = s unless \
+ self.pdf_viewer and not self.pdf_viewer.empty?
+ self.ps_viewers.unshift( s ) unless self.ps_viewers.index( s )
+ self.pdf_viewers.push( s ) unless self.pdf_viewers.index( s )
+ return 1
+ else
+ return nil
+ end
+ else
+ return nil
+ end
+ end # accept_ps_viewer
+
+ # previously-configured settings into hash $rc_settings
+ # here no validity testing.
+ # we accept empty settings.
+
+ def read_settings
+ if ARCH == 'w32'
+ [Registry::HKEY_LOCAL_MACHINE,
+ Registry::HKEY_CURRENT_USER].each { |hk|
+ begin # open REG_KEY safely
+ hk.open( REG_KEY ) do |ep|
+ ep.each_value do |key, type, val|
+ $rc_settings[ key ] = val \
+ if $settings[ key ] and $settings[ key ].type == 'config'
+ end # do |key, type, val|
+ end # do |ep|
+ rescue
+ end # open REG_KEY safely
+ } # each |hk|
+ else
+ if test( ?s, RC_FILE )
+ lines = File.read( RC_FILE ).split( /\r\n?|\n/ )
+ lines.each do |l|
+ l = l.sub( /#.*$/, '' ) # remove trailing comments
+ if l =~ /^\s*(\S+)\s*=\s*(\S(.*\S)?)\s*$/
+ key, val = $1, $2
+ $rc_settings[ key ] = val \
+ if $settings[ key ] and $settings[ key ].type == 'config'
+ elsif l =~ /^\s*(\S+)\s*=\s*$/
+ key, val = $1, ''
+ $rc_settings[ key ] = '' \
+ if $settings[ key ] and $settings[ key ].type == 'config'
+ end # if l =~
+ end # do |l|
+ end # if ?s
+ end # if ARCH
+ end # def
+
+ def write_settings
+ if ARCH == 'w32'
+ begin
+ Registry::HKEY_CURRENT_USER.create(
+ 'SOFTWARE', desired = Registry::KEY_ALL_ACCESS) do |reg|
+ reg.create( REG_K, desired = Registry::KEY_ALL_ACCESS ) do |rk|
+ $settings.each do |k, s|
+ key = String.new( k )
+ st = Setting.new( s.val, s.type, s.comment )
+ # this copying looks kind of silly,
+ # but prevents a 'modifying frozen object' error.
+ if st.type == 'config'
+ vl = st.val ? st.val : ''
+ rk.write_s( key, vl )
+ end
+ end # do each
+ end # do |rk|
+ end # do |reg|
+ rescue => er # no real error handling for now
+ puts $!
+ puts er.backtrace.join( $/ )
+ puts 'Settings will be lost at next run'
+ end
+ else
+ File.open( RC_FILE, 'w' ) do |f|
+ f.write( "# This file will be overwritten by epspdf_tk[.rb]" \
+ + $/ )
+ $settings.each do |key, st|
+ if st.type == 'config'
+ f.write( $/ )
+ f.write( '# ' + st.comment + $/ ) if st.comment
+ # STDERR.puts "write setting for " + key
+ # STDERR.flush
+ f.write( key + " = " + ( st.val ? st.val : '' ) + $/ )
+ end
+ end # do |key, st|
+ end # do |f|
+ end # if
+ end # def
+
+ def get_settings
+
+ # phase 1: autodetect
+ # w32: gs_prog, gs_version, pdf_viewer, ps_viewer
+ # gs: search registry settings; the highest version wins.
+ # viewers: check file type registry entry for valid open commands
+ # w32/TL: gs_prog, gs_version, pdf_viewer, ps_viewer
+ # gs: from TL
+ # viewers: check file type registry entry for valid open commands
+
+ # unix: gs_prog, gs_version, pdftops_prog, pdf_viewers, ps_viewers
+ # osx: gs_prog, gs_version, pdftops_prog
+ # viewers: use Preview; don't check anything
+ # unix/osx are done together, except that for osx
+ # the viewers code is skipped.
+
+ case ARCH
+ when 'w32'
+ if !TL then # else use built-in texlive versions
+ # check registry for latest valid version of Ghostscript
+ # tentative values; HKLM and HKCU may provide different values
+ try_gs_version = nil
+ try_gs_prog = nil
+ [Registry::HKEY_LOCAL_MACHINE,
+ Registry::HKEY_CURRENT_USER].each { |hk|
+ puts hk.to_s if $DEBUG
+ hk.open('SOFTWARE') { |sof|
+ puts sof.to_s if $DEBUG
+ sof.each_key { |key, wtime|
+ puts key.to_s if $DEBUG
+ if key =~ /ghostscript/i
+ gh = hk.open('SOFTWARE\\' + key)
+ gh.each_key { |skey, wtime|
+ if skey =~ /^\d+\.\d+$/ # version number
+ if skey.to_f > try_gs_version.to_f
+ this_gs = hk.open('SOFTWARE\\' + key + '\\' + skey)
+ this_gs_prog = this_gs['GS_DLL'].sub(
+ /([\\\/])([^\\\/]+)$/, '\1gswin32c.exe')
+ if test(?e,this_gs_prog)
+ try_gs_version = skey
+ try_gs_prog = this_gs_prog
+ end # if ?e (exist)
+ end # skey.to_f > try_gs_version.to_f
+ end # if skey =~ /^\d+\.\d+$/
+ } # gh.each_key
+ end # if key =~ /ghostscript/i
+ } # sof.each_key
+ } # hk.open |sof|
+ } # [HKCU, HKLM].each
+ self.gs_version = try_gs_version
+ self.gs_prog = try_gs_prog
+ end
+
+ # viewers
+ self.pdf_viewer = open_with( 'pdf' )
+ self.ps_viewer = open_with( 'ps' )
+
+ when /unix|osx/
+ # gs
+ answer = `gs --version`
+ if answer and not answer.empty?
+ self.gs_prog = 'gs'
+ self.gs_version = answer.chomp
+ else
+ self.gs_prog = nil
+ self.gs_version = nil
+ end
+
+ # pdftops
+ self.pdftops_prog = xpdf_version( 'pdftops' ) ? 'pdftops' : nil
+
+ # viewers
+ vw = %w{ gpdf xpdf acroread evince ggv gv kghostview }
+ vw.delete_if { |x| not is_a_program( x ) }
+ vw = nil if vw.empty?
+ self.pdf_viewers = vw
+ self.pdf_viewer = vw ? vw[0] : nil
+ if vw
+ vw2 = vw.dup # copy the elements rather than the array ref
+ [ 'gpdf', 'xpdf', 'acroread' ].each { |pg|
+ vw2.delete( pg ) if vw2.index( pg )
+ }
+ vw2 = nil if vw2.empty?
+ self.ps_viewers = vw2
+ self.ps_viewer = vw2 ? vw2[ 0 ] : nil
+ end # if vw
+ end # case
+
+ # built-in defaults already set during initialization of $settings
+
+ # phase 2: pre-existing configuration
+ # w32: pdftops_prog
+ # unix (not osx): pdf_viewers
+
+ read_settings
+
+ case ARCH
+ when 'w32'
+ $rc_settings[ 'pdftops_prog' ] = (
+ TL ? (TLROOT.gsub( /\//, '\\' ) + '\\bin\\win32\\pdftops.exe') :
+ "z:\\aps\\staff\\ber\\miktex\\xpdf\\pdftops.exe" ) unless
+ ( $rc_settings[ 'pdftops_prog' ] and
+ ! $rc_settings[ 'pdftops_prog' ].empty? )
+ ptop = $rc_settings[ 'pdftops_prog' ]
+ if xpdf_version( ptop ) then
+ self.pdftops_prog = ptop
+ end
+ if TL
+ self.gs_prog = TLROOT.gsub( /\//, '\\' ) +
+ '\\tlpkg\\tlgs\\bin\\gswin32c.exe'
+ self.gs_version =
+ ( `#{short_name( self.gs_prog )} --version` ).chomp
+ end
+ when 'unix'
+ if v = $rc_settings[ 'pdf_viewer' ] and is_a_program( v )
+ self.pdf_viewer = v
+ self.pdf_viewers.unshift( v ) unless self.pdf_viewers.index( v )
+ end # if
+ if v = $rc_settings[ 'ps_viewer' ] and is_a_program( v )
+ self.ps_viewer = v
+ self.ps_viewers.unshift( v ) unless self.ps_viewers.index( v )
+ end # if
+ if self.ps_viewers and not self.pdf_viewers
+ self.pdf_viewers = self.ps_viewers.dup
+ self.pdf_viewer = self.ps_viewer
+ end # if
+ end # case ARCH
+
+ # no validity checks for pdf- and ps output options.
+ # reminder: self.s shortcut for self['s'].val
+ [ 'pdf_target', 'pdf_version', 'pdf_custom', 'ps_options' ].each { |p|
+ self[ p ].val = $rc_settings[ p ] if $rc_settings[ p ]
+ }
+ if $rc_settings.has_key?( 'ignore_pdftops' )
+ $settings.ignore_pdftops = case $rc_settings[ 'ignore_pdftops' ]
+ when /1|yes|true|y|t/i
+ '1'
+ when /0|no|false|n|f/i
+ '0'
+ end
+ else
+ $settings.ignore_pdftops = '0'
+ end
+
+ self.bb_spread = $rc_settings[ 'bb_spread' ] if
+ $rc_settings.has_key?( 'bb_spread' ) and
+ $rc_settings[ 'bb_spread' ] =~ /^[+-]?[\d]+$/
+
+ end # get_settings
+
+end # class << $settings
+
+$settings.get_settings
diff --git a/Master/texmf-dist/scripts/epspdf/epspdftk b/Master/texmf-dist/scripts/epspdf/epspdftk
new file mode 100755
index 00000000000..6d3465a8c4b
--- /dev/null
+++ b/Master/texmf-dist/scripts/epspdf/epspdftk
@@ -0,0 +1,7 @@
+#!/bin/sh
+script=`kpsewhich -format=texmfscripts epspdftk.rb`
+if test "x$1" = "x"; then
+ "$script" $HOME
+else
+ "$script" $*
+fi \ No newline at end of file
diff --git a/Master/texmf-dist/scripts/epspdf/epspdftk.rb b/Master/texmf-dist/scripts/epspdf/epspdftk.rb
new file mode 100755
index 00000000000..c09509c0c8f
--- /dev/null
+++ b/Master/texmf-dist/scripts/epspdf/epspdftk.rb
@@ -0,0 +1,958 @@
+#!/usr/bin/env ruby
+
+# epspdf conversion utility, GUI frontend
+
+#####
+# Copyright (C) 2006 Siep Kroonenberg
+# n dot s dot kroonenberg at rug dot nl
+#
+# This program is free software, licensed under the GNU GPL, >=2.0.
+# This software comes with absolutely NO WARRANTY. Use at your own risk!
+#####
+
+#$DEBUG=1
+
+# epspdfboot.rb: modify loadpath in a way which works both
+# with a full Ruby and with a custom subset ruby
+
+require __FILE__.sub( /epspdftk\.rbw?/, 'epspdfboot.rb' )
+
+##########################################
+
+# load conversion engine. epspdf also loads epspdfrc,
+# which detects platform and available converters.
+
+require 'epspdf'
+
+$VERBOSE = nil
+
+#require 'pp'
+
+if $DEBUG
+ puts ARCH
+ puts Config::CONFIG['arch']
+ puts "Ghostscript command #{$settings.gs_prog}" \
+ " and version #{$settings.gs_version}"
+ puts "Pdftops command #{$settings.pdftops_prog}" \
+ " and version #{$settings.pdftops_version}"
+end
+
+def viewable( p )
+ return nil unless p && p.path
+ return nil if p.type == 'other'
+ case ARCH
+ when 'osx'
+ return true
+ when 'w32'
+ return nil if p.type == 'epsPreview'
+ return open_with( File.extname( p.path ) )
+ else
+ return nil if p.type == 'epsPreview'
+ return true if p.type =~ /e?ps/ and ( not $settings.ps_viewer.empty? )
+ return true if p.type == 'pdf' and ( not $settings.pdf_viewer.empty? )
+ end # case ARCH
+ return nil
+end # viewable
+
+####################################
+
+# Tk and custom widgets
+
+require 'tk'
+require 'tkscrollbox'
+
+# For event field strings, which codify event details, see
+# the bind man page from the tk man pages (Ubuntu: tk8.x-doc package)
+
+####################################
+
+# combobox adapted from Takaaki Tateishi <ttate / jaist.ac.jp>
+# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/18167
+
+# literal content of an xbm file, created e.g. with the GIMP
+
+$DOWN_ARROW_IMG = <<STR
+#define dwnarrow.icn_width 15
+#define dwnarrow.icn_height 10
+static unsigned char dwnarrow.icn_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0xf8, 0x0f, 0xf0, 0x07, 0xe0, 0x03,
+ 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 };
+STR
+
+class TkACombobox < TkFrame
+
+ include TkComposite
+
+ attr_reader :scrollbox, :tframe
+ attr_accessor :entries, :is_valid
+
+ def initialize_composite( params = {} )
+
+ @entries = []
+ @is_valid = proc{ |s| true }
+ @entry = nil
+
+ # entry widget plus arrow for drop-down listbox
+
+ @entry = TkEntry.new( @frame,
+ 'width' => 30, 'bd' => 1, 'highlightthickness' => 0 )
+ image = TkBitmapImage.new( 'data' => $DOWN_ARROW_IMG )
+ @bt_arrow = TkButton.new( @frame, 'bd' => 1, 'image' => image,
+ 'highlightthickness' => 0, 'command' => proc{ cmd_scrollbox } )
+ @entry.pack( 'side' => 'left', 'fill' => 'x', 'expand' => 'yes' )
+ @bt_arrow.pack( 'side' => 'right' )
+
+ # drop-down listbox
+
+ @tframe = TkToplevel.new( @frame )
+ @tframe.overrideredirect( 1 ) # no window manager decorations
+ @tframe.transient
+ @tframe.withdraw
+ @scrollbox = TkScrollbox.new( @tframe, 'width' => 30, 'border' => 1 )
+ @scrollbox.pack( 'fill' => 'both', 'expand' => 'yes' )
+ @scrollbox.bind( 'Any-Leave', proc{ hide_scrollbox } )
+ # "%y", "%P": event field string; see bind manual from tk8.x-docs
+ @scrollbox.bind( 'Double-1', proc{ |y| select_this( y ) }, "%y" )
+ @scrollbox.bind( 'Return', proc{ |y| select_this( y ) }, "%y" )
+
+ @entry.bind( 'FocusOut', proc{ entry_proc } )
+ @entry.bind( 'Return', proc{ entry_proc } )
+ @entry.bind( 'Double-1', proc{ entry_proc } )
+
+ delegate( :width, @entry, @scrollbox )
+
+ configure params if params
+
+ end # initialize_composite
+
+ def cmd_scrollbox
+ case @tframe.state
+ when "withdrawn"
+ show_scrollbox( @entries )
+ else
+ hide_scrollbox
+ end
+ end
+
+ def show_scrollbox( entries = nil )
+ width = TkWinfo.width( @frame )
+ height = 5 * TkWinfo.height( @entry )
+ rootx = TkWinfo.rootx( @frame )
+ rooty = TkWinfo.rooty( @frame ).to_i + TkWinfo.height( @frame ).to_i
+ geometry = "#{width}x#{height}+#{rootx}+#{rooty}"
+ @tframe.geometry( geometry )
+ @tframe.deiconify
+ entries.each{ |entry| @scrollbox.insert( "end", entry ) } if entries
+ end
+
+ def hide_scrollbox
+ @tframe.withdraw
+ @scrollbox.delete( 0, "end" )
+ @entry.focus
+ end
+
+ def select_this( y )
+ i = @scrollbox.nearest( y )
+ s = @scrollbox.get( i )
+ @entry.delete( 0, 'end' )
+ @entry.insert( 0, s )
+ @is_valid.call( s ) # activates side effects
+ hide_scrollbox
+ end
+
+ def entry_proc
+ #puts @entry.value
+ if @is_valid.call( @entry.value )
+ @entries.unshift( @entry.value ).sort! \
+ unless @entries.index( @entry.value )
+ @tframe.withdraw unless @tframe.state == 'withdrawn'
+ else
+ Tk.bell
+ @entry.focus( true )
+ end
+ end
+
+ def get_entry
+ @entry.value
+ end
+
+ def set_entry( s )
+ @entry.delete( 0, 'end' )
+ @entry.insert( 'end', s ) if s
+ end
+
+end # TkACombobox
+
+####################################
+
+# checkboxes and radioboxes with built-in variables.
+# use string- rather than symbol keys when creating these widgets.
+
+def zero_one( v ) # For Tcl/Tk, everything is a string
+ case v
+ when /t(rue)?|y(es)?|1/i
+ '1'
+ when /f(alse)?|n(o)?|0/i
+ '0'
+ when 1
+ '1'
+ when 0
+ '0'
+ else
+ nil
+ end
+end
+
+class TkACheck < TkFrame
+
+ include TkComposite
+
+ def initialize_composite( params = {} )
+
+ Kernel::fail StandardError, "TkACheck doesn\'t allow \'variable\' key" \
+ if params.has_key?( 'variable' )
+
+ v = params.delete( 'value' )
+ @value = TkVariable.new( zero_one( v ) )
+
+ @ck = TkCheckButton.new( @frame, :variable => @value \
+ ).pack( :padx => 0, :pady => 0, :ipadx => 0, :ipady => 0 )
+
+ delegate( 'DEFAULT', @ck )
+
+ configure params unless params.empty?
+
+ end # initialize_composite
+
+ def value
+ @value.value
+ end
+
+ def value=( v )
+ @value.value = zero_one( v )
+ end
+
+end # TkACheck
+
+class TkRadios < TkFrame
+
+ include TkComposite
+
+ def initialize_composite( params = {} )
+
+ Kernel::fail StandardError, "TkRadios doesn\'t allow \'variable\' key" \
+ if params.has_key?( 'variable' )
+
+ @value = TkVariable.new( params.delete( 'value' ) )
+ @values = params.delete( 'values' )
+ @packing = params.delete( 'packing' )
+ @buttons = []
+
+ if ( @values.kind_of? Hash )
+ @values.each_key { |k|
+ @buttons << TkRadioButton.new( @frame,
+ :text => @values[k] || k,
+ :variable => @value,
+ :value => k
+ ).pack( @packing )
+ }
+ elsif ( @values.kind_of? Array )
+ @values.each { |k|
+ @buttons << TkRadioButton.new( @frame,
+ :text => k,
+ :variable => @value,
+ :value => k
+ ).pack( @packing )
+ }
+ else
+ Kernel::fail StandardError, "TkRadios requires a values array or hash"
+ end
+
+ delegate( 'DEFAULT', @frame )
+ delegate( 'command', *@buttons )
+ delegate( 'state', *@buttons )
+
+ configure( params ) unless params.empty?
+
+ end # initialize_composite
+
+ def value
+ @value.value
+ end
+
+ def value=( v )
+ @value.value = v
+ end
+
+ def get_button_state( v )
+ @buttons.each { |b|
+ if b.value == v
+ return b.cget( 'state' )
+ end
+ }
+ return nil
+ end
+
+ def set_button_state( v, s )
+ @buttons.each { |b|
+ if b.value == v
+ b.configure( 'state' => s )
+ @value.value = nil if s == 'disabled' and @value.value == v
+ end
+ }
+ end
+
+end # TkRadios
+
+$root = TkRoot.new { title "PostScript- and pdf conversions" }
+
+##################################
+
+# Initial tests: no gs => bail out; no viewers => warning
+
+if not $settings.gs_prog
+ Tk.messageBox(
+ :icon=>'error',
+ :type=>'ok',
+ :parent=>$root,
+ :message=>"No Ghostscript found; aborting..."
+ )
+ abort
+end
+
+if not $settings.pdf_viewer
+ Tk.messageBox( :icon=>'warning', :type=>'ok', :message =>
+ "No PostScript- or pdf viewer found" )
+elsif not $settings.ps_viewer
+ Tk.messageBox( :icon=>'warning', :type=>'ok', :message =>
+ "No PostScript viewer found" )
+end
+
+########################################
+
+$defaultDir = ENV['PWD']
+
+$defaultDir = ARGV[0] if ((ARGV.length > 0) and File.directory?(ARGV[0]))
+
+$source = PsPdf.new # currently loaded PsPdf object
+
+$tl_config = nil # configuration screen
+$tl_wait = nil # instead of a wait cursor or progress bar
+
+# widgets which are configured on the fly,
+# e.g. by ep_config, get a global name.
+# They don't really have to be declared early.
+
+# buttons and option widgets
+$view_button = nil
+$page_radio = nil
+$page_entry = nil
+$type_radio = nil
+$bbox_check = nil
+
+# widgets which display file info
+$source_dir_label = nil
+$source_name_label = nil
+$source_type_label = nil
+
+def set_widget_states
+ # states (normal/disabled) for various widgets.
+ # their values should already be mutually consistent.
+ # widgets concerned:
+ # view / save
+ # output format / bbox / single page / page no.
+
+ $view_button.configure( :state =>
+ ( viewable( $source ) ? 'normal' : 'disabled' ) )
+ $save_button.configure( :state =>
+ ( ( $source.type and $source.type != 'other' ) ? \
+ 'normal' : 'disabled' ) )
+
+ $type_radio.set_button_state( 'ps', ( \
+ ( $settings.pdftops_prog and $settings.use_pdftops and
+ ( $source.type =~ /ps|pdf/ ) ) ? \
+ 'normal' : 'disabled' ) )
+
+ $page_radio.set_button_state( 'all', 'normal' )
+ $page_radio.set_button_state( 'single', 'normal' )
+ $page_radio.set_button_state( 'all', 'disabled' ) if \
+ $type_radio.value == 'eps'
+ $page_radio.set_button_state( 'single', 'disabled' ) if \
+ $type_radio.value == 'ps'
+
+ $page_entry.configure( :state => \
+ ( $page_radio.value == 'all' ? 'disabled' : 'normal' ) )
+
+ $bbox_check.configure( :state => \
+ ( $page_radio.value == 'single' or $source.type =~ /eps/ ) \
+ ? 'normal' : 'disabled' )
+
+end # set_widget_states
+
+def load_file( path )
+ $source = PsPdf.new( 'file' => path )
+ # write info to labels
+ $source_dir_label.configure( :text => File.dirname( path ) )
+ $source_name_label.configure( :text => File.basename( path ) )
+ $source_type_label.configure( :text => $source.type )
+ $source.pdf_pages if ( $source.type == 'pdf' )
+ $source_npages_label.configure( :text => (
+ case $source.type
+ when 'pdf' then ( $source.npages ).to_s
+ when 'eps' then '1'
+ else ''
+ end
+ ) )
+ $page_entry.delete( 0, 'end' )
+ $page_entry.insert( 'end', '1' )
+ set_widget_states
+end
+
+# ipadx and ipady seem ineffective for frames
+
+FRM_PACK = {
+ :side => 'top',
+ :fill => 'x',
+ :expand => 1,
+ :padx => 4,
+ :pady => 4,
+ :anchor => 'w'
+}
+
+##################################
+
+# configuration screen (toplevel widget)
+
+$tl_config = nil
+
+def ep_config
+
+ if not $tl_config
+
+ $tl_config = TkToplevel.new( $root, :title => 'Configure epspdf' )
+
+ ### viewers frame
+
+ if ARCH == 'unix'
+ TkFrame.new( $tl_config ) { |frm|
+ frm.borderwidth 2
+ frm.relief 'groove'
+ TkLabel.new( frm, :text => 'VIEWERS'
+ ).pack( :side => 'top', :padx => 4, :anchor => 'w' )
+ TkFrame.new( frm ) { |fm|
+ TkLabel.new( fm, :text => 'Pdf viewer' ).grid(
+ :in => fm, :row => 0, :column => 0,
+ :sticky => 'w', :padx => 2 )
+ $pdf_vw_combo = TkACombobox.new( fm, :width => 30 )
+ $pdf_vw_combo.is_valid = lambda { |s| is_a_program( s ) }
+ $pdf_vw_combo.grid( :in => fm, :row => 0, :column => 1,
+ :pady => 2, :padx => 2, :sticky => 'e' )
+
+ TkLabel.new( fm, :text => 'PostScript viewer' ).grid(
+ :in => fm, :row => 1, :column => 0,
+ :sticky => 'w', :padx => 2 )
+ $ps_vw_combo = TkACombobox.new( fm, :width => 30 )
+ $ps_vw_combo.is_valid = lambda { |s| is_a_program( s ) }
+ $ps_vw_combo.grid( :in => fm, :row => 1, :column => 1,
+ :pady => 2, :padx => 2, :sticky => 'e' )
+ }.pack( :side => 'top', :anchor => 'w', :fill => 'x' )
+ }.pack( FRM_PACK )
+ end # if unix
+
+ ### postscript frame
+
+ TkFrame.new( $tl_config ){ |frm|
+ frm.borderwidth 2
+ frm.relief 'groove'
+ TkLabel.new( frm, :text => 'POSTSCRIPT CONVERSION'
+ ).pack( :side => 'top', :padx => 4, :anchor => 'w' )
+
+ if ARCH == 'w32' # others: assume pdftops on search path
+ TkLabel.new( frm, :text => "Find pdftops"
+ ).pack( :side => 'top', :anchor => 'w', :padx => 4 )
+
+ TkFrame.new( frm ) { |fm|
+ $pdftops_entry = TkEntry.new( fm, :width => 20
+ ).pack( 'side'=>'left', :padx => 4 )
+ TkButton.new( fm,
+ :text => 'Browse ...',
+ :command => lambda {
+ tryprog = Tk.getOpenFile(
+ :filetypes => [ [ 'Programs', [ '.exe' ] ] ],
+ :parent => fm
+ )
+ if tryprog and ( not tryprog.empty? )
+ if not xpdf_version( tryprog )
+ Tk.messageBox(
+ :icon => 'warning',
+ :type => 'ok',
+ :parent => fm,
+ :message => "pdftops missing or dysfunctional"
+ )
+ else
+ $pdftops_entry.delete( 0, 'end' )
+ $pdftops_entry.insert( 'end', tryprog )
+ end # ifthenelse xpdf_version
+ end # ifthenelse tryprog
+ } # command lambda
+ ).pack( :side => 'left' ) # TkButton
+ }.pack( :side => 'top', :pady => 4, :anchor => 'w' )
+ end # ARCH == 'w32'
+
+ $pdftops_check = TkACheck.new( frm,
+ 'text' => "Use pdftops if available"
+ ).pack( :side => 'top', :pady => 4, :anchor => 'w' )
+
+ }.pack( FRM_PACK ) # TkFrame |frm|
+
+ ### pdf frame
+
+ TkFrame.new( $tl_config ){ |frm|
+ frm.borderwidth 2
+ frm.relief 'groove'
+ TkLabel.new( frm, :text => 'PDF CONVERSION'
+ ).pack( :side => 'top', :padx => 4, :anchor => 'w' )
+
+ # internal packing
+ pack_pdf = {
+ :side => 'left', :padx => 2, :pady => 4, :anchor => 'w' }
+
+ TkLabel.new( frm, :text => 'Intended use'
+ ).pack( :side => 'top', :padx => 2, :pady => 0, :anchor => 'w' )
+ $pdf_target_radio = TkRadios.new( frm,
+ 'values' => PDF_TARGETS, 'packing' => pack_pdf
+ ).pack( :side => 'top', :anchor => 'w' )
+
+ # dummy widget for extra vertical space
+ TkLabel.new( frm, :text => ' ' ).pack
+
+ TkLabel.new( frm, :text => 'Pdf version'
+ ).pack( :side => 'top', :padx => 2, :pady => 0, :anchor => 'w' )
+
+ $pdf_version_radio = TkRadios.new( frm,
+ 'values' => PDF_VERSIONS, 'packing' => pack_pdf
+ ).pack( :side => 'top', :anchor => 'w' )
+
+ TkLabel.new( frm, :text => ' ' ).pack
+
+ TkLabel.new( frm, :text => 'Custom Ghostscript/ps2pdf parameters'
+ ).pack( :side => 'top', :padx => 2, :pady => 0, :anchor => 'w' )
+
+ $pdf_custom_entry = TkEntry.new( frm, :width => 50
+ ).pack( :side => 'top', :padx => 2, :pady => 2, :anchor => 'w' )
+
+ }.pack( FRM_PACK )
+
+ ### button frame
+
+ TkFrame.new( $tl_config ) { |frm|
+
+ TkButton.new( frm,
+ :text => 'Cancel',
+ :command => lambda {
+ $tl_config.withdraw
+ $root.focus
+ }
+ ).pack( :padx => 4, :side => 'left', :anchor => 'e' )
+
+ TkButton.new( frm,
+ :text => 'Done',
+ :command => lambda {
+ # copy settings from widgets to $settings
+ case ARCH
+ when 'unix' # viewers
+ $settings.accept_ps_viewer( $ps_vw_combo.get_entry )
+ $settings.accept_pdf_viewer( $pdf_vw_combo.get_entry )
+ when 'w32'
+ $settings.pdftops_prog = $pdftops_entry.get
+ end
+ $settings.use_pdftops = ( not $pdftops_check.value == '0' )
+ $settings.pdf_target = $pdf_target_radio.value
+ $settings.pdf_version = $pdf_version_radio.value
+ $settings.pdf_custom = $pdf_custom_entry.get
+ $settings.write_settings
+ $tl_config.withdraw
+ $root.focus
+ set_widget_states
+ } # lambda
+ ).pack( :side => 'left', :anchor => 'e' )
+
+ }.pack( :side => 'bottom', :padx => 4, :pady => 4, :anchor => 'e' )
+ else
+ $tl_config.deiconify
+ end # ifthenelse $tl_config
+
+ # copy data from $settings to widgets
+ if ARCH == 'unix'
+ $pdf_vw_combo.set_entry( $settings.pdf_viewer )
+ $pdf_vw_combo.entries = $settings.pdf_viewers[0..-1] # deep copy
+ $ps_vw_combo.set_entry( $settings.ps_viewer )
+ $ps_vw_combo.entries = $settings.ps_viewers[0..-1]
+ elsif ARCH == 'w32'
+ $pdftops_entry.delete( 0, 'end' )
+ $pdftops_entry.insert( 'end', $settings.pdftops_prog ) \
+ if $settings.pdftops_prog and not $settings.pdftops_prog.empty?
+ end # ifthenelse ARCH
+ $pdftops_check.value = $settings.use_pdftops ? '1' : '0'
+ $pdf_target_radio.value = $settings.pdf_target
+ $pdf_version_radio.value = $settings.pdf_version
+ $pdf_custom_entry.delete( 0, 'end' )
+ $pdf_custom_entry.insert( 'end', $settings.pdf_custom ) \
+ if not $settings.pdf_custom.empty?
+
+end # def ep_config
+
+###################################
+
+### makeshift help
+
+$tl_help = nil
+
+def ep_help
+ if not $tl_help
+ $tl_help = TkToplevel.new( $root, :title => 'Epspdftk help' )
+ TkFrame.new( $tl_help ) { |tf|
+ txt = TkText.new( tf,
+ 'width' => 80,
+ 'height' => 25
+ ) { |t|
+ TkScrollbar.new( tf,
+ 'command' => lambda{ |*args| t.yview( *args ) } ) { |sc|
+ t.yscrollcommand( lambda{ |first, last| sc.set first, last } )
+ }.pack( 'side' => 'right', 'fill' => 'y' )
+ }.pack( 'expand' => 'yes', 'fill' => 'both' )
+
+ txt.delete( '1.0', 'end' )
+
+ # LF ok for Win32 and Mac? Otherwise, split and join with $/
+
+ File.open( File.dirname( __FILE__ ) + '/epspdf.help', 'r' ) { |f|
+ $s = f.read
+ }
+
+ txt.insert( '1.0', $s )
+
+ }.pack( 'side' => 'top', 'fill' => 'x' )
+
+ TkButton.new( $tl_help,
+ :text => 'Cancel',
+ :command => lambda{
+ $tl_help.withdraw
+ $root.focus
+ }
+ ).pack( 'anchor' => 'e', 'padx' => 4, 'pady' => 4 )
+ else
+ $tl_help.deiconify
+ end # ifthenelse $tl_help
+
+end # def ep_help
+
+### some buttons
+
+TkFrame.new( $root ) { |frm|
+
+ TkButton.new( frm,
+ :text => "Configure",
+ :command => lambda { ep_config }
+ ).pack( :side => 'left', :padx => 4, :pady => 4 )
+
+ TkButton.new( frm,
+ :text => 'Help',
+ :command => lambda { ep_help }
+ ).pack( :side => 'right', :padx => 4, :pady => 4)
+
+}.pack( :side => 'top', :fill => 'x' ) # frm
+
+########################################
+
+### status info
+
+TkFrame.new( $root ){ |frm|
+ frm.borderwidth 2
+ frm.relief 'groove'
+
+ ### status info
+
+ TkFrame.new( frm ) { |fm|
+ TkLabel.new( fm,
+ :justify => 'left',
+ :text => 'Directory'
+ ).grid( :in => fm, :sticky => 'w', :row => 0, :column => 0 )
+ $source_dir_label = TkLabel.new( fm,
+ :justify => 'left'
+ ).grid( :in => fm, :sticky => 'w', :row => 0, :column => 1 )
+
+ TkLabel.new( fm,
+ :justify => 'left',
+ :text => 'File'
+ ).grid( :in => fm, :sticky => 'w', :row => 1, :column => 0 )
+ $source_name_label = TkLabel.new( frm,
+ :justify => 'left'
+ ).grid( :in => fm, :sticky => 'w', :row => 1, :column => 1 )
+
+ TkLabel.new( fm,
+ :justify => 'left',
+ :text => 'Type'
+ ).grid( :in => fm, :sticky => 'w', :row => 2, :column => 0 )
+ $source_type_label = TkLabel.new( fm,
+ :justify => 'left'
+ ).grid( :in => fm, :sticky => 'w', :row => 2, :column => 1 )
+
+ TkLabel.new( fm,
+ :justify => 'left',
+ :text => 'Pages'
+ ).grid( :in => fm, :sticky => 'w', :row => 3, :column => 0 )
+ $source_npages_label = TkLabel.new( fm,
+ :justify => 'left'
+ ).grid( :in => fm, :sticky => 'w', :row => 3, :column => 1 )
+
+ TkGrid.columnconfigure( fm, 0, :weight => 1, :minsize => 60, :pad =>4 )
+ TkGrid.columnconfigure( fm, 1, :weight => 3, :minsize => 60, :pad =>4 )
+ }.pack( :side => 'top', :anchor => 'w', :padx => 4 )
+
+}.pack( FRM_PACK )
+
+########################################
+
+### conversion options: see also $options, defined in epspdf.rb
+
+TkFrame.new( $root ) { |frm|
+
+ TkFrame.new( frm ) { |fm| # grayscaling, output format
+ TkFrame.new( fm ) { |f| # grayscaling
+ TkLabel.new( f, 'text' => 'Grayscaling'
+ ).pack( :side => 'top', :anchor => 'w' )
+
+ gray_options = {
+ 'gRAY' => 'Try harder to grayscale',
+ 'gray' => 'Try to grayscale',
+ 'color' => 'No color conversion'
+ }
+
+ $gray_radio = TkRadios.new( f,
+ 'values' => gray_options,
+ 'value' => 'color',
+ 'packing' => { 'side' => 'top', 'anchor' => 'w' }
+ ).pack( :side => 'bottom', :anchor => 'w' ) # $gray_radio
+ }.pack( :side => 'left', :padx => 4 ) # f: grayscaling
+
+ TkFrame.new( fm ) { |f| # output format
+ TkLabel.new( f, 'text' => 'Output format'
+ ).pack( :side => 'top', :anchor => 'w' )
+
+ $type_radio = TkRadios.new( f,
+ 'values' => [ 'pdf', 'eps', 'ps' ],
+ 'value' => 'pdf',
+ 'command' => lambda {
+ case 'value'
+ when 'eps'
+ $page_radio.value = 'single'
+ when 'ps'
+ $page_radio.value = 'all'
+ $bbox_check.value = '0'
+ end
+ set_widget_states
+ },
+ 'packing' => { 'side' => 'top', 'anchor' => 'w' }
+ ).pack( :side => 'bottom', :anchor => 'w' )
+ }.pack( :side => 'right', :padx => 4 ) # f: output format
+ }.pack( :side => 'top', :anchor => 'n', :fill => 'x' )
+
+ # dummy widget for extra vertical space
+ TkLabel.new( frm, :text => ' ' ).pack
+
+ $bbox_check = TkACheck.new( frm,
+ 'text' => 'Compute tight boundingbox',
+ 'value' => '0',
+ 'command' => lambda {
+ $page_radio.value = 'single' if 'value' == '1'
+ set_widget_states
+ }
+ ).pack( :side => 'top', :padx => 4, :anchor => 'w' )
+
+ TkLabel.new( frm, :text => ' ' ).pack
+
+ TkFrame.new( frm ) { |fm|
+ page_options = { 'all' => 'Convert all pages', 'single' => 'Page:' }
+ $page_radio = TkRadios.new( fm,
+ 'values' => page_options,
+ 'packing' => { 'side' => 'left', 'padx' => 4 },
+ 'value' => 'single',
+ 'command' => lambda {
+ $bbox_check.value = '0' if 'value' == 'all'
+ set_widget_states
+ }
+ ).pack( 'side' => 'left', :anchor => 'nw' )
+
+ $page_entry = TkEntry.new( fm,
+ :validate => 'focus',
+ :vcmd => [ lambda { |s|
+ ( s =~ /\d+/ ) and
+ ( s.to_i >= 1 ) and
+ ( $source.type != 'pdf' or s.to_i <= $source.npages )
+ }, "%P" ],
+ :invcmd => lambda { Tk.bell; $page_entry.focus },
+ :width => 5
+ ).pack( :side => 'left' )
+ $page_entry.delete( 0, 'end' )
+ $page_entry.insert( 'end', '1' )
+ }.pack( 'side' => 'left', :anchor => 'nw' )
+}.pack( FRM_PACK )
+
+########################################
+
+### view | open | save | done buttons
+
+TkFrame.new( $root ) { |frm|
+
+ $view_button = TkButton.new( frm,
+ :text => 'View',
+ :state => 'disabled',
+ :command => lambda {
+ # start a viewer
+ if ARCH == 'w32'
+ shell = Win32API.new("shell32", "ShellExecute",
+ ['l','p','p','p','p','l'], 'l')
+ shell.Call(0, 'open', $source.path, 0, 0, 1)
+ # shell.Call(0, 'open', $source.path, 0, 0, SW_SHOWNORMAL)
+ elsif ARCH == 'osx'
+ fork { exec "open -a Preview \"#{$source.path}\"" }
+ elsif viewable( $source )
+ viewer =
+ $source.type == 'pdf' ? $settings.pdf_viewer : $settings.ps_viewer
+ fork { exec "\"#{viewer}\" \"#{$source.path}\"" }
+ end
+ }
+ ).pack( :side=>'left', :anchor => 'w', :padx=>4, :pady=>4 )
+
+ TkFrame.new( frm ) { |fm|
+ TkButton.new( fm,
+ :text => 'Open..',
+ :command => lambda {
+ path = Tk.getOpenFile(
+ :initialdir => $defaultDir,
+ :filetypes => [
+ ['All files', '*'],
+ ['EPS', ['.eps']],
+ ['PDF', ['.pdf']],
+ ['PostScript', ['.ps']]
+ ],
+ :parent => $root
+ )
+ if path and ( not path.empty? )
+ load_file( path )
+ $defaultDir = File.expand_path( File.dirname( path ) )
+ end
+ }
+ ).pack( :side=>'left', :padx=>4, :pady=>4 )
+
+ $save_button = TkButton.new( fm,
+ :text => "Convert and save..",
+ :command => lambda {
+ $options.type = $type_radio.value
+ $options.page = \
+ ( ( $page_radio.value == 'single' ) ? $page_entry.value : nil )
+ $options.gray = ($gray_radio.value and $gray_radio.value != 'color' )
+ $options.gRAY = ($gray_radio.value and $gray_radio.value == 'gRAY' )
+ $options.bbox = ( ( $bbox_check.value == '1' ) \
+ and ( $page_radio.value == 'single' ) )
+ filetypes = case $options.type
+ when 'pdf' then [ ['Pdf', ['.pdf'] ] ]
+ when 'ps' then [ ['PostScript', ['.ps'] ] ]
+ when 'eps' then [ ['EPS (Encapsulated PostScript', ['.eps'] ] ]
+ end
+ path = nil
+ path = Tk.getSaveFile(
+ :filetypes => filetypes,
+ :parent => $root,
+ :initialdir => File.dirname( $source.path ),
+ :initialfile => File.basename( $source.path, ".*" ) +
+ '.' + $options.type,
+ :defaultextension => '.' + $options.type
+ )
+ return unless path && ! path.empty?
+ $defaultDir = File.expand_path( File.dirname( path ) )
+
+ # waitbox
+ if not $tl_wait
+ $tl_wait = TkToplevel.new( $root,
+ 'title' => 'Converting...',
+ 'geometry' =>
+ '+' + ( TkWinfo.rootx( $root ).to_i + 100 ).to_s +
+ '+' + ( TkWinfo.rooty( $root ).to_i + 100 ).to_s,
+ 'borderwidth' => 2,
+ 'relief' => 'solid'
+ )
+ $cnv_label = TkLabel.new( $tl_wait,
+ 'text' => 'converting...'
+ ).pack( 'side' => 'top' )
+ $tl_wait.overrideredirect( 1 )
+ end
+ $cnv_label.configure(
+ 'text' => "Converting #{$source.path} to \n #{path} ..."
+ )
+ $tl_wait.update
+ $tl_wait.deiconify
+ $tl_wait.raise
+ begin
+ result = $source.any_to_any( $options )
+ rescue EPCallError => exc
+ mess = "Wrong method call or conversion not supported" +
+ " or wrong page number"
+ write_log( mess + $/ +
+ exc.message + $/ + exc.backtrace.join( $/ ) )
+ Tk.messageBox(
+ 'icon' => 'error',
+ 'type' => 'ok',
+ 'parent' => $root,
+ 'message' => "#{mess}\nSee #{LOGFILE} for details."
+ )
+ rescue EPBBError => exc
+ mess = "Boundingbox problem" + $/ +
+ exc.message
+ write_log( mess + $/ + exc.backtrace.join( $/ ) )
+ Tk.messageBox(
+ 'icon' => 'error',
+ 'type' => 'ok',
+ 'parent' => $root,
+ 'message' => "#{mess}\nSee #{LOGFILE} for details."
+ )
+ rescue EPSystemError => exc
+ mess = "Problem with system call" + $/ +
+ exc.message
+ write_log( mess + $/ + exc.backtrace.join( $/ ) )
+ Tk.messageBox(
+ 'icon' => 'error',
+ 'type' => 'ok',
+ 'parent' => $root,
+ 'message' => "#{mess}\nSee #{LOGFILE} for details."
+ )
+ ensure
+ $tl_wait.withdraw
+ end
+ if result
+ ccp( result.path, path )
+ load_file( path )
+ Tk.messageBox(
+ 'icon' => 'info',
+ 'type' => 'ok',
+ 'parent' => $root,
+ 'message' => "Conversion completed"
+ )
+ end
+ }
+ ).pack( :side=>'left', :padx=>0, :pady=>4 )
+
+ TkButton.new( fm,
+ :text => "Done",
+ :command => lambda { $root.destroy }
+ ).pack( :side => 'left', :padx => 4, :pady => 4 )
+ }.pack( :side => 'right', :anchor => 'e' )
+}.pack( :side => 'bottom', :fill => 'x' )
+
+set_widget_states
+
+$root.raise
+
+Tk.mainloop
+cleantemp
diff --git a/Master/texmf-dist/scripts/epspdf/makegray.pro b/Master/texmf-dist/scripts/epspdf/makegray.pro
new file mode 100644
index 00000000000..67dc5705839
--- /dev/null
+++ b/Master/texmf-dist/scripts/epspdf/makegray.pro
@@ -0,0 +1,29 @@
+%!
+% makegray.pro, PostScript header file for grayscale conversion.
+
+%%%%%
+% Siep Kroonenberg, n dot s dot kroonenberg at rug dot nl
+% Public domain.
+%%%%%
+
+% This version only handles some basic color models,
+% and doesn't handle image data at all.
+% A more robust version would be warmly welcomed.
+
+%%%%<< /ProcessColorModel /DeviceGray >> setpagedevice
+userdict begin
+% .11*B + .59*G + .3*R
+/setrgbcolor {
+ 0.11 mul exch 0.59 mul add exch 0.3 mul add
+ systemdict begin setgray end
+} def
+% 1.0 - min(1.0, .3*C + .59*M + .11*Y + B)
+/setcmykcolor {
+ exch 0.11 mul add
+ exch 0.59 mul add
+ exch 0.3 mul add
+ dup 1 gt {pop 1} if
+ 1 exch sub
+ systemdict begin setgray end
+} def
+end