summaryrefslogtreecommitdiff
path: root/fonts/utilities/accfonts
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /fonts/utilities/accfonts
Initial commit
Diffstat (limited to 'fonts/utilities/accfonts')
-rw-r--r--fonts/utilities/accfonts/CHANGES342
-rw-r--r--fonts/utilities/accfonts/COPYING339
-rw-r--r--fonts/utilities/accfonts/CSX.def133
-rw-r--r--fonts/utilities/accfonts/ISO-Latin1.def131
-rw-r--r--fonts/utilities/accfonts/ISO-Latin2.def159
-rw-r--r--fonts/utilities/accfonts/IndUni_Omega.def491
-rw-r--r--fonts/utilities/accfonts/Norman.def176
-rw-r--r--fonts/utilities/accfonts/README458
-rw-r--r--fonts/utilities/accfonts/dvips.enc75
-rwxr-xr-xfonts/utilities/accfonts/mkt1font1012
-rwxr-xr-xfonts/utilities/accfonts/vpl2ovp1085
-rwxr-xr-xfonts/utilities/accfonts/vpl2vpl994
12 files changed, 5395 insertions, 0 deletions
diff --git a/fonts/utilities/accfonts/CHANGES b/fonts/utilities/accfonts/CHANGES
new file mode 100644
index 0000000000..039ab7709b
--- /dev/null
+++ b/fonts/utilities/accfonts/CHANGES
@@ -0,0 +1,342 @@
+Changes to vpl2vpl between first (unnumbered) release and release 0.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When I first wrote vpl2vpl I was under the impression that the vpl
+file output by afm2tfm could never contain accented character
+definitions. The first (unnumbered) release of vpl2vpl thus did not
+implement the -b option allowed for mkt1font (to block the use of
+predefined accented characters). I have since become aware that in
+the rather rare case of an afm file containing composite character
+information, afm2tfm uses that information to build definitions of
+accented characters; I have therefore introduced a -b option in
+version 0.1.
+
+There were two bugs in the coding dealing with the -s option in the
+first version of vpl2vpl. First, the shrink-factor specified by the
+user was incorrectly applied to the underdot accent as well as to
+dropped superscript accents. Second, the shrink-factor was not
+correctly scaled in terms of the value of DESIGNUNITS (this chiefly
+affected Computer Modern fonts). Both of these have been fixed in
+version 0.1.
+
+Another bug affected those characters (quotesingle, quotedbl,
+backslash, underscore, braceleft, bar and braceright) which
+dvips.enc places in the lower half of the character set, but which
+vpl2vpl removes to make room for the normal TeX inhabitants of their
+"slots"; in the first version of the program it was not possible to
+include these characters in the output font. This has also been
+fixed in version 0.1.
+
+The handling of LIGTABLE information controlling kerning etc. has
+been improved, to eliminate repeated instructions and "orphaned"
+instructions with no LABEL.
+
+In the first version of vpl2vpl I deliberately did not allow for
+double superscript accents on tall characters such as capital
+letters, on the grounds that this would be bad typographic practice.
+A specific request for one such character has led me to modify
+version 0.1 of the program to make the creation of such characters
+possible, but I would still argue against their use.
+
+Some minor improvements have been made to the code in various areas,
+including checking for inappropriate input, calculation of italic
+correction for characters with superscript accents, and placing of
+dropped superscript accents. (However, it is likely that such
+accents will still sometimes require manual intervention.)
+
+
+Changes to mkt1font between first (unnumbered) release and release 0.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the first release of mkt1font, kerning information for predefined
+accented characters was taken from the input font, even if the -b
+option had been specified to force the redefinition of such
+characters. This has been fixed in version 0.1: if the -b option is
+used, kerns for characters such as "eacute" are generalised from the
+kerns for "e" in just the same way as happens for "emacron" etc.
+
+Similarly, predefined accented characters eliminated by the -b
+option used to retain "ghost" entries among the unencoded characters
+in the afm file. This too has been fixed in version 0.1.
+
+As of version 0.1, any composite character definitions contained in
+the afm file of the input font are eliminated from the output font,
+since they will almost certainly be incomplete, and (if the user has
+specified -b) will probably be wrong as well.
+
+Version 0.1 can now properly process input fonts using MS-DOS file
+format (with newline represented by CR/LF). It can also process
+fonts in which the character "|" is used in the names of the
+frequently used "noaccess def" and "noaccess put" definitions
+(previously this fell foul of Perl's regular expression handler).
+
+As with vpl2vpl, I have modified version 0.1 of mkt1font to permit
+the creation of tall characters bearing double superscript accents,
+though I do not recommend the use of such characters.
+
+The "FontBBox" entries in the afm and pfb files now reflect any
+increase in the maximum height or depth of characters in the output
+font.
+
+Various other minor improvements have been made to the code,
+including the placing of dropped superscript accents. (As with
+vpl2vpl, however, it is likely that such accents will still
+sometimes require manual intervention.)
+
+
+Changes between release 0.1 and release 0.2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A. Changes common to both programs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+I have implemented the candrabindu ("moon-dot") accent sometimes
+used in Indian-language material. This is achieved by overprinting a
+breve with a dotaccent; a new command-line option (-c) has been
+introduced to allow for font-specific adjustments in the placing of
+the dotaccent.
+
+The user's command-line is now stored as a comment at the head of
+the output file(s).
+
+The constraint on the ordering of definitions in a definition file
+has been removed: it is no longer necessary to ensure that a
+character is defined before it is used.
+
+Digraphs are now implemented: if the character specified as the
+"accent" in a definition is not in fact a valid accent character,
+the definition is interpreted as a request for a digraph formed from
+the "character" followed by the "accent".
+
+A bug which placed superscript accents incorrectly over tall
+characters already bearing "under" accents has been fixed.
+
+The vertical positioning of "under" accents has been adjusted: they
+are now placed slightly lower than previously.
+
+
+B. Changes to vpl2vpl
+~~~~~~~~~~~~~~~~~~~~~
+
+Fixed a bug which resulted in some accents in small caps fonts being
+positioned at the wrong height.
+
+Fixed a bug which resulted in small amounts of LIGTABLE information
+being lost.
+
+
+C. Changes to mkt1font
+~~~~~~~~~~~~~~~~~~~~~~
+
+The internal organisation of the program has been cleaned up in a
+number of respects. In particular, various subroutines are now
+called with the appropriate formal parameters, rather than relying
+on the existence of equivalent global variables; the fetching and
+storing of character metric information is tidier and more
+efficient; and kerning information is dealt with in the course of
+the main program loop, rather than in a private (double) loop
+afterwards.
+
+The -s option allowing "under" accents to be shrunk by a specified
+factor, which was previously available only in vpl2vpl, has now been
+implemented in mkt1font also.
+
+The output afm file previously sometimes contained spurious entries
+for unencoded characters that duplicated items in the list of
+encoded characters. This has been fixed.
+
+Despite the fix introduced in version 0.1, some predefined kerning
+information continued to find its way into the afm file even when
+the -b option was specified to block the use of predefined accented
+characters. A new, improved fix is now in place to prevent this. An
+error in a regular expression which generated some undesirable kerns
+has also been corrected.
+
+The "FontBBox" entries in the afm and pfb files now reflect any
+increase in the maximum width of characters in the output font, as
+well as increases in their maximum height or depth.
+
+Fixed a bug causing the underbar accent to be too long.
+
+Fixed a bug causing "under" accents to be assigned the wrong depth:
+this could result in the bottom of the accent failing to print
+properly.
+
+
+Changes between release 0.2 and release 0.21
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Changes common to both programs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The vertical positioning of "under" accents has been adjusted again
+(the previous adjustment was a little too enthusiastic). They have
+been raised slightly.
+
+The height at which characters are reckoned to be so tall that
+superscript accents placed on them must be raised above the normal
+level has been increased slightly (from 1.1 x xheight to 1.15 x
+xheight).
+
+Changes between release 0.21 and release 0.211
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A. Changes to vpl2vpl
+~~~~~~~~~~~~~~~~~~~~~
+
+A single minor change has been made to vpl2vpl: this has been
+necessitated by a change in the format of the LIGTABLE information
+produced by version 8.1 of afm2tfm, which now adds identificatory
+comments to lines referring to characters by means of octal
+notation. Vpl2vpl strips out such comments.
+
+
+B. Changes to mkt1font
+~~~~~~~~~~~~~~~~~~~~~~
+
+Minor bugfixes have been put in place: extra spaces in the the
+"noaccess def" and "noaccess put" definitions are now permitted, and
+so is a character named ".null". An error message has been improved.
+
+Changes between release 0.211 and release 0.212
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A. Changes to vpl2vpl
+~~~~~~~~~~~~~~~~~~~~~
+
+Fixed a bug in the "double superscript accent on small caps
+character" routine.
+
+
+B. Changes to mkt1font
+~~~~~~~~~~~~~~~~~~~~~~
+
+Fixed a bug which produced incorrect output in cases where the
+character to be accented is defined as blank (e.g. space).
+
+Changes to between release 0.212 and release 0.22
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Changes common to both programs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The programs now recognise "commaaccent" as a valid subscript
+accent. Note that they cannot replace this subscript with the
+superscript form used with the letter "g" (any more than they can
+substitute the apostrophe-like form of the caron that is used with
+"L", "d", "l" and "t"). Note also that as there is no position for
+this accent in either the standard TeX encoding or the dvips.enc
+variant, vpl2vpl will not actually be able to use it to build new
+characters without further modification.
+
+In the case where the definition file specifies, say, "z overdot"
+and the font contains a predefined version named "zdotaccent", it
+previously happened that the output font contained both characters.
+This has been fixed: now only the character requested in the
+definition file exists in the output.
+
+Changes between release 0.22 and release 0.221
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A. Changes to mkt1font
+~~~~~~~~~~~~~~~~~~~~~~
+
+Fixed a bug which caused the program to fail after incorrectly
+identifying CharStrings definitions.
+
+Changes tbetween release 0.221 and release 0.222
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A. Changes to mkt1font
+~~~~~~~~~~~~~~~~~~~~~~
+
+Changed FamilyName to remove only the final one of a number of
+hyphenated elements from the font name.
+
+Changes between release 0.222 and release 0.23
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A. Changes to mkt1font
+~~~~~~~~~~~~~~~~~~~~~~
+
+No changes have in fact been made to mkt1font, but its version number
+has been raised to 0.23 to conform with those of vpl2vpl and vpl2ovp.
+
+B. Changes to vpl2vpl
+~~~~~~~~~~~~~~~~~~~~~
+
+A change has been introduced to permit the program to use the output
+of the AFM conversion utility afm2pl, rather than the earlier afm2tfm.
+This has been done because it has come to light that afm2tfm gives
+incorrect values for the heights of some characters, which can cause
+poor accent placement. Support for the output of afm2tfm has not been
+withdrawn, but afm2pl is now definitely preferred.
+
+B. A new program: vpl2ovp
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The greatest change as of 0.23 is the addition of a third program to
+the suite. Vpl2ovp does essentially the same job as vpl2vpl, in that
+it creates virtual fonts that contain arbitrarily accented characters,
+but its output is a .ovp file suitable for use with Omega (the 16-bit
+Unicode-aware development from TeX). Using vpl2ovp it is possible to
+build substantial Unicode-compliant virtual fonts for use with Omega,
+and a .def file for the set of characters I have included in my
+earlier "IndUni" OpenType fonts is now included in the distribution.
+(IndUni virtual fonts for Omega created with vpl2ovp are available at
+http://bombay.indology.info/software/fonts/induni/index.html.) Glyphs
+representing characters requiring more than a single codepoint are
+stored in the Private Use Area, and a system of ligatures is provided
+to allow them to be accessed. This system also permits
+single-codepoint accented characters to be accessed through their
+"decomposed" component parts. Thus if the characters a-macron (single
+codepoint: U+0101) and a-macron-acute (two codepoints: U+0101 +
+U+0301) are defined, the former will be accessible both as U+0101
+(a-macron) and as U+0061 + U+0304 ("a" + macron); the latter will be
+accessible both as U+0101 + U+0301 (a-macron + acute) and U+0061 +
+U+0304 + U+0301 ("a" + macron + acute). This is a considerable
+advantage, given the different possible ways in which Unicode can be,
+and is, used.
+
+Changes between release 0.23 and release 0.24
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A. Changes to mkt1font
+~~~~~~~~~~~~~~~~~~~~~~
+
+The format expected of glyph names has been brought into line with
+Adobe's specification, i.e. they may contain upper- and lower-case
+letters, numerals, "_" and ".", but must begin with a letter or with
+"_". The format expected of PFB head and tail material has been made
+less restrictive, to match the realities of perceived usage. A bug in
+digraph creation has been fixed. A "dotlessj" character is created for
+use with superscript accents. Full Flex hinting is now supported.
+
+B. Changes to vpl2vpl
+~~~~~~~~~~~~~~~~~~~~~
+
+The help information has been improved.
+
+C. Changes to vpl2ovp
+~~~~~~~~~~~~~~~~~~~~~
+
+A bug has been fixed that generated "ghost" replicas of some existing
+accent characters in the Private Use Area. The handling of digraphs
+and underscored digraphs has been brought into better Unicode
+compliance. The help information has also been improved.
+
+Changes between release 0.24 and release 0.25
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A. Changes to mkt1font
+~~~~~~~~~~~~~~~~~~~~~~
+
+Various bugs have been fixed. Rounding of non-integer values to
+integers has been improved.
+
+B. Changes to vpl2vpl
+~~~~~~~~~~~~~~~~~~~~~
+
+No changes have in fact been made to vpl2vpl or vpl2ovp, but their
+version number has been raised to 0.25 to conform with that of
+mkt1font.
diff --git a/fonts/utilities/accfonts/COPYING b/fonts/utilities/accfonts/COPYING
new file mode 100644
index 0000000000..a43ea2126f
--- /dev/null
+++ b/fonts/utilities/accfonts/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, 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., 675 Mass Ave, Cambridge, MA 02139, 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/fonts/utilities/accfonts/CSX.def b/fonts/utilities/accfonts/CSX.def
new file mode 100644
index 0000000000..be299b77fc
--- /dev/null
+++ b/fonts/utilities/accfonts/CSX.def
@@ -0,0 +1,133 @@
+# CSX encoding for mkt1font and vpl2vpl
+#
+# Classical Sanskrit eXtended encoding for the representation of
+# Indian languages in Roman script
+
+128 C cedilla
+129 u dieresis
+130 e acute
+131 a circumflex
+132 a dieresis
+133 a grave
+134 a ring
+135 c cedilla
+136 e circumflex
+137 e dieresis
+138 e grave
+139 i dieresis
+140 i circumflex
+141 i grave
+142 A dieresis
+143 A ring
+144 E acute
+145 ae
+146 AE
+147 o circumflex
+148 o dieresis
+149 o grave
+150 u circumflex
+151 u grave
+152 y dieresis
+153 O dieresis
+154 U dieresis
+155 cent
+156 sterling
+157 yen
+158 .notdef
+159 r underbar
+160 a acute
+161 i acute
+162 o acute
+163 u acute
+164 n tilde
+165 N tilde
+166 l tilde
+167 m overdot
+168 amacron breve
+169 imacron breve
+170 umacron breve
+171 amacron tilde
+172 imacron tilde
+173 n underbar
+174 guillemotleft
+175 guillemotright
+176 .notdef
+177 .notdef
+178 .notdef
+179 .notdef
+180 .notdef
+181 amacron acute
+182 amacron grave
+183 imacron acute
+184 imacron grave
+185 .notdef
+186 .notdef
+187 .notdef
+188 .notdef
+189 umacron acute
+190 umacron grave
+191 .notdef
+192 .notdef
+193 .notdef
+194 .notdef
+195 .notdef
+196 .notdef
+197 .notdef
+198 runderdot acute
+199 runderdot grave
+200 .notdef
+201 .notdef
+202 .notdef
+203 .notdef
+204 .notdef
+205 .notdef
+206 .notdef
+207 runderdotmacron acute
+208 a tilde
+209 i tilde
+210 u tilde
+211 e tilde
+212 o tilde
+213 e breve
+214 o breve
+215 l underbar
+216 umacron tilde
+217 .notdef
+218 .notdef
+219 .notdef
+220 .notdef
+221 .notdef
+222 .notdef
+223 .notdef
+224 a macron
+225 germandbls
+226 A macron
+227 i macron
+228 I macron
+229 u macron
+230 U macron
+231 r underdot
+232 R underdot
+233 runderdot macron
+234 Runderdot macron
+235 l underdot
+236 L underdot
+237 lunderdot macron
+238 Lunderdot macron
+239 n overdot
+240 N overdot
+241 t underdot
+242 T underdot
+243 d underdot
+244 D underdot
+245 n underdot
+246 N underdot
+247 s acute
+248 S acute
+249 s underdot
+250 S underdot
+251 .notdef
+252 m underdot
+253 M underdot
+254 h underdot
+255 H underdot
diff --git a/fonts/utilities/accfonts/ISO-Latin1.def b/fonts/utilities/accfonts/ISO-Latin1.def
new file mode 100644
index 0000000000..7221082541
--- /dev/null
+++ b/fonts/utilities/accfonts/ISO-Latin1.def
@@ -0,0 +1,131 @@
+# ISO-Latin1 encoding (iso8859-1) for mkt1font and vpl2vpl
+
+127 .notdef
+128 .notdef
+129 .notdef
+130 .notdef
+131 .notdef
+132 .notdef
+133 .notdef
+134 .notdef
+135 .notdef
+136 .notdef
+137 .notdef
+138 .notdef
+139 .notdef
+140 .notdef
+141 .notdef
+142 .notdef
+143 .notdef
+144 dotlessi
+145 grave
+146 acute
+147 circumflex
+148 tilde
+149 .notdef
+150 breve
+151 dotaccent
+152 .notdef
+153 .notdef
+154 ring
+155 .notdef
+156 .notdef
+157 hungarumlaut
+158 ogonek
+159 caron
+160 .notdef
+161 exclamdown
+162 cent
+163 sterling
+164 currency
+165 yen
+166 brokenbar
+167 section
+168 dieresis
+169 copyright
+170 ordfeminine
+171 guillemotleft
+172 logicalnot
+173 hyphen
+174 registered
+175 macron
+176 degree
+177 plusminus
+178 twosuperior
+179 threesuperior
+180 acute
+181 mu
+182 paragraph
+183 periodcentered
+184 cedilla
+185 onesuperior
+186 ordmasculine
+187 guillemotright
+188 onequarter
+189 onehalf
+190 threequarters
+191 questiondown
+192 A grave
+193 A acute
+194 A circumflex
+195 A tilde
+196 A dieresis
+197 A ring
+198 AE
+199 C cedilla
+200 E grave
+201 E acute
+202 E circumflex
+203 E dieresis
+204 I grave
+205 I acute
+206 I circumflex
+207 I dieresis
+208 Eth
+209 N tilde
+210 O grave
+211 O acute
+212 O circumflex
+213 O tilde
+214 O dieresis
+215 multiply
+216 Oslash
+217 U grave
+218 U acute
+219 U circumflex
+220 U dieresis
+221 Y acute
+222 Thorn
+223 germandbls
+224 a grave
+225 a acute
+226 a circumflex
+227 a tilde
+228 a dieresis
+229 a ring
+230 ae
+231 c cedilla
+232 e grave
+233 e acute
+234 e circumflex
+235 e dieresis
+236 i grave
+237 i acute
+238 i circumflex
+239 i dieresis
+240 eth
+241 n tilde
+242 o grave
+243 o acute
+244 o circumflex
+245 o tilde
+246 o dieresis
+247 divide
+248 oslash
+249 u grave
+250 u acute
+251 u circumflex
+252 u dieresis
+253 y acute
+254 thorn
+255 y dieresis
diff --git a/fonts/utilities/accfonts/ISO-Latin2.def b/fonts/utilities/accfonts/ISO-Latin2.def
new file mode 100644
index 0000000000..736906f016
--- /dev/null
+++ b/fonts/utilities/accfonts/ISO-Latin2.def
@@ -0,0 +1,159 @@
+# ISO-Latin2 encoding (iso8859-2) for mkt1font and vpl2vpl
+
+# This document is a modified version of Jan "Yenya" Kasprzak's
+# mpage filter ISO-Latin.2. Yenya writes as follows:
+
+#% Wed Dec 7 14:43:55 MET 1994
+#% Written by Jan "Yenya" Kasprzak (kas@foresta.cz, kas@muni.cz) for mpage
+#% filter. ISO Latin 2 (aka iso8859-2) is a character set, used in some
+#% Middle- and East European countries (Czech republic, Slovakia, Poland,
+#% Slovenia, Hungary, and some other -- I don't remember right now).
+#%
+#% You can redistribute this file under the terms of GNU General
+#% Public License (GPL). If you have not your own copy of GPL,
+#% mail me, I will send you one.
+#% -Yenya
+#%
+#% This encoding vector describes real 8859-2 encoding, except of
+#% some little differences: I was not able to find how to name characters,
+#% which have accent shaped as right quote. Instead of these characters
+#% I put there character with caron accent. If you find out how to name
+#% characters with "right quote" accent, mail me. Or you can change it
+#% yourself. You must change the following characters:
+#%
+#% lcaron -> l with right quote,
+#% Lcaron -> L --''--
+#% tcaron -> L --''--
+#% dcaron -> L --''--
+#%
+#% Tcaron and Dcaron are written with a _real_ caron.
+
+127 .notdef
+128 .notdef
+129 .notdef
+130 .notdef
+131 .notdef
+132 .notdef
+133 .notdef
+134 .notdef
+135 .notdef
+136 .notdef
+137 .notdef
+138 .notdef
+139 .notdef
+140 .notdef
+141 .notdef
+142 .notdef
+143 .notdef
+144 dotlessi
+145 grave
+146 acute
+147 circumflex
+148 tilde
+149 .notdef
+150 breve
+151 .notdef
+152 .notdef
+153 .notdef
+154 ring
+155 .notdef
+156 .notdef
+157 hungarumlaut
+158 ogonek
+159 caron
+160 .notdef
+161 A ogonek
+162 breve
+163 Lslash
+164 currency
+165 L caron # ? -- See above
+166 S acute
+167 section
+168 dieresis
+169 S caron
+170 S cedilla
+171 T caron
+172 Z acute
+173 hyphen
+174 Z caron
+175 Z dotaccent
+176 degree
+177 a ogonek
+178 ogonek
+179 lslash
+180 acute
+181 l caron # ? -- See above
+182 s acute
+183 circumflex
+184 cedilla
+185 s caron
+186 s cedilla
+187 t caron # ? -- See above
+188 z acute
+189 hungarumlaut
+190 z caron
+191 z dotaccent
+192 R acute
+193 A acute
+194 A circumflex
+195 A breve
+196 A dieresis
+197 L acute
+198 C acute
+199 C cedilla
+200 C caron
+201 E acute
+202 E ogonek
+203 E dieresis
+204 E caron
+205 I acute
+206 I circumflex
+207 D caron
+208 Eth
+209 N acute
+210 N caron
+211 O acute
+212 O circumflex
+213 O hungarumlaut
+214 O dieresis
+215 multiply
+216 R caron
+217 U ring
+218 U acute
+219 U hungarumlaut
+220 U dieresis
+221 Y acute
+222 T cedilla
+223 germandbls
+224 r acute
+225 a acute
+226 a circumflex
+227 a breve
+228 a dieresis
+229 l acute
+230 c acute
+231 c cedilla
+232 c caron
+233 e acute
+234 e ogonek
+235 e dieresis
+236 e caron
+237 i acute
+238 i circumflex
+239 d caron # ? -- See above
+240 eth
+241 n acute
+242 n caron
+243 o acute
+244 o circumflex
+245 o hungarumlaut
+246 o dieresis
+247 divide
+248 r caron
+249 u ring
+250 u acute
+251 u hungarumlaut
+252 u dieresis
+253 y acute
+254 t cedilla
+255 dotaccent
diff --git a/fonts/utilities/accfonts/IndUni_Omega.def b/fonts/utilities/accfonts/IndUni_Omega.def
new file mode 100644
index 0000000000..dee9c2850d
--- /dev/null
+++ b/fonts/utilities/accfonts/IndUni_Omega.def
@@ -0,0 +1,491 @@
+# IndUni encoding for mkt1font and vpl2vpl
+#
+# This version designed for use with Omega
+#
+# Characters are intended to represent a complete
+# set of those required for use with Indian languages in
+# transliteration, together with others commonly needed
+# in the same environment. The "non-Indian" characters
+# form an almost complete implementation on MES1, but
+# are limited by the fact that some glyphs, though
+# present in later versions of the URW++ fonts, are not
+# present in all, and anyway cannot readily be accessed.
+# Such items are included in this list but commented out.
+
+# ASCII: I should probably put in a complete list, or at least
+# notdef the control codes and return other odds and ends to
+# ASCII normality. I would need to know Omega policies here.
+
+0x007f .notdef
+
+# ISO-Latin1
+
+0x0080 .notdef
+0x0081 .notdef
+0x0082 .notdef
+0x0083 .notdef
+0x0084 .notdef
+0x0085 .notdef
+0x0086 .notdef
+0x0087 .notdef
+0x0088 .notdef
+0x0089 .notdef
+0x008a .notdef
+0x008b .notdef
+0x008c .notdef
+0x008d .notdef
+0x008e .notdef
+0x008f .notdef
+0x0090 .notdef
+0x0091 .notdef
+0x0092 .notdef
+0x0093 .notdef
+0x0094 .notdef
+0x0095 .notdef
+0x0096 .notdef
+0x0097 .notdef
+0x0098 .notdef
+0x0099 .notdef
+0x009a .notdef
+0x009b .notdef
+0x009c .notdef
+0x009d .notdef
+0x009e .notdef
+0x009f .notdef
+0x00a0 space
+0x00a1 exclamdown
+0x00a2 cent
+0x00a3 sterling
+0x00a4 currency
+0x00a5 yen
+#0x00a6 brokenbar
+0x00a7 section
+0x00a8 dieresis
+#0x00a9 copyright
+0x00aa ordfeminine
+0x00ab guillemotleft
+#0x00ac logicalnot
+0x00ad hyphen
+#0x00ae registered
+0x00af macron
+#0x00b0 degree
+#0x00b1 plusminus
+#0x00b2 twosuperior
+#0x00b3 threesuperior
+0x00b4 acute
+#0x00b5 mu
+0x00b6 paragraph
+0x00b7 periodcentered
+0x00b8 cedilla
+#0x00b9 onesuperior
+0x00ba ordmasculine
+0x00bb guillemotright
+#0x00bc onequarter
+#0x00bd onehalf
+#0x00be threequarters
+0x00bf questiondown
+0x00c0 A grave
+0x00c1 A acute
+0x00c2 A circumflex
+0x00c3 A tilde
+0x00c4 A dieresis
+0x00c5 A ring
+0x00c6 AE
+0x00c7 C cedilla
+0x00c8 E grave
+0x00c9 E acute
+0x00ca E circumflex
+0x00cb E dieresis
+0x00cc I grave
+0x00cd I acute
+0x00ce I circumflex
+0x00cf I dieresis
+#0x00d0 Eth
+0x00d1 N tilde
+0x00d2 O grave
+0x00d3 O acute
+0x00d4 O circumflex
+0x00d5 O tilde
+0x00d6 O dieresis
+#0x00d7 multiply
+0x00d8 Oslash
+0x00d9 U grave
+0x00da U acute
+0x00db U circumflex
+0x00dc U dieresis
+0x00dd Y acute
+#0x00de Thorn
+0x00df germandbls
+0x00e0 a grave
+0x00e1 a acute
+0x00e2 a circumflex
+0x00e3 a tilde
+0x00e4 a dieresis
+0x00e5 a ring
+0x00e6 ae
+0x00e7 c cedilla
+0x00e8 e grave
+0x00e9 e acute
+0x00ea e circumflex
+0x00eb e dieresis
+0x00ec i grave
+0x00ed i acute
+0x00ee i circumflex
+0x00ef i dieresis
+#0x00f0 eth
+0x00f1 n tilde
+0x00f2 o grave
+0x00f3 o acute
+0x00f4 o circumflex
+0x00f5 o tilde
+0x00f6 o dieresis
+#0x00f7 divide
+0x00f8 oslash
+0x00f9 u grave
+0x00fa u acute
+0x00fb u circumflex
+0x00fc u dieresis
+0x00fd y acute
+#0x00fe thorn
+0x00ff y dieresis
+
+# Bare accents.
+
+0x0327 cedilla
+0x0328 ogonek
+#0x0326 commaaccent
+0x0301 acute
+0x0300 grave
+0x0302 circumflex
+0x0303 tilde
+0x0304 macron
+0x0306 breve
+0x0307 space overdot
+0x0308 dieresis
+0x030a ring
+0x030b hungarumlaut
+0x030c caron
+0x0310 space candrabindu
+0x0331 space underbar
+0x032e space underbreve
+0x0324 space underdieresis
+0x0323 space underdot
+0x0325 space underring
+
+# Indian etc. characters
+
+0x0102 A breve
+0x01cd A caron
+0x0100 A macron
+#0x0104 A ogonek
+0x01fc AE acute
+0x01e2 AE macron
+0xe000 Amacron tilde
+0xe001 Atilde acute
+0x0106 C acute
+0x010c C caron
+0x0108 C circumflex
+0xe002 C macron
+0x010a C overdot
+0xe003 C underdot
+#0x010E D caron
+0x1e0c D underdot
+0xe004 Dunderdot acute
+#0x0110 Dcroat
+0x0114 E breve
+0x011a E caron
+0x0112 E macron
+0x1ebc E tilde
+#0x0118 E ogonek
+0x0116 E overdot
+0xe006 Emacron tilde
+0xe005 Etilde acute
+0xe007 G acute
+#0x0122 G cedilla
+0x0120 G overdot
+0xe008 Gacute macron
+0xe009 H acute
+0x0124 H circumflex
+0xe00b H underbar
+0x1e2a H underbreve
+0xe00a H underdieresis
+0x1e24 H underdot
+#0x0126 Hbar
+0x012c I breve
+0x01cf I caron
+#0x012e I ogonek
+0x012a I macron
+0x0130 I overdot
+0x0128 I tilde
+0xe00d Imacron tilde
+0xe00c Itilde acute
+#0x0132 IJ
+0x0134 J circumflex
+0xe00f J caron
+0xe00e J macron
+0xe05e K underdot
+#0x0136 K cedilla
+0xe012 K h
+0xe010 K H
+0x1e34 K underbar
+0xe013 Kh underbar
+0xe011 KH underbar
+0x0139 L acute
+#0x013d L caron
+#0x013b L cedilla
+0x1e3a L underbar
+0x1e36 L underdot
+0xe014 L underring
+#0x013f L middot
+0x0141 Lslash
+0x1e38 Lunderdot macron
+0xe015 Lunderring macron
+0xe016 M breve
+0xe017 M candrabindu
+0x1e40 M overdot
+0x1e42 M underdot
+0x0143 N acute
+0xe018 N breve
+0x0147 N caron
+0x1e44 N overdot
+#0x0145 N cedilla
+0x1e48 N underbar
+0x1e46 N underdot
+#0x014a Eng
+0x014e O breve
+0x01d1 O caron
+0x014c O macron
+0x0150 O hungarumlaut
+0x0152 OE
+0xe019 Omacron tilde
+0x1e4c Otilde acute
+0x1e54 P acute
+0x0154 R acute
+0xe01a R breve
+0x0158 R caron
+#0x0156 R cedilla
+0x1e5e R underbar
+0x1e5a R underdot
+0xe01b R underring
+0x1e5c Runderdot macron
+0xe01c Runderring macron
+0x015a S acute
+0x015c S circumflex
+0x0160 S caron
+0x015e S cedilla
+0xe020 S underbar
+0xe01f S underdieresis
+0x1e62 S underdot
+0xe01d Sacute macron
+0xe01e Sunderdot macron
+#0x0164 T caron
+0x0162 T cedilla
+#0x0166 Tcroat
+0x1e6e T underbar
+0xe022 T underdieresis
+0x1e6c T underdot
+0xe021 Tunderdot acute
+0x016c U breve
+0x01d3 U caron
+0x016a U macron
+0x016e U ring
+0x0170 U hungarumlaut
+#0x0172 U ogonek
+0x0168 U tilde
+0x01d7 Udieresis acute
+0x01d9 Udieresis caron
+0x01db Udieresis grave
+0x01d5 Udieresis macron
+0xe023 Umacron tilde
+0x1e78 Utilde acute
+0xe024 V acute
+0x0174 W circumflex
+0x1e88 W underdot
+0x0176 Y circumflex
+0x0178 Y dieresis
+0x1e8e Y overdot
+0x0179 Z acute
+0x017d Z caron
+0x017b Z overdot
+0x1e94 Z underbar
+0xe025 Z underdieresis
+0x1e92 Z underdot
+0x0103 a breve
+0x01ce a caron
+0x0101 a macron
+#0x0105 a ogonek
+0x01fd ae acute
+0x01e3 ae macron
+0xe026 amacron acute
+0xe029 amacron breve
+0xe027 amacron grave
+0xe028 amacron tilde
+0xe02a atilde acute
+0x0107 c acute
+0x010d c caron
+0x0109 c circumflex
+0xe02b c macron
+0x010b c overdot
+0xe02c c underdot
+#0x010f d caron
+#0x0111 dcroat
+0x1e0d d underdot
+0xe02d dunderdot acute
+0x0115 e breve
+0x011b e caron
+0x0113 e macron
+0x1ebd e tilde
+0x0117 e overdot
+#0x0119 e ogonek
+0xe02f emacron acute
+0xe031 emacron breve
+0xe030 emacron tilde
+0xe02e etilde acute
+0xe032 g acute
+0x0121 g overdot
+#0x0123 g cedilla
+0xe033 gacute macron
+0xe034 h acute
+0x0125 h circumflex
+0x1e96 h underbar
+0x1e2b h underbreve
+0xe035 h underdieresis
+0x1e25 h underdot
+#0x0127 hbar
+0x012d i breve
+0x01d0 i caron
+0x012b i macron
+0x0129 i tilde
+#0x012f i ogonek
+0xe036 imacron acute
+0xe039 imacron breve
+0xe037 imacron grave
+0xe038 imacron tilde
+0xe03a itilde acute
+0x0131 dotlessi
+#0x0133 ij
+0x0135 j circumflex
+0x01f0 j caron
+0xe03b j macron
+#0x0137 k cedilla
+0xe05f k underdot
+0xe03c k h
+0x1e35 k underbar
+0xe03d kh underbar
+#0x0138 kra (Greenlandic)
+0x013a l acute
+#0x013e l caron
+#0x013c l cedilla
+#0x0140 l middot
+0xe03e l tilde
+0x1e3b l underbar
+0x1e37 l underdot
+0xe040 l underring
+0x0142 lslash
+0xe03f lunderdot acute
+0x1e39 lunderdot macron
+0xe041 lunderring acute
+0xe042 lunderring macron
+0xe043 m breve
+0xe044 m candrabindu
+0x1e41 m overdot
+0x1e43 m underdot
+0x0144 n acute
+0x0148 n caron
+#0x0146 n cedilla
+0xe045 n breve
+0x1e45 n overdot
+0x1e49 n underbar
+0x1e47 n underdot
+#0x0149 n apostophe
+#0x014b eng
+0x014f o breve
+0x01d2 o caron
+0x014d o macron
+0x0151 o hungarumlaut
+0x0153 oe
+0xe047 omacron breve
+0xe046 omacron tilde
+0x1e4d otilde acute
+0x1e55 p acute
+0x0155 r acute
+0xe048 r breve
+0x0159 r caron
+#0x0156 r cedilla
+0x1e5f r underbar
+0xe04c r underdieresis
+0x1e5b r underdot
+0xe04d r underring
+0xe049 runderdot acute
+0xe04a runderdot grave
+0x1e5d runderdot macron
+0xe04b runderdotmacron acute
+0xe04e runderring acute
+0xe04f runderring grave
+0xe050 runderring macron
+0xe051 runderringmacron acute
+0x015b s acute
+0x015d s circumflex
+0x015f s cedilla
+0x0161 s caron
+0xe055 s underbar
+0xe054 s underdieresis
+0x1e63 s underdot
+0xe052 sacute macron
+0xe053 sunderdot macron
+#0x0165 t caron
+0x0163 t cedilla
+0x1e6f t underbar
+0xe057 t underdieresis
+0x1e6d t underdot
+0xe056 tunderdot acute
+#0x0167 tcroat
+0x016d u breve
+0x01d4 u caron
+0x016b u macron
+0x016f u ring
+0x0169 u tilde
+0x0171 u hungarumlaut
+#0x0173 u ogonek
+0x01d8 udieresis acute
+0x01da udieresis caron
+0x01dc udieresis grave
+0x01d6 udieresis macron
+0xe058 umacron acute
+0xe05b umacron breve
+0xe059 umacron grave
+0xe05a umacron tilde
+0x1e79 utilde acute
+0xe05c v acute
+0x0175 w circumflex
+0x1e89 w underdot
+0x0177 y circumflex
+0x1e8f y overdot
+0x017a z acute
+0x017e z caron
+0x017c z overdot
+0x1e95 z underbar
+0xe05d z underdieresis
+0x1e93 z underdot
+
+# Odds and ends
+
+0x2002 bullet
+0x2020 dagger
+0x2021 daggerdbl
+0x2026 ellipsis
+0x2014 emdash
+0x2013 endash
+0x0192 florin
+0x2039 guilsinglleft
+0x203a guilsinglright
+#0x2212 minus
+0x2030 perthousand
+0x201e quotedblbase
+0x201c quotedblleft
+0x201d quotedblright
+0x2018 quoteleft
+0x2019 quoteright
+0x201a quotesinglbase
+0x0027 quotesingle
+#0x2122 trademark
diff --git a/fonts/utilities/accfonts/Norman.def b/fonts/utilities/accfonts/Norman.def
new file mode 100644
index 0000000000..b934f46bba
--- /dev/null
+++ b/fonts/utilities/accfonts/Norman.def
@@ -0,0 +1,176 @@
+# Norman encoding for mkt1font and vpl2vpl
+#
+# Encoding devised by Prof. K. R. Norman for the representation of
+# Indian languages in Roman script
+
+# Chars 0-31
+
+0 .notdef
+1 Eth
+2 eth
+3 Lslash
+4 lslash
+5 S caron
+6 s caron
+7 Y acute
+8 y acute
+9 .notdef
+10 .notdef
+11 Thorn
+12 thorn
+13 .notdef
+14 Z caron
+15 z caron
+16 .notdef
+17 asciitilde
+18 j macron # j is dotless in Normyn
+19 circumflex
+20 tilde
+21 onehalf
+22 onequarter
+23 onesuperior
+24 threequarters
+25 threesuperior
+26 twosuperior
+27 brokenbar
+28 minus
+29 multiply
+30 .notdef
+31 .notdef
+
+# Changes from ASCII in range 32-127
+
+39 quotesingle
+94 circumflex
+96 grave
+
+# Chars 128-255
+
+128 A dieresis
+129 A ring
+130 imacron tilde
+131 E acute
+132 N tilde
+133 O dieresis
+134 U dieresis
+135 a acute
+136 a grave
+137 a circumflex
+138 a dieresis
+139 a tilde
+140 a macron
+141 c cedilla
+142 e acute
+143 e grave
+144 e circumflex
+145 e dieresis
+146 i acute
+147 i grave
+148 i circumflex
+149 i dieresis
+150 n tilde
+151 o acute
+152 o grave
+153 o circumflex
+154 o dieresis
+155 o tilde
+156 u acute
+157 u grave
+158 u circumflex
+159 u dieresis
+160 t underdot # see also 173, 202
+161 degree
+162 e tilde
+163 sterling
+164 section
+165 runderdot macron # runderring macron in Normyn
+166 paragraph
+167 s acute
+168 r underdot
+169 s caron
+170 umacron breve
+171 acute
+172 dieresis
+173 t underdot # notequal in Normyn
+174 AE
+175 o macron
+176 i tilde
+177 plusminus
+178 amacron acute
+179 umacron acute
+180 i macron
+181 m underdot
+182 d underdot
+183 s underdot
+184 emacron acute
+185 z acute
+186 n overdot
+187 emacron breve
+188 omacron breve
+189 u tilde
+190 ae
+191 oslash
+192 macron breve
+193 amacron breve
+194 l underdot
+195 j macron # j is dotless in Normyn
+196 a breve
+197 u breve
+198 amacron tilde
+199 imacron acute
+200 M underdot
+201 ellipsis
+202 .notdef # t underdot in PC Normyn
+203 A grave
+204 A tilde
+205 O tilde
+206 m breve
+207 oe
+208 endash
+209 emdash
+210 quotedblleft
+211 quotedblright
+212 quoteleft
+213 quoteright
+214 l underring
+215 m overdot
+216 n breve
+217 multiply
+218 runderdotmacron acute # runderringmacron acute in Normyn
+219 r underring
+220 N overdot
+221 S underdot
+222 H underdot
+223 D underdot
+224 daggerdbl
+225 runderdot acute # runderring acute in Normyn
+226 L underdot
+227 e macron
+228 imacron breve
+229 r underbar
+230 r underdieresis
+231 I macron
+232 u macron
+233 T underdot
+234 S acute
+235 dagger
+236 e breve
+237 o breve
+238 A macron
+239 N underdot
+240 umacron tilde
+241 l underbar
+242 U macron
+243 Z acute
+244 R underdot # R underring in Normyn
+245 dotlessi
+246 n underdot
+247 n underbar
+248 macron
+249 breve
+250 h underdot
+251 i breve
+252 cedilla
+253 hungarumlaut
+254 ogonek
+255 caron
diff --git a/fonts/utilities/accfonts/README b/fonts/utilities/accfonts/README
new file mode 100644
index 0000000000..79431d7653
--- /dev/null
+++ b/fonts/utilities/accfonts/README
@@ -0,0 +1,458 @@
+
+
+ Mkt1font, vpl2vpl and vpl2ovp: programs to generate accented fonts
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ John D. Smith
+ ~~~~~~~~~~~~~
+
+
+These three programs, all made available under the GNU General Public
+License, address the same requirement using the same basic algorithms:
+their aim is to make it easy to create versions of existing fonts
+containing whatever accented characters the user may need, arranged
+according to whatever encoding he/she may favour. Mkt1font does this
+by reading in the two files that define a Type 1 PostScript font and
+writing out new versions of them; vpl2vpl does it by reading in the
+file that defines a TeX virtual font and writing out a new version of
+it; vpl2ovp does the same as vpl2vpl, but its output is a 16-bit
+virtual font suitable for Omega, the Unicode-aware development from
+TeX. In each case information about what accented characters are
+required and where they should be located is supplied by means of a
+simple definition file, which has the same format for both programs.
+
+Note that most Type 1 PostScript fonts are commercial products
+subject to both copyright and licensing restrictions. If the license
+for such a font forbids reverse-engineering it, it is presumably
+illegal to run mkt1font on it; in any case it would certainly be a
+serious breach of copyright to make modified versions of the font
+available to third parties. The author of mkt1font will not be held
+responsible for any such misuses of the software. (No such legal
+problems surround the use of TeX virtual fonts, which merely specify
+new ways to use existing fonts.) However, would-be users may wish to
+note the existence of a body of high-quality freeware lookalikes for
+many of the standard Type 1 fonts: like mkt1font and vpl2vpl, the
+Ghostscript fonts developed by URW++ Design and Development
+Incorporated are made available under the GNU General Public License
+(see the file COPYING), which permits them to be modified and
+redistributed provided that certain simple decencies are observed.
+These fonts are available from many ftp sites, including those
+forming the Comprehensive TeX Archive Network (CTAN), for example
+ftp.tex.ac.uk: look for the most recent font archive file in the
+directory /tex-archive/support/ghostscript/gnu/fonts.
+
+A detailed specification of the form of the definition file used by
+mkt1font and vpl2vpl is given below in the instructions for using the
+programs, but it may be helpful to give a quick idea of its contents
+here. Each line of the file contains something similar to "128 x
+acute", which is an instruction to create a new character formed from
+"x" with an acute accent and located at position 128 in the character
+set. Once a new character has been defined in this way, it "exists" in
+just the same way as any other character, under the name "xacute" (or
+whatever); thus it can even receive further accents. The two lines
+
+ 129 e macron
+ 130 emacron breve
+
+will create a "long e" and a "long-or-short e" at the positions
+specified. (If only the latter is desired, they can both be assigned
+the same position in the encoding -- the second will overwrite the
+first.) Subscript as well as superscript accents are available. Some
+sample definition files are included to give an idea of the format:
+note that two of these (CSX.def and Norman.def), used for Indian
+language material in Roman script, contain the triple-accented
+character "runderdotmacron acute"!
+
+In addition to accented characters proper, both programs can produce
+digraphs -- single characters composed of pairs of other characters.
+In itself this may seem to be of limited use, since the digraph
+should always be indistinguishable from its two constituent
+characters printed consecutively. However, some Unicode-style
+encodings require that certain character-pairs be treated as
+digraphs. In addition, use of a digraph in subsequent definitions
+allows an accent to be applied to two characters as a pair: so, for
+example,
+
+ 131 k h
+ 131 kh underbar
+
+will produce a character consisting of an underlined "kh" at
+position 131.
+
+The algorithms used in both programs take great care to secure the
+most attractive results, placing accents centrally over/under their
+characters at appropriate heights/depths, varying their position
+according to the angle of slant in Italic and similar fonts,
+providing new characters with kerning information (which will be
+resolutely ignored by most word-processors), and -- in the case of
+mkt1font -- giving hinting instructions to improve output on
+low-resolution printers. However, users may feel that some
+characters need "tweaking". This tends to happen when the part of
+the character adjacent to the accent is highly asymmetrical:
+subscript accents below "r" may need moving to the left, while
+superscript accents above "d" may need moving to the right. It is
+relatively easy to modify the output of vpl2vpl to make such
+improvements by hand (vpl files are designed to be easy for humans
+to read, and vpl2vpl identifies each character with a comment). Type
+1 fonts are another matter; mkt1font generates a human-readable and
+commented ".dis" file as well as the ".pfb" font file, and it is
+possible to make changes to this and rebuild the pfb file with t1asm
+(see below), but this is not quite as simple as modifying a TeX
+virtual font.
+
+For details on how vpl2ovp handles access to accented characters by
+means of a system of ligatures, see further the CHANGES file.
+
+The programs are written in Perl, and have not been tested on
+systems other than Unix. (Apart from the #! line at the top, the
+only Unix specificities the author is aware of are two references to
+"/dev/null" in mkt1font and the general assumption that filenames
+can be of any length.) At run time, mkt1font invokes two further
+font utilities, t1asm and t1disasm, written by I. Lee Hetherington
+and available from CTAN ftp sites: look in the directory
+/tex-archive/fonts/utilities/t1utils.
+
+Detailed instructions for using the programs follow. In each case
+these instructions can also be seen by typing the name of the program
+with a "-h" option.
+
+
+Mkt1font
+~~~~~~~~
+Syntax: mkt1font -n fontname -d definition-file -a afm-file -f font-file
+ [-s shrink-factor] [-c candrabindu-adjustment] [-b]
+
+Mkt1font creates new Type 1 PostScript fonts based on existing fonts
+("input fonts"). In order to do this it makes use of I. Lee
+Hetherington's programs t1asm and t1disasm, which must be present on
+the system. A successful run will generate an AFM file and a PFB
+file, as well as a DIS file containing a disassembled version of the
+PFB file (including useful comments). Four options must be specified
+on the command line, as follows:
+
+ -n should name the font it is intended to generate. Avoid names
+ such as "myfont", as both mkt1font and other programs attempt
+ to draw conclusions from the name; better would be something
+ like "Utopia_French-BoldItalic". The generated font files
+ will also use this for their basename.
+
+ -d should refer to a font definition file. This file (which could
+ usefully be named, e.g., "French.def") should consist of
+ lines of character definitions, in the form
+ "number" "character"
+ or
+ "number" "character" "accent"
+ Here "number" represents the character's position in the new
+ encoding and may be expressed in decimal, octal or hex;
+ "character" names the character (e.g. "comma", "eight",
+ "A") or consists of the word ".notdef" (indicating that
+ the specified number's "slot" in the new encoding is to be
+ empty); and "accent" optionally names an accent to be placed
+ on the character. In addition to the standard accents available
+ in PostScript fonts, "underbar" and "underdot" are also
+ available, as are "under" versions of all the normal
+ superscript accents ("underdieresis", "underring", etc.).
+ The Indian accent "candrabindu" may also be specified: it
+ is formed by overprinting a breve with a dotaccent. Finally,
+ "overdot" may be used as a synonym for "dotaccent".
+
+ If the character named in the "accent" position is not in fact
+ a valid accent character, the program interprets the definition
+ as a request for a digraph formed from the "character" and the
+ "accent". A digraph consisting of, say, "k" and "h" will be
+ indistinguishable from the letters "k" and "h" printed
+ consecutively, but the digraph "kh" can itself receive accents
+ like any other character: see next paragraph.
+
+ A new character (such as "amacron" or "kh") may be freely
+ used in the "character" position of a further definition (such
+ as "amacron breve" or "kh underbar"). There is no constraint
+ on the ordering of definitions within a definition file. The
+ definition of "a macron" does not have to precede that of
+ "amacron breve": requests for "impossible" characters are
+ deferred until their constituents have had a chance to come into
+ being.
+
+ "Slots" for which no new definition is given retain the
+ definition they have in the input font.
+
+ The definition file may also contain blank lines and comments
+ (introduced by "#").
+
+ -a should refer to the AFM (Adobe Font Metrics) file for the input
+ font.
+
+ -f should refer to the binary font file (PFB) for the input font.
+ (In fact the equivalent ASCII file (PFA) is also acceptable for
+ input, but the output font is always in PFB format.)
+
+ -s may optionally give the factor, expressed as a per-thousand
+ value, by which normally superscript accents (such as dieresis,
+ ring) should be shrunk when they are used as subscript accents
+ (such as underdieresis, underring). Values of around 800 may be
+ found useful.
+
+ -c may optionally give two comma-separated numerical values to
+ adjust the x and y coordinates of the dotaccent placed within a
+ breve to form the candrabindu accent.
+
+ -b may optionally be specified to block the use of predefined
+ accented characters, forcing mkt1font to define its own
+ versions. This may be useful to secure a consistent appearance
+ in cases where a font designer does not share mkt1font's views
+ on where accents should be placed.
+
+The -h option prints this help.
+
+
+Vpl2vpl
+~~~~~~~
+Syntax: vpl2vpl -d definition-file [-s shrink-factor]
+ [-c candrabindu-adjustment] [-b] vpl-file
+
+Vpl2vpl creates new TeX virtual fonts based on existing fonts or
+virtual fonts ("input fonts"). A successful run will read a pl
+(Property List) or vpl (Virtual Property List) file and a definition
+file, and will generate a new vpl (Virtual Property List) file on
+standard output. The input font is assumed to adhere to the standard
+TeX encoding for text fonts unless it was created with either of the
+programs afm2pl or afm2tfm, in which case it is assumed to conform to
+(respectively) the Adobe Standard Encoding or the encoding specified
+in the file dvips.enc. In either case, the name of the input font is
+assumed to be the name of the input file without its .vpl or .pl
+extension: it must conform to normal TeX conventions for naming fonts,
+as vpl2vpl attempts to draw conclusions from it about the kind of font
+it is dealing with.
+
+A typical complete sequence of commands to create a new virtual
+font might therefore be
+ tftopl cmr10.tfm cmr10.pl
+ vpl2vpl -d ISO-Latin1.def cmr10.pl >cmr10_isol1.vpl
+ vptovf cmr10_isol1.vpl cmr10_isol1.vf cmr10_isol1.tfm
+for a Computer Modern font, or
+ afm2pl Times-Roman.afm rptmr.pl
+ pltotf rptmr.pl rptmr.tfm
+ vpl2vpl -d ISO-Latin1.def rptmr.pl >ptmr-isol1.vpl
+ vptovf ptmr-isol1.vpl ptmr-isol1.vf ptmr-isol1.tfm
+for a PostScript font.
+
+Another approach for a PostScript font is to use afm2tfm:
+ afm2tfm Times-Roman.afm -t dvips.enc -v ptmr rptmr
+ vpl2vpl -d ISO-Latin1.def ptmr.vpl >ptmr-isol1.vpl
+ vptovf ptmr-isol1.vpl ptmr-isol1.vf ptmr-isol1.tfm
+-- but this is now deprecated, as afm2tfm generates incorrect
+values for the heights of some characters, and this can lead to
+bad accent placing.
+
+In order to keep the whole upper half of the character set free for
+the requirements of the encoding specified in the definition file,
+certain modifications are made to input fonts following the
+dvips.enc encoding to bring them into greater conformity with the
+TeX norm. In particular, the characters dotaccent and hungarumlaut
+are placed in the positions assigned by TeX ("5F, "7D), not those
+enforced by dvips.enc ("C7, "CD). The f-ligatures, double quotes
+and dashes are also moved from the upper half of the character set
+to their normal TeX positions. As a result, the following characters
+are not found in the lower half of the character set: quotesingle,
+quotedbl, backslash, underscore, braceleft, bar, braceright. These
+characters can, however, be assigned positions in the output font if
+they are needed. (Indeed, they could all be explicitly restored to
+their dvips.enc positions if this were desired.)
+
+Options:
+
+ -d should refer to a font definition file. This file (which could
+ usefully be named, e.g., "French.def") should consist of
+ lines of character definitions, in the form
+ "number" "character"
+ or
+ "number" "character" "accent"
+ Here "number" represents the character's position in the new
+ encoding and may be expressed in decimal, octal or hex;
+ "character" names the character (e.g. "comma", "eight",
+ "A") or consists of the word ".notdef" (indicating that
+ the specified number's "slot" in the new encoding is to be
+ empty); and "accent" optionally names an accent to be placed
+ on the character. In addition to the standard accents available
+ in PostScript fonts, "underbar" and "underdot" are also
+ available, as are "under" versions of all the normal
+ superscript accents ("underdieresis", "underring", etc.).
+ The Indian accent "candrabindu" may also be specified: it
+ is formed by overprinting a breve with a dotaccent. Finally,
+ "overdot" may be used as a synonym for "dotaccent".
+
+ If the character named in the "accent" position is not in fact
+ a valid accent character, the program interprets the definition
+ as a request for a digraph formed from the "character" and the
+ "accent". A digraph consisting of, say, "k" and "h" will be
+ indistinguishable from the letters "k" and "h" printed
+ consecutively, but the digraph "kh" can itself receive accents
+ like any other character: see next paragraph.
+
+ A new character (such as "amacron" or "kh") may be freely
+ used in the "character" position of a further definition (such
+ as "amacron breve" or "kh underbar"). There is no constraint
+ on the ordering of definitions within a definition file. The
+ definition of "a macron" does not have to precede that of
+ "amacron breve": requests for "impossible" characters are
+ deferred until their constituents have had a chance to come into
+ being.
+
+ "Slots" for which no new definition is given retain the
+ definition they have in the input font.
+
+ The definition file may also contain blank lines and comments
+ (introduced by "#").
+
+ -s may optionally give the factor, expressed as a per-thousand
+ value, by which normally superscript accents (such as dieresis,
+ ring) should be shrunk when they are used as subscript accents
+ (such as underdieresis, underring). Values of around 800 may be
+ found useful.
+
+ -c may optionally give two comma-separated numerical values to
+ adjust the x and y coordinates of the dotaccent placed within a
+ breve to form the candrabindu accent. A coordinate scheme using
+ "DESIGNUNITS R 1000" is assumed.
+
+ -b may optionally be specified to block the use of predefined
+ accented characters, forcing vpl2vpl to define its own
+ versions. This may be useful to secure a consistent appearance
+ in cases where a font designer does not share vpl2vpl's views
+ on where accents should be placed.
+
+ -h prints this help.
+
+
+Vpl2ovp
+~~~~~~~
+
+Syntax: vpl2ovp -d definition-file [-s shrink-factor]
+ [-c candrabindu-adjustment] [-b] vpl-file
+
+Vpl2ovp creates new Omega virtual fonts based on existing TeX
+fonts or virtual fonts ("input fonts"). A successful run will
+read a pl (Property List) or vpl (Virtual Property List) file
+and a definition file, and will generate a new ovp (Omega
+Virtual Property List) file on standard output. The input font
+is assumed to adhere to the standard TeX encoding for text
+fonts unless it was created with either of the programs afm2pl
+or afm2tfm, in which case it is assumed to conform to
+(respectively) the Adobe Standard Encoding or the encoding
+specified in the file dvips.enc. In either case, the name of
+the input font is assumed to be the name of the input file
+without its .vpl or .pl extension: it must conform to normal
+TeX conventions for naming fonts, as vpl2ovp attempts to draw
+conclusions from it about the kind of font it is dealing with.
+
+A typical complete sequence of commands to create a new virtual
+font might therefore be
+ tftopl cmr10.tfm cmr10.pl
+ vpl2ovp -d Unicode1.def cmr10.pl >cmr10-uni1.ovp
+ ovp2ovf cmr10-uni1.ovp cmr10-uni1.ovf cmr10-uni1.ofm
+for a Computer Modern font, or
+ afm2pl Times-Roman.afm rptmr.pl
+ pltotf rptmr.pl rptmr.tfm
+ vpl2ovp -d Unicode1.def rptmr.pl >ptmr-uni1.ovp
+ ovp2ovf ptmr-uni1.ovp ptmr-uni1.ovf ptmr-uni1.ofm
+for a PostScript font.
+
+Another approach for a PostScript font is to use afm2tfm:
+ afm2tfm Times-Roman.afm -t dvips.enc -v ptmr rptmr
+ vpl2ovp -d Unicode1.def ptmr.vpl >ptmr-uni1.ovp
+ ovp2ovf ptmr-uni1.ovp ptmr-uni1.ovf ptmr-uni1.ofm
+-- but this is now deprecated, as afm2tfm generates incorrect
+values for the heights of some characters, and this can lead to
+bad accent placing.
+
+In order to keep the whole of the character range "F0-"FF free for
+the requirements of the encoding specified in the definition file,
+certain modifications are made to input fonts following the dvips.enc
+encoding to bring them into greater conformity with the TeX norm. In
+particular, the characters dotaccent and hungarumlaut are placed in
+the positions assigned by TeX ("5F, "7D), not those enforced by
+dvips.enc ("C7, "CD). The f-ligatures, double quotes and dashes are
+also moved from the upper half of the original 8-bit character set to
+their normal TeX positions. As a result, the following characters are
+not found in the lower half of the character set: quotesingle,
+quotedbl, backslash, underscore, braceleft, bar, braceright. These
+characters can, however, be assigned positions in the output font if
+they are needed. (Indeed, they could all be explicitly restored to
+their dvips.enc positions if this were desired.)
+
+Options:
+
+ -d should refer to a font definition file. This file (which could
+ usefully be named, e.g., "Unicode1.def") should consist of
+ lines of character definitions, in the form
+ "number" "character"
+ or
+ "number" "character" "accent"
+ Here "number" represents the character's position in the new
+ encoding and may be expressed in decimal, octal or hex;
+ "character" names the character (e.g. "comma", "eight",
+ "A") or consists of the word ".notdef" (indicating that
+ the specified number's "slot" in the new encoding is to be
+ empty); and "accent" optionally names an accent to be placed
+ on the character. In addition to the standard accents available
+ in PostScript fonts, "underbar" and "underdot" are also
+ available, as are "under" versions of all the normal
+ superscript accents ("underdieresis", "underring", etc.).
+ The Indian accent "candrabindu" may also be specified: it
+ is formed by overprinting a breve with a dotaccent. Finally,
+ "overdot" may be used as a synonym for "dotaccent".
+
+ Note that all accents used in defining accented characters must
+ themselves be defined in the .def file. Those which exist in the
+ source font should simply be referenced by name in their
+ appropriate Unicode position (e.g. "0x0304 macron"); those
+ which do not should be defined as the character "space"
+ followed by the name of the accent (e.g. "0x0310 space
+ candrabindu").
+
+ If the character named in the "accent" position is not in fact
+ a valid accent character, the program interprets the definition
+ as a request for a digraph formed from the "character" and the
+ "accent". A digraph consisting of, say, "k" and "h" will be
+ indistinguishable from the letters "k" and "h" printed
+ consecutively, but the digraph "kh" can itself receive accents
+ like any other character: see next paragraph.
+
+ A new character (such as "amacron" or "kh") may be freely
+ used in the "character" position of a further definition (such
+ as "amacron breve" or "kh underbar"). There is no constraint
+ on the ordering of definitions within a definition file. The
+ definition of "a macron" does not have to precede that of
+ "amacron breve": requests for "impossible" characters are
+ deferred until their constituents have had a chance to come into
+ being.
+
+ "Slots" for which no new definition is given retain the
+ definition they have in the input font.
+
+ The definition file may also contain blank lines and comments
+ (introduced by "#").
+
+ -s may optionally give the factor, expressed as a per-thousand
+ value, by which normally superscript accents (such as dieresis,
+ ring) should be shrunk when they are used as subscript accents
+ (such as underdieresis, underring). Values of around 800 may be
+ found useful.
+
+ -c may optionally give two comma-separated numerical values to
+ adjust the x and y coordinates of the dotaccent placed within a
+ breve to form the candrabindu accent. A coordinate scheme using
+ "DESIGNUNITS R 1000" is assumed.
+
+ -b may optionally be specified to block the use of predefined
+ accented characters, forcing vpl2ovp to define its own
+ versions. This may be useful to secure a consistent appearance
+ in cases where a font designer does not share vpl2ovp's views
+ on where accents should be placed.
+
+ -h prints this help.
+
+
+John D. Smith
+jds10@cam.ac.uk
+http://bombay.indology.info
diff --git a/fonts/utilities/accfonts/dvips.enc b/fonts/utilities/accfonts/dvips.enc
new file mode 100644
index 0000000000..ea451ff106
--- /dev/null
+++ b/fonts/utilities/accfonts/dvips.enc
@@ -0,0 +1,75 @@
+% @@psencodingfile@{
+% author = "T. Rokicki, K. Berry",
+% version = "2.0",
+% date = "22 June 1996",
+% filename = "dvips.enc",
+% email = "kb@@mail.tug.org",
+% address = "135 Center Hill Rd. // Plymouth, MA 02360",
+% codetable = "ISO/ASCII",
+% checksum = "75 515 3715",
+% docstring = "An encoding for PostScript fonts to be used with TeX."
+% @}
+%
+% This is almost the default encoding produced by the afm2tfm program
+% that comes with the dvips distribution, when it is applied to a
+% StandardEncoding PostScript font. The positions of the accented
+% characters (which afm2tfm assigned more or less randomly in the
+% previous set of fonts) have been held fixed.
+%
+% It is almost upward-compatible with TeX text. (The primary exceptions
+% are dotaccent and hungarumlaut.) Some of the ligatures are also in
+% different positions, but this is not important, since ligature
+% positions are defined in the TFM file, not by macros.
+%
+% The character positions were assigned in this order:
+% 1) non-composite characters in the afm2tfm encoding (except dotlessj
+% was included in its plain TeX position);
+% 2) available characters in the Cork (EC) encoding;
+% 3) remaining composite characters in the base encoding (starting at
+% position 130 decimal). We don't include all the other base
+% characters because that changes the height/depth/width tables in
+% the TFM files (because more characters mean more distinct values).
+%
+% We leave the initial positions open for the Greek letters in Times-Roman.
+%
+/DvipsEncoding [
+ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+ /.notdef /.notdef /.notdef /.notdef
+ /.notdef /quotesingle /exclamdown /questiondown
+ /dotlessi /dotlessj /grave /acute /caron /breve /macron /ring
+ /cedilla /germandbls /ae /oe /oslash /AE /OE /Oslash
+ /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright
+ /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash
+ /zero /one /two /three /four /five /six /seven
+ /eight /nine /colon /semicolon /less /equal /greater /question
+ /at /A /B /C /D /E /F /G
+ /H /I /J /K /L /M /N /O
+ /P /Q /R /S /T /U /V /W
+ /X /Y /Z /bracketleft /backslash /bracketright /circumflex /underscore
+ /quoteleft /a /b /c /d /e /f /g
+ /h /i /j /k /l /m /n /o
+ /p /q /r /s /t /u /v /w
+ /x /y /z /braceleft /bar /braceright /tilde /dieresis
+ /asciicircum /asciitilde /Ccedilla /Iacute
+ /Icircumflex /atilde /edieresis /egrave
+ /scaron /zcaron /Eth /ff /ffi /ffl /.notdef /.notdef
+ /.notdef /.notdef /Scaron /.notdef /.notdef /.notdef /.notdef /.notdef
+ /Ydieresis /.notdef /Zcaron /.notdef /.notdef /.notdef /.notdef /.notdef
+ /.notdef /.notdef /cent /sterling /fraction /yen /florin /section
+ /currency /copyright /quotedblleft /guillemotleft
+ /guilsinglleft /guilsinglright /fi /fl
+ /degree /endash /dagger /daggerdbl /periodcentered /.notdef /paragraph /bullet
+ /quotesinglbase /quotedblbase /quotedblright /guillemotright
+ /ellipsis /perthousand /.notdef /.notdef
+ /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /.notdef /dotaccent
+ /Egrave /Eacute /Ecircumflex /Edieresis
+ /Igrave /hungarumlaut /ogonek /Idieresis
+ /emdash /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /.notdef
+ /.notdef /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /.notdef
+ /agrave /aacute /acircumflex /ordfeminine
+ /adieresis /aring /.notdef /ccedilla
+ /Lslash /eacute /ecircumflex /ordmasculine
+ /igrave /iacute /icircumflex /idieresis
+ /.notdef /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /.notdef
+ /lslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis
+] def
diff --git a/fonts/utilities/accfonts/mkt1font b/fonts/utilities/accfonts/mkt1font
new file mode 100755
index 0000000000..966ba5932d
--- /dev/null
+++ b/fonts/utilities/accfonts/mkt1font
@@ -0,0 +1,1012 @@
+#!/usr/bin/perl
+
+# Mkt1font: a program to generate accented Type 1 PostScript fonts
+# Copyright (C) 1997 John D. Smith
+
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$version = 0.25;
+#-----------------------------------------------------------------------------#
+$description =
+"Syntax: mkt1font -n fontname -d definition-file -a afm-file -f font-file
+ [-s shrink-factor] [-c candrabindu-adjustment] [-b]
+
+Mkt1font creates new Type 1 PostScript fonts based on existing fonts
+(\"input fonts\"). In order to do this it makes use of I. Lee
+Hetherington's programs t1asm and t1disasm, which must be present on
+the system. A successful run will generate an AFM file and a PFB
+file, as well as a DIS file containing a disassembled version of the
+PFB file (including useful comments). Four options must be specified
+on the command line, as follows:
+
+ -n should name the font it is intended to generate. Avoid names
+ such as \"myfont\", as both mkt1font and other programs attempt
+ to draw conclusions from the name; better would be something
+ like \"Utopia_French-BoldItalic\". The generated font files
+ will also use this for their basename.
+
+ -d should refer to a font definition file. This file (which could
+ usefully be named, e.g., \"French.def\") should consist of
+ lines of character definitions, in the form
+ \"number\" \"character\"
+ or
+ \"number\" \"character\" \"accent\"
+ Here \"number\" represents the character's position in the new
+ encoding and may be expressed in decimal, octal or hex;
+ \"character\" names the character (e.g. \"comma\", \"eight\",
+ \"A\") or consists of the word \".notdef\" (indicating that
+ the specified number's \"slot\" in the new encoding is to be
+ empty); and \"accent\" optionally names an accent to be placed
+ on the character. In addition to the standard accents available
+ in PostScript fonts, \"underbar\" and \"underdot\" are also
+ available, as are \"under\" versions of all the normal
+ superscript accents (\"underdieresis\", \"underring\", etc.).
+ The Indian accent \"candrabindu\" may also be specified: it
+ is formed by overprinting a breve with a dotaccent. Finally,
+ \"overdot\" may be used as a synonym for \"dotaccent\".
+
+ If the character named in the \"accent\" position is not in fact
+ a valid accent character, the program interprets the definition
+ as a request for a digraph formed from the \"character\" and the
+ \"accent\". A digraph consisting of, say, \"k\" and \"h\" will be
+ indistinguishable from the letters \"k\" and \"h\" printed
+ consecutively, but the digraph \"kh\" can itself receive accents
+ like any other character: see next paragraph.
+
+ A new character (such as \"amacron\" or \"kh\") may be freely
+ used in the \"character\" position of a further definition (such
+ as \"amacron breve\" or \"kh underbar\"). There is no constraint
+ on the ordering of definitions within a definition file. The
+ definition of \"a macron\" does not have to precede that of
+ \"amacron breve\": requests for \"impossible\" characters are
+ deferred until their constituents have had a chance to come into
+ being.
+
+ \"Slots\" for which no new definition is given retain the
+ definition they have in the input font.
+
+ The definition file may also contain blank lines and comments
+ (introduced by \"\#\").
+
+ -a should refer to the AFM (Adobe Font Metrics) file for the input
+ font.
+
+ -f should refer to the binary font file (PFB) for the input font.
+ (In fact the equivalent ASCII file (PFA) is also acceptable for
+ input, but the output font is always in PFB format.)
+
+ -s may optionally give the factor, expressed as a per-thousand
+ value, by which normally superscript accents (such as dieresis,
+ ring) should be shrunk when they are used as subscript accents
+ (such as underdieresis, underring). Values of around 800 may be
+ found useful.
+
+ -c may optionally give two comma-separated numerical values to
+ adjust the x and y coordinates of the dotaccent placed within a
+ breve to form the candrabindu accent.
+
+ -b may optionally be specified to block the use of predefined
+ accented characters, forcing mkt1font to define its own
+ versions. This may be useful to secure a consistent appearance
+ in cases where a font designer does not share mkt1font's views
+ on where accents should be placed.
+
+The -h option prints this help.
+";
+#-----------------------------------------------------------------------------#
+
+########################
+# Packages and constants
+########################
+#
+use File::Basename;
+use Getopt::Std;
+$cmdline = basename($0) . " " . join " ", @ARGV;
+getopts('n:d:a:f:c:s:bh');
+if ($opt_h or !($opt_n && $opt_d && $opt_a && $opt_f) or ($#ARGV >= 0)) {
+ print STDERR $description;
+ exit 1;
+}
+($enc = basename($opt_d)) =~ s/\..*$//;
+if ($opt_n =~ /\s/) { die "Font name cannot contain whitespace\n" }
+($famname = $opt_n) =~ s/^(.*)-.*?$/$1/;
+if ($opt_s) { $shrink = $opt_s / 1000 } else { $shrink = 1 }
+@months = ( "January", "February", "March", "April",
+ "May", "June", "July", "August",
+ "September", "October", "November", "December"
+ );
+@lt = localtime;
+$date = "$months[$lt[4]] $lt[3], ${ \($lt[5] + 1900) }";
+if ($opt_c) { ($cbx, $cby) = $opt_c =~ /^(.*),(.*)$/ } # candrabindu
+
+###############
+# Read DEF file
+###############
+#
+open DEF, $opt_d or die "Cannot open $opt_d: $!\n";
+while (<DEF>) {
+ next if (/^\s*$/ || /^\#/);
+ s/\s*(\#.*)?$//;
+ push @deflines, $_;
+}
+close DEF;
+
+###############
+# Read AFM file
+###############
+#
+# File header
+#
+open AFM, $opt_a or die "Cannot open $opt_a: $!\n";
+while (<AFM>) {
+ if (/^StartFontMetrics/) {
+ $afmhead = $_;
+ do {
+ $_ = <AFM>;
+ $afmhead .= $_;
+ }
+ until $_ =~ /^StartCharMetrics \d+\r?$/;
+ $afmhead =~ s/\r//gm; # Might be DOS file
+ $afmhead =~ /^FontName (.*)$/m;
+ $ofname = $1;
+ $afmbanner = "\nComment Based on $ofname; modified for $enc encoding";
+ $afmbanner .= "\nComment by John Smiths's program mkt1font ";
+ $afmbanner .= "(v. $version) " if $version;
+ $afmbanner .= "on $date";
+ $afmbanner .= "\nComment Command line: $cmdline";
+ $afmhead =~ s/(\n^FontName )(.*)$/$1$opt_n/m;
+ $afmhead =~ s/(\n^FullName )(.*)$/$1$opt_n/m;
+ $afmhead =~ s/(\n^FamilyName )(.*)$/$1$famname/m;
+ $afmhead =~ s/\n^Comment /$afmbanner$&/m;
+ $afmhead =~ s/(\n^EncodingScheme ).*$/$1FontSpecific/m;
+ if ($afmhead =~ /\n^ItalicAngle (.*)$/m) { $italangle = $1 }
+ if ($afmhead =~ /\n^CapHeight (.*)$/m) { $capheight = $1 }
+ if ($afmhead =~ /\n^XHeight (.*)$/m) { $xheight = $1 }
+ if ($afmhead =~ /\n^FontBBox -?\d+ (-?\d+) (-?\d+) (-?\d+)$/m) {
+ ($maxdp, $maxrs, $maxht) = ($1, $2, $3);
+ }
+ }
+ #
+ # Encoded chars
+ #
+ if (/(^C (\d+) ; WX \d+ ; N ([a-zA-Z_][a-zA-Z0-9_.]*|\.notdef) ; B .* ;( L .* ;)?)\r?$/) {
+ $metrics_enc[$2] = "$1\n";
+ }
+ #
+ # Unencoded chars
+ #
+ elsif (/(^C -1 ; WX \d+ ; N ([a-zA-Z_][a-zA-Z0-9_.]*|\.notdef) ; B .* ;( L .* ;)?)\r?$/) {
+ $metrics_unenc .= "$1\n";
+ }
+ #
+ # Kerns etc.
+ #
+ if (/^EndCharMetrics\r?$/) {
+ $afmtail = $_;
+ do {
+ $_ = <AFM>;
+ $afmtail .= $_;
+ }
+ until eof(AFM);
+ $afmtail =~ s/[\r\cZ]//gm; # Might be DOS file
+ }
+}
+if ($afmtail =~ /(\A(?:.|\n)*^StartKernPairs )\d+\n((?:.|\n)*)(^EndKernPairs(?:.|\n)*\Z)/m) {
+ ($kstart, $kdefs, $kend) = ($1, $2, $3);
+}
+close AFM;
+
+###############################
+# Read and disassemble PFB file
+###############################
+#
+open PFB, $opt_f or die "Cannot open $opt_f: $!\n";
+$_ = <PFB>;
+unless (/%!/) { die "File $opt_f is not a PostScript font\n" }
+close PFB;
+$disfile1 = "mkt1font$$.dis";
+system "t1disasm $opt_f >$disfile1 2>/dev/null";
+open DIS, $disfile1 or die "Cannot open disassembled font file: $!\n";
+while (<DIS>) {
+ #
+ # Locate crucial definitions
+ #
+ if (/^\/(.*?) ?{ ?noaccess def ?} ?executeonly def$/) {
+ $nd = $1;
+ ($rend = $nd) =~ s/\|/\\|/g; # Regexp version
+ next;
+ }
+ if (/^\/(.*?) ?{ ?noaccess put ?} ?executeonly def$/) {
+ $np = $1;
+ ($renp = $np) =~ s/\|/\\|/g; # Regexp version
+ next;
+ }
+ if (/^\/Subrs (\d+) array/) {
+ $subrsnum = $1;
+ do {
+ #
+ # Store subroutine definitions in @subrs
+ #
+ $l = $_ = <DIS>;
+ if (/^dup (\d+) {$/) {
+ $subrnum = $1;
+ $subrdef = $_;
+ do {
+ $_ = <DIS>;
+ $subrdef .= $_;
+ }
+ until /^\t} ?$renp$/;
+ }
+ #
+ # "correct" t1disasm output so t1asm will accept it as input
+ #
+ $subrdef =~ s/^(\t})($rend|$renp)$/$1 $2/m;
+ $subrs[$subrnum] = $subrdef;
+ }
+ until ($l !~ /^dup \d+ {$/);
+ next;
+ }
+ if (/^2 index \/CharStrings (\d+) dict dup begin/) {
+ #
+ # do *not* use "$" to anchor the end of this line, because
+ # it may end with an invisible trailing space!
+ #
+ $chdefsnum = $1;
+ do {
+ #
+ # Store character definitions in %chstrings
+ #
+ $l = $_ = <DIS>;
+ if (/^\/([a-zA-Z_][a-zA-Z0-9_.]*|\.notdef|\.null) {$/) {
+ $chname = $1;
+ $chdef = $_;
+ do {
+ $_ = <DIS>;
+ $chdef .= $_;
+ }
+ until /^\t} ?$rend$/;
+ }
+ #
+ #"correct" t1disasm output so t1asm will accept it as input
+ #
+ $chdef =~ s/^(\t})($rend|$renp)$/$1 $2/m;
+ $chstrings{$chname} = $chdef;
+ }
+ until ($l !~ /^\/([a-zA-Z_][a-zA-Z0-9_.]*|\.notdef|\.null) {$/);
+ #
+ # File tail
+ #
+ if (/^end/) {
+ $distail = $_;
+ do {
+ $_ = <DIS>;
+ $distail .= $_;
+ }
+ until eof(DIS);
+ }
+ }
+}
+close DIS;
+unless ($nd) { die "Cannot find \"noaccess def\" definition\n" }
+unless ($np) { die "Cannot find \"noaccess put\" definition\n" }
+unless ($subrsnum) { die "Cannot find size of Subrs array\n" }
+unless ($chdefsnum) { die "Cannot find size of CharStrings dict\n" }
+
+##################
+# Set up constants
+##################
+#
+$subacc = "(cedilla|ogonek|commaaccent)";
+$supacc = "(grave|acute|circumflex|tilde|macron|breve|dotaccent|overdot|dieresis|ring|hungarumlaut|caron|candrabindu)";
+$underacc = "(underdot|under$supacc)";
+$accents = "($subacc|$supacc|$underacc|underbar)";
+$underadp = -230; # depth of "under" accs
+$underddp = -213; # depth of underdot
+if ($opt_n =~ /Bold/) { $thk = 72 } else { $thk = 52 } # thickness and
+$underbdp = -(82 + $thk); # depth of underbar
+getcharinfo("macron");
+$accheight = $chht{macron}; # height of macron
+$accdepth = $chdp{macron}; # "depth" of macron
+$v1 = $accheight - $xheight; # vertical offset for double accents
+$v2 = $capheight - $xheight; # vertical offset for accented caps etc
+#
+# Italic adjustment: tan(angle)
+#
+$itadj = sin($italangle * 3.14159 / 180) / cos($italangle * 3.14159 / 180);
+
+###########################
+# Create uni0237 (dotlessj)
+###########################
+#
+$chstrings{uni0237} = $chstrings{j} . "\n";
+$chstrings{uni0237} =~ /\A(.*?)(\t[-0-9 ]+?[rvh]moveto)(\n.+)(\n\t.*?(-?\d+) [rv]moveto)(.*?)(\n\tendchar.*?)\Z/ms;
+($one, $two, $three, $four, $five, $six, $seven) = ($1, $2, $3, $4, $5, $6, $7);
+if ($five > 0) { $chstrings{uni0237} = $one . $two . $three . $seven }
+else {
+ findend("j1", ($two . $three));
+ $j1end = "\t$hend{j1} $vend{j1} rmoveto";
+ $chstrings{uni0237} = $one . $j1end . $four . $six . $seven
+}
+$chstrings{uni0237} =~s/\A\/j /\/uni0237 /m;
+getcharinfo("j");
+getcharinfo("dotlessi");
+$metrics_unenc .= "C -1 ; WX $chwd{j} ; N uni0237 ; B $chls{j} $chdp{j} $chrs{j} $chht{dotlessi} ;\n";
+#
+######################
+# Build the characters
+######################
+#
+# First build a list of definitions supplied by user
+#
+for (@deflines) {
+ if (/^\s*(\d+|0[0-7]+|0x[0-9a-fA-F]+)\s+([a-zA-Z_][a-zA-Z0-9_.]*?|\.notdef)(?:\s+([a-zA-Z_][a-zA-Z0-9_.]*))?$/) {
+ ($num, $char, $acc) = ($1, $2, $3);
+ $num = oct $num if $num =~ /^0/;
+ if ($num > 255) { die "Bad definition (number out of range): $_\n" }
+ $def = {};
+ $def->{qdef} = $_;
+ $def->{num} = $num;
+ $def->{char} = $char;
+ $def->{acc} = $acc;
+ $def->{nchar} = $char . $acc;
+ push @nchars, $def->{nchar};
+ push @defs, $def;
+ }
+ else { die "Bad definition: $_\n" }
+}
+#
+# Work through the list
+#
+while (@defs) {
+ $def = shift @defs;
+ $qdef = $def->{qdef};
+ $num = $def->{num};
+ $char = $def->{char};
+ $acc = $def->{acc};
+ $nchar = $def->{nchar};
+ #
+ # If we can't handle $char/$acc yet, but believe we will be able
+ # to later, send the definition to the back of the queue. In case
+ # it later turns out we were wrong, allow only five loops before
+ # giving up.
+ #
+ if (!grep / ; N $char ; /, @metrics_enc
+ and $metrics_unenc !~ / ; N $char ; /m) {
+ if (grep /^$char$/, @nchars) {
+ unless (++$def->{requeue} > 5) {
+ push @defs, $def;
+ next;
+ }
+ }
+ else { die "Bad definition (no such character): $qdef\n" }
+ }
+ if ($acc
+ and !grep / ; N $acc ; /, @metrics_enc
+ and $metrics_unenc !~ / ; N $acc ; /m
+ and $acc !~ /^$accents$/) {
+ if (grep /^$acc$/, @nchars) {
+ unless (++$def->{requeue} > 5) {
+ push @defs, $def;
+ next;
+ }
+ }
+ else { die "Bad definition (no such accent): $qdef\n" }
+ }
+ #
+ # First deal with .notdef
+ #
+ if ($nchar eq ".notdef") {
+ ($old = $metrics_enc[$num]) =~ s/^C $num/C -1/;
+ $metrics_unenc .= $old unless $metrics_unenc =~ /$old/m;
+ undef $metrics_enc[$num];
+ }
+ #
+ # Now look for new char among existing encoded chars (unless blocked by -b)
+ #
+ else {
+ if (!($acc and $opt_b)
+ and @foundit = grep / ; N $nchar ; /, @metrics_enc) {
+ ($foundit = shift @foundit) =~ s/^C (\d+)/C $num/;
+ $prevnum = $1;
+ unless ($prevnum == $num) {
+ ($old = $metrics_enc[$num]) =~ s/^C $num/C -1/;
+ $metrics_unenc .= $old unless $metrics_unenc =~ /$old/m;
+ $metrics_enc[$num] = $foundit;
+ }
+ fixkerns($char, $acc);
+ }
+ #
+ # Next look among existing unencoded chars (unless blocked by -b)
+ #
+ elsif (!($acc and $opt_b)
+ and $metrics_unenc =~ s/^C -1 ; WX \d+ ; N $nchar ; B .* ;( L .* ;)?\n//m) {
+ ($foundit = $&) =~ s/^C -1/C $num$1/m;
+ $old = $metrics_enc[$num];
+ if ($old) {
+ $old =~ s/^C $num/C -1/;
+ $metrics_unenc .= $old unless $metrics_unenc =~ /$old/m;
+ }
+ $metrics_enc[$num] = $foundit;
+ fixkerns($char, $acc);
+ }
+ #
+ # If it can't be built from sub-elements, issue a warning and move on
+ #
+ elsif (!$acc) { warn "No such character - ignoring definition: $qdef\n" }
+ #
+ # Now build the char
+ #
+ else {
+ #
+ # First get rid of predefined afm entries and synonyms
+ #
+ $metrics_unenc =~ s/^C -1 ; WX \d+ ; N $nchar ; B .* ;( L .* ;)?\n//m;
+ $kdefs =~ s/\nKPX .*$nchar .*$//gm;
+ if ($acc eq "overdot") {
+ $nchar2 = $char . "dotaccent";
+ $metrics_unenc =~ s/^C -1 ; WX \d+ ; N $nchar2 ; B .* ;( L .* ;)?\n//m;
+ $kdefs =~ s/\nKPX .*$nchar2 .*$//gm;
+ delete $chstrings{$nchar2};
+ }
+ #
+ # Go!
+ #
+ if ($acc =~ /^$subacc$/) {
+ subacc($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ elsif ($acc =~ /^$supacc$/) {
+ supacc($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ elsif ($acc =~ /^$underacc$/) {
+ underacc($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ elsif ($acc =~ /^underbar$/) {
+ underb($num, $char, $nchar);
+ fixkerns($char, $acc);
+ }
+ else {
+ digraph($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ }
+ }
+}
+
+################
+# Write AFM file
+################
+#
+open OUTAFM, ">$opt_n.afm";
+foreach (@metrics_enc) { # Avoid duplicate entries
+ ($chname) = /( ; N [a-zA-Z_][a-zA-Z0-9_.]* ; )/;
+ $metrics_unenc =~ s/^C -1 .*$chname.*\n//gm if $chname;
+}
+$chmetricnum = split(/\n/, $metrics_unenc);
+$chmetricnum += grep /^C /, @metrics_enc;
+$afmhead =~ s/^(FontBBox -?\d+ )-?\d+ -?\d+ -?\d+$/$1$maxdp $maxrs $maxht/m;
+$afmhead =~ s/^(StartCharMetrics )\d+$/$1$chmetricnum/m;
+$encoding = "/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n";
+print OUTAFM $afmhead;
+for $i (0 .. 255) {
+ $line = $metrics_enc[$i];
+ if ($line) {
+ print OUTAFM $line;
+ if ($line =~ /^C \d+ ; WX \d+ ; N ([a-zA-Z_][a-zA-Z0-9_.]*) ; /) {
+ $encoding .= "dup $i /$1 put\n";
+ }
+ }
+}
+$encoding .= "readonly def\n";
+print OUTAFM $metrics_unenc;
+#
+# Tidy up kerns
+#
+if ($kdefs) {
+ $kdefs = join("\n", sort split /\n/, $kdefs); # sort
+ $kdefs .= "\n";
+ $kdefs =~ s/((^KPX .*?)-?\d+$)\n\2.*$/$1/gm; # remove duplicates
+ $kdefs =~ s/^\s*\n//gm; # and blank lines
+ $knum = split(/\n/, $kdefs);
+ $afmtail = $kstart . $knum . "\n" . $kdefs . $kend;
+}
+#
+# Eliminate composite character definitions
+#
+$afmtail =~ s/\n(Start|End)Composites.*$//gm;
+$afmtail =~ s/\nCC .*;$//gm;
+print OUTAFM $afmtail;
+close OUTAFM;
+
+#########################
+# Write DIS and PFB files
+#########################
+#
+$disfile2 = "$opt_n.dis";
+open OUTDIS, ">$disfile2";
+$disbanner = "% Based on $ofname; modified for $enc encoding\n";
+$disbanner .= "% by John Smiths's program mkt1font ";
+$disbanner .= "(v. $version) " if $version;
+$disbanner .= "on $date\n";
+$disbanner .= "% Command line: $cmdline";
+open DIS, $disfile1;
+while (<DIS>) { # get header
+ s/^(%!.*: ).*$/$1$opt_n\n$disbanner/;
+ s/(\/FullName \().*(\).*)$/$1$opt_n$2/;
+ s/(\/FamilyName \().*(\).*)$/$1$famname$2/;
+ s/(\/FontName \/).*?( .*)$/$1$opt_n$2/;
+ s/(\/FontBBox {-?\d+ )-?\d+ -?\d+ -?\d+/$1$maxdp $maxrs $maxht/m;
+ if (/^\/Encoding /) {
+ print OUTDIS $encoding;
+ next;
+ }
+ next if (/\/UniqueID .*$/);
+ s /(\/BlueValues \[.*)(\] def)$/$1 $accheight $accheight$2/;
+ if (/(\/Subrs )\d+( array)$/) {
+ print OUTDIS "$1$subrsnum$2\n";
+ last;
+ }
+ else { print OUTDIS }
+}
+close DIS;
+unlink $disfile1;
+foreach $subrdef (@subrs) { print OUTDIS $subrdef }
+$chdefsnum = scalar(keys(%chstrings));
+print OUTDIS "$nd\n2 index /CharStrings $chdefsnum dict dup begin\n";
+foreach (sort values %chstrings) { print OUTDIS }
+print OUTDIS $distail;
+close OUTDIS;
+system "t1asm -b $disfile2 >$opt_n.pfb 2>/dev/null";
+
+#####################
+# End of main program
+#####################
+
+sub subacc {
+ #
+ # Subscript accents
+ #
+ my ($num, $char, $acc, $nchar) = @_;
+ my ($old, $astr, $h, $H, $V, $chdef, $acdef, $pstr);
+ ($old = $metrics_enc[$num]) =~ s/^C $num/C -1/;
+ $metrics_unenc .= $old unless $metrics_unenc =~ /$old/m;
+ getcharinfo($char) unless defined $chwd{$char};
+ getcharinfo($acc) unless defined $chwd{$acc};
+ $astr = "C $num ; WX $chwd{$char} ; N $nchar ; B $chls{$char} ";
+ $astr .= "$chdp{$acc} $chrs{$char} $chht{$char} ;\n";
+ $metrics_enc[$num] = $astr;
+ $h = round(($chwd{$char} - $chwd{$acc}) / 2 + $chls{$acc});
+ unless (defined $hend{$char}) { findend($char, $chstrings{$char}) }
+ $H = $h - $hend{$char} - $chls{$char};
+ $V = -$vend{$char};
+ $chstrings{$char} =~ /^\/$char {\n(\t.+?hsbw\n(.|\n)*?)\tendchar\n\t} $rend\n/m;
+ $chdef = $1;
+ $chstrings{$acc} =~ /^\/$acc {\n\t.+? .+?hsbw\n((.|\n)+?\t} $rend\n)/m;
+ $acdef = $1;
+ $acdef = fixhints($nchar, $acc, $acdef, $h, 0);
+ $pstr = "/$nchar {\n$chdef % $nchar: start of $acc\n";
+ $pstr .= "\t$H $V rmoveto\n$acdef";
+ $chstrings{$nchar} = $pstr;
+}
+
+sub supacc {
+ #
+ # Superscript accents
+ #
+ my ($num, $char, $acc, $nchar) = @_;
+ my ($old, $cb, $astr, $h, $v, $H, $V, $it, $chdef, $acdef, $pstr, $newchar);
+ ($old = $metrics_enc[$num]) =~ s/^C $num/C -1/;
+ $metrics_unenc .= $old unless $metrics_unenc =~ /$old/m;
+ if ($char eq "i") { $char = "dotlessi" }
+ if ($char eq "j") { $char = "uni0237" }
+ if ($acc eq "overdot") { $acc = "dotaccent" }
+ if ($acc eq "candrabindu") {
+ $acc = "breve";
+ $chstrings{"dotaccent"} =~ /^\/dotaccent {\n\t.+? .+?hsbw\n((.|\n)+?\t} $rend\n)/m;
+ $cb = $1;
+ }
+ getcharinfo($char) unless defined $chwd{$char};
+ getcharinfo($acc) unless defined $chwd{$acc};
+ $astr = "C $num ; WX $chwd{$char} ; N $nchar ; B ";
+ $astr .= "$chls{$char} $chdp{$char} $chrs{$char} ";
+ $v = $chht{$acc};
+ if ($chht{$char} >= $accheight + $v2) { # double accs
+ $v += ($v1 + $v2); # on caps etc.
+ $it = ($v1 + $v2) * $itadj;
+ }
+ elsif ($chht{$char} > 1.15 * $xheight) {
+ if ($char =~ /$supacc$/ and $char !~ /under$supacc$/) {
+ $v += $v1; # double accents
+ $it = $v1 * $itadj;
+ }
+ else {
+ $v += $v2; # accented caps etc.
+ $it = $v2 * $itadj;
+ }
+ }
+ else { $it = 0 }
+ if ($v > $maxht) { $maxht = $v }
+ $astr .= "$v ;\n";
+ $metrics_enc[$num] = $astr;
+ $v -= $chht{$acc};
+ $h = round(($chwd{$char} - $chwd{$acc}) / 2 + $chls{$acc} - $it);
+ unless (defined $hend{$char}) { findend($char, $chstrings{$char}) }
+ $H = $h - $hend{$char} - $chls{$char};
+ $V = $v - $vend{$char};
+ $chstrings{$char} =~ /^\/$char {\n(\t.+?hsbw\n(.|\n)*?)\tendchar\n\t} $rend\n/m;
+ $chdef = $1;
+ $chstrings{$acc} =~ /^\/$acc {\n\t.+? .+?hsbw\n((.|\n)+?\t} $rend\n)/m;
+ $acdef = $1;
+ $acdef = fixhints($nchar, $acc, $acdef, $h, $v);
+ $pstr = "/$nchar {\n$chdef % $nchar: start of $acc\n";
+ $pstr .= "\t$H $V rmoveto\n$acdef";
+ if ($cb) { # candrabindu
+ getcharinfo("dotaccent") unless defined $chwd{dotaccent};
+ $h = round(($chwd{$char} - $chwd{dotaccent}) / 2 + $chls{dotaccent} - $it);
+ $h += $cbx;
+ $v += $cby;
+ $cb = fixhints($nchar, "dotaccent", $cb, $h, $v);
+ $newchar = $char . $acc;
+ unless (defined $hend{$newchar}) { findend($newchar, $pstr) }
+ $H = $h - $hend{$newchar} - $chls{$char};
+ $V = $v - $vend{$newchar};
+ $pstr =~ s/\tendchar\n\t} $rend\n\Z//m;
+ $pstr .= " % $nchar: start of dotaccent\n\t$H $V rmoveto\n$cb";
+ }
+$chstrings{$nchar} = $pstr;
+}
+
+sub underacc {
+ #
+ # Dropped accents
+ #
+ # The Fontographer hack below is necessary because Fontographer (which
+ # I have had to use to build TrueType and Macintosh versions of fonts)
+ # seems not to respect the depths for characters specified in afm files
+ # it has imported: it sets the depth to the lowest point in the path,
+ # whether or not a mark was made there. So it is not possible to
+ # implement (e.g.) underring by diving down low and then printing a
+ # ring at its normal height.
+ #
+ my ($num, $char, $acc, $nchar) = @_;
+ my ($old, $acname, $astr, $h, $v, $H, $V, $chdef, $acdef, $begin, $line, $end, $pstr);
+ ($old = $metrics_enc[$num]) =~ s/^C $num/C -1/;
+ $metrics_unenc .= $old unless $metrics_unenc =~ /$old/m;
+ $acc =~ s/^under//;
+ $acname = $acc;
+ if ($acc eq "dot") { $acc = "period" }
+ if ($acc eq "candrabindu") { die "Bad definition (no such accent): $qdef\n" }
+ getcharinfo($char) unless defined $chwd{$char};
+ getcharinfo($acc) unless defined $chwd{$acc};
+ if ($acc =~ /^$supacc$/) {
+ $v = round($underadp + ($chdp{$acc} - $accdepth) * $shrink);
+ }
+ else { $v = $underddp + $chdp{$acc} }
+ if ($v < $maxdp) { $maxdp = $v }
+ $astr = "C $num ; WX $chwd{$char} ; N $nchar ; B $chls{$char} ";
+ $astr .= "$v $chrs{$char} $chht{$char} ;\n";
+ $metrics_enc[$num] = $astr;
+ if ($acc =~ /^$supacc$/) {
+ $h = round(($chwd{$char} - ($chwd{$acc} * $shrink)) / 2
+ + $chls{$acc} * $shrink - ($v - $accdepth * $shrink) * $itadj);
+ }
+ else {
+ $h = round(($chwd{$char} - $chwd{$acc}) / 2 + $chls{$acc} - $v * $itadj);
+ }
+ unless (defined $hend{$char}) { findend($char, $chstrings{$char}) }
+ $H = $h - $hend{$char} - $chls{$char};
+ if ($acc =~ /^$supacc$/) { $V = $underadp - $vend{$char} }
+ else { $V = $v - $chdp{$acc} - $vend{$char} }
+ #
+ # Adjustment for smaller, therefore lower, shrunken accent defs
+ #
+ if ($acc =~ /^$supacc$/) {
+ $V += round($chdp{$acc} * (1 - $shrink) / $shrink);
+ }
+ $chstrings{$char} =~ /^\/$char {\n(\t.+?hsbw\n(.|\n)*?)\tendchar\n\t} $rend\n/m;
+ $chdef = $1;
+ $chstrings{$acc} =~ /^\/$acc {\n\t.+? .+?hsbw\n((.|\n)+?\t} $rend\n)/m;
+ $acdef = $1;
+ if ($acc =~ /^$supacc$/ and $opt_s) { $acdef = fixshrink($acc, $acdef) }
+ if ($acc =~ /^$supacc$/) {
+ $acdef = fixhints($nchar, $acc, $acdef, $h, $underadp);
+ }
+ else { $acdef = fixhints($nchar, $acc, $acdef, $h, $underddp) }
+ #
+ # Bloody Fontographer! We can't just say
+ # if ($acc =~ /^$supacc$/) { $V -= $accdepth }
+ # Instead we have to go through the following rigmarole:
+ #
+ if ($acc =~ /^$supacc$/) {
+ if ($acdef =~ /^(.*moveto)$/m) {
+ ($begin, $line, $end) = ($`, $1, $');
+ if ($line =~ /^\t(-?\d+) (-?\d+)( rmoveto)$/) {
+ $acdef = "$begin\t$1 " . ($2 - $accdepth) . $3 . $end;
+ }
+ elsif ($line =~ /^\t(-?\d+)( vmoveto)$/) {
+ $acdef = "$begin\t" . ($1 - $accdepth) . $2 . $end;
+ }
+ elsif ($line =~ /\t(-?\d+) hmoveto$/) {
+ $acdef = "$begin\t$1 " . (-$accdepth) . "rmoveto" . $end;
+ }
+ }
+ else { $acdef =~ s/\A/\t-$accdepth vmoveto\n/m }
+ }
+ $pstr = "/$nchar {\n$chdef % $nchar: start of $acname\n";
+ $pstr .= "\t$H $V rmoveto\n$acdef";
+ $chstrings{$nchar} = $pstr;
+}
+
+sub underb {
+ #
+ # Underbar
+ #
+ my ($num, $char, $nchar) = @_;
+ my ($old, $astr, $l, $h, $v, $H, $V, $bdef, $chdef, $acdef, $pstr);
+ ($old = $metrics_enc[$num]) =~ s/^C $num/C -1/;
+ $metrics_unenc .= $old unless $metrics_unenc =~ /$old/m;
+ $v = $underbdp + $thk;
+ getcharinfo($char) unless defined $chwd{$char};
+ $h = round(0.1 * $chwd{$char} - $underbdp * $itadj);
+ $l = round(0.8 * $chwd{$char});
+ $astr = "C $num ; WX $chwd{$char} ; N $nchar ; B $chls{$char} ";
+ $astr .= "$underbdp $chrs{$char} $chht{$char} ;\n";
+ $metrics_enc[$num] = $astr;
+ unless (defined $hend{$char}) { findend($char, $chstrings{$char}) }
+ $H = $h - $hend{$char} - $chls{$char};
+ $V = -$vend{$char};
+ $bdef = "\t$underbdp $thk hstem\n\t$v vmoveto\n\t-$thk vlineto\n\t";
+ $bdef .= "$l hlineto\n\t$thk vlineto\n\tclosepath\n";
+ $chstrings{$char} =~ /^\/$char {\n(\t.+?hsbw\n(.|\n)*?)\tendchar\n\t} $rend\n/m;
+ $chdef = $1;
+ $acdef = fixhints($nchar, "underbar", $bdef, $h, 0);
+ $pstr = "/$nchar {\n$chdef % $nchar: start of $acc\n";
+ $pstr .= "\t$H $V rmoveto\n$acdef\tendchar\n\t} $nd\n";
+ $chstrings{$nchar} = $pstr;
+}
+
+sub digraph {
+ #
+ # Make a new character consisting of two existing characters
+ #
+ my ($num, $char, $acc, $nchar) = @_;
+ my ($old, $kern, $w, $newrs, $astr, $H, $V, $chdef, $acdef, $pstr);
+ ($old = $metrics_enc[$num]) =~ s/^C $num/C -1/;
+ $metrics_unenc .= $old unless $metrics_unenc =~ /$old/m;
+ getcharinfo($char) unless defined $chwd{$char};
+ getcharinfo($acc) unless defined $chwd{$acc};
+ if ($kdefs =~ /^KPX $char $acc (-?\d+)$/m) { $kern = $1 };
+ $w = $chwd{$char} + $chwd{$acc} + $kern;
+ $newrs = $chrs{$char} + $chwd{$acc} + $kern;
+ if ($newrs > $maxrs) { $maxrs = $newrs }
+ $astr = "C $num ; WX " . $w . " ; N $nchar ; B $chls{$char} ";
+ $astr .= (min($chdp{$char}, $chdp{$acc})) . " $newrs ";
+ $astr .= (max($chht{$char}, $chht{$acc})) . " ;\n";
+ $metrics_enc[$num] = $astr;
+ unless (defined $hend{$char}) { findend($char, $chstrings{$char}) }
+ $H = $chwd{$char} + $chls{$acc} + $kern - $hend{$char};
+ $V = -$vend{$char};
+ $chstrings{$char} =~ /^\/$char {\n(\t.+?hsbw\n(.|\n)*?)\tendchar\n\t} $rend\n/m;
+ ($chdef = $1) =~ s/-?\d+( hsbw\n)/$w$1/m;
+ $chstrings{$acc} =~ /^\/$acc {\n\t.+? .+?hsbw\n((.|\n)+?\t} $rend\n)/m;
+ $acdef = $1;
+ $acdef = fixhints($nchar, $acc, $acdef, ($chwd{$char} + $kern), 0);
+ $pstr = "/$nchar {\n$chdef % $nchar: start of $acc\n";
+ $pstr .= "\t$H $V rmoveto\n$acdef";
+ $chstrings{$nchar} = $pstr;
+}
+
+sub max {
+ #
+ # Return greater of two values
+ #
+ my ($a, $b) = @_;
+ return $a > $b ? $a : $b;
+}
+
+sub min {
+ #
+ # Return lesser of two values
+ #
+ my ($a, $b) = @_;
+ return $a > $b ? $b : $a;
+}
+
+sub round {
+ #
+ # Return nearest integer value
+ #
+ my ($num) = shift;
+ my $n1, $n2;
+ if ($num < 0) { $n1 = (0 - $num) }
+ else { $n1 = $num }
+ $n2 = int($n1);
+ if (($n1 - $n2) >= 0.5) { $n2++ }
+ if ($num < 0) { return (0 - $n2) }
+ else { return $n2 }
+}
+
+sub getcharinfo {
+ #
+ # Store character metric information
+ #
+ my $char = shift;
+ my $foundit;
+ my $metrics_all = join("", @metrics_enc) . $metrics_unenc;
+ if ($metrics_all =~ /^.* ; N $char ; .*$/m) { $foundit = $& }
+ else { die "Bad definition (no such character/accent): $char\n" }
+ $foundit =~ /^C (-?\d+) ; WX (\d+) ; N $char ; B (.+?) (.+?) (.+?) (.+?) ;/;
+ ($chnum{$char}, $chwd{$char}, $chls{$char},
+ $chdp{$char}, $chrs{$char}, $chht{$char}) = ($1, $2, $3, $4, $5, $6);
+}
+
+sub fixkerns {
+ #
+ # Generalise the kerning info contained in the afm file by applying
+ # it to new accented chars. Do not kern lower-case chars bearing
+ # superscript accents with capitals, quotes or a preceding "f".
+ #
+ my ($char, $acc) = @_;
+ my ($lchar, $rchar);
+ if ($acc =~ /^$accents$/) { $lchar = $rchar = $char }
+ else {
+ $lchar = $char;
+ $rchar = $acc;
+ }
+ if ($char =~ /^[a-z]/ and $acc =~ /^$supacc$/) {
+ if ($kdefs =~ /^(KPX $char)(( (?:[a-pr-z][a-zA-Z]*|q(?!uote).*?) )-?\d+)$/m) {
+ ($one, $three) = ($1, $3);
+ $kdefs =~ s[^(KPX $char)(( (?:[a-pr-z][a-zA-Z]*|q(?!uote).*?) )-?\d+)$]
+ [$&\n$1$acc$2]gm
+ unless $kdefs =~ /^$one$acc$three/m;
+ }
+ if ($kdefs =~ /^(KPX (?:[a-eg-pr-z][a-zA-Z]*|q(?!uote).*?) $char)( -?\d+)$/m) {
+ $one = $1;
+ $kdefs =~ s[^(KPX (?:[a-eg-pr-z][a-zA-Z]*|q(?!uote).*?) $char)( -?\d+)$]
+ [$&\n$1$acc$2]gm
+ unless $kdefs =~ /^$one$acc /m;
+ }
+ }
+ else {
+ if ($kdefs =~ /^(KPX )$rchar(( [a-zA-Z]+ )-?\d+)$/m) {
+ ($one, $three) = ($1, $3);
+ $kdefs =~ s[^(KPX )$rchar(( [a-zA-Z]+ )-?\d+)$]
+ [$&\n$1$char$acc$2]gm
+ unless $kdefs =~ /^$one$char$acc$three/m;
+ }
+ if ($kdefs =~ /^(KPX [a-zA-Z]+ )$char( -?\d+)$/m) {
+ $one = $1;
+ $kdefs =~ s[^(KPX [a-zA-Z]+ )$char( -?\d+)$]
+ [$&\n$1$char$acc$2]gm
+ unless $kdefs =~ /^$one$char$acc /m;
+ }
+ }
+}
+
+sub fixshrink {
+ #
+ # Multiply all coordinates in a character definition by $shrink,
+ # creating new subroutines as necessary.
+ #
+ my ($ch, $chdef) = @_;
+ my (@chdef, $line, $snum, $subrdef);
+ @chdef = split(/\n/, $chdef);
+ $chdef = "";
+ foreach $line (@chdef) {
+ if ($line =~ /^\t(\d+) .*call(other)?subr$/) {
+ $snum = $1;
+ $subrdef = $subrs[$snum];
+ $subrdef = fixshrink($ch, $subrdef);
+ $subrdef =~ s/^(dup )$snum \{$/$1$subrsnum {\n % $nchar: shrink $ch/m;
+ $subrs[$subrsnum] = $subrdef;
+ $line =~ s/^\t$snum/\t$subrsnum/;
+ $subrsnum++;
+ }
+ else { $line =~ s/-?\d+/int($& * $shrink)/ge unless $line =~ /^dup / }
+ $chdef .= "$line\n";
+ }
+ return $chdef;
+}
+
+sub fixhints {
+ #
+ # First adjust any Flex "0 callsubr" lines for horizontal and
+ # vertical offset. Then collect the hints from the accent definition,
+ # remove them, adjust for horizontal and vertical offset, and
+ # place them in a numbered subroutine. Have the definition call
+ # the subroutine.
+ #
+ my ($nchar, $acc, $acdef, $h, $v) = @_;
+ my $subrdef;
+ $acdef =~ s[^(\t-?\d+ )(-?\d+) (-?\d+)( 0 callsubr)$]
+ [$1 . ($2 + $h) . " " . ($3 + $v) . $4]gme;
+ if ($subrdef = join("\n", grep /^\t.*[hv]stem$/, split(/\n/, $acdef))) {
+ $acdef = join("\n", grep !/^\t.*[hv]stem$/, split(/\n/, $acdef)) . "\n";
+ }
+ elsif ($acdef =~ s/\A(?:\t(\d+) callsubr\n)((?:.|\n)*)\Z/$2/m) {
+ $subrdef = $subrs[$1];
+ $subrdef = join("\n", grep /^\t.*[hv]stem$/, split(/\n/, $subrdef))
+ }
+ $subrdef =~ s/^(\t)(-?\d+)( .*hstem)$/$1 . ($2 + $v) . $3/gme;
+ $subrdef =~ s/^(\t)(-?\d+)( .*vstem)$/$1 . ($2 + $h) . $3/gme;
+ if ($subrdef) {
+ $subrs[$subrsnum] = "dup $subrsnum {\n % $nchar: hints for $acc\n";
+ $subrs[$subrsnum] .= "$subrdef\n\treturn\n\t} $np\n";
+ $acdef = "\t$subrsnum 1 3 callothersubr\n\tpop\n\tcallsubr\n" . $acdef;
+ $subrsnum++;
+ }
+ return $acdef;
+}
+
+sub findend {
+ #
+ # Calculate the current point reached at the end of the character
+ # definition. Place the horizontal offset in $hend{$char}, the
+ # vertical offset in $vend{$char}.
+ #
+ my ($char, $def) = @_;
+ my $line;
+ foreach $line (split /\n/, $def) {
+ SWITCH: {
+ $line =~ /^\t(-?\d+) h(line|move)to$/
+ && do {
+ $hend{$char} += $1;
+ last SWITCH;
+ };
+ $line =~ /^\t(-?\d+) v(line|move)to$/
+ && do {
+ $vend{$char} += $1;
+ last SWITCH;
+ };
+ $line =~ /^\t(-?\d+) (-?\d+) r(line|move)to$/
+ && do {
+ $hend{$char} += $1;
+ $vend{$char} += $2;
+ last SWITCH;
+ };
+ $line =~ /^\t(-?\d+) (-?\d+) (-?\d+) (-?\d+) hvcurveto$/
+ && do {
+ $hend{$char} += ($1 + $2);
+ $vend{$char} += ($3 + $4);
+ last SWITCH;
+ };
+ $line =~ /^\t(-?\d+) (-?\d+) (-?\d+) (-?\d+) vhcurveto$/
+ && do {
+ $hend{$char} += ($2 + $4);
+ $vend{$char} += ($1 + $3);
+ last SWITCH;
+ };
+ $line =~ /^\t(-?\d+) (-?\d+) (-?\d+) (-?\d+) (-?\d+) (-?\d+) rrcurveto$/
+ && do {
+ $hend{$char} += ($1 + $3 + $5);
+ $vend{$char} += ($2 + $4 + $6);
+ last SWITCH;
+ };
+ $line =~ /^\t(\d+) callsubr$/
+ && do {
+ findend($char, $subrs[$1]);
+ last SWITCH;
+ };
+ $line =~ /^\t-?\d+ (-?\d+) (-?\d+) 0 callsubr$/ # Flex
+ && do {
+ $hend{$char} = $1;
+ $vend{$char} = $2;
+ last SWITCH;
+ };
+ }
+ }
+}
diff --git a/fonts/utilities/accfonts/vpl2ovp b/fonts/utilities/accfonts/vpl2ovp
new file mode 100755
index 0000000000..eb88bfd3dd
--- /dev/null
+++ b/fonts/utilities/accfonts/vpl2ovp
@@ -0,0 +1,1085 @@
+#!/usr/bin/perl
+
+# Vpl2ovp: a program to generate accented virtual fonts for Omega
+# Copyright (C) 2008 John D. Smith
+
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$version = 0.25;
+#------------------------------------------------------------------------#
+$description =
+"Syntax: vpl2ovp -d definition-file [-s shrink-factor]
+ [-c candrabindu-adjustment] [-b] vpl-file
+
+Vpl2ovp creates new Omega virtual fonts based on existing TeX
+fonts or virtual fonts (\"input fonts\"). A successful run will
+read a pl (Property List) or vpl (Virtual Property List) file
+and a definition file, and will generate a new ovp (Omega
+Virtual Property List) file on standard output. The input font
+is assumed to adhere to the standard TeX encoding for text
+fonts unless it was created with either of the programs afm2pl
+or afm2tfm, in which case it is assumed to conform to
+(respectively) the Adobe Standard Encoding or the encoding
+specified in the file dvips.enc. In either case, the name of
+the input font is assumed to be the name of the input file
+without its .vpl or .pl extension: it must conform to normal
+TeX conventions for naming fonts, as vpl2ovp attempts to draw
+conclusions from it about the kind of font it is dealing with.
+
+A typical complete sequence of commands to create a new virtual
+font might therefore be
+ tftopl cmr10.tfm cmr10.pl
+ vpl2ovp -d Unicode1.def cmr10.pl >cmr10-uni1.ovp
+ ovp2ovf cmr10-uni1.ovp cmr10-uni1.ovf cmr10-uni1.ofm
+for a Computer Modern font, or
+ afm2pl Times-Roman.afm rptmr.pl
+ pltotf rptmr.pl rptmr.tfm
+ vpl2ovp -d Unicode1.def rptmr.pl >ptmr-uni1.ovp
+ ovp2ovf ptmr-uni1.ovp ptmr-uni1.ovf ptmr-uni1.ofm
+for a PostScript font.
+
+Another approach for a PostScript font is to use afm2tfm:
+ afm2tfm Times-Roman.afm -t dvips.enc -v ptmr rptmr
+ vpl2ovp -d Unicode1.def ptmr.vpl >ptmr-uni1.ovp
+ ovp2ovf ptmr-uni1.ovp ptmr-uni1.ovf ptmr-uni1.ofm
+-- but this is now deprecated, as afm2tfm generates incorrect
+values for the heights of some characters, and this can lead to
+bad accent placing.
+
+In order to keep the whole of the character range \"F0-\"FF free for
+the requirements of the encoding specified in the definition file,
+certain modifications are made to input fonts following the dvips.enc
+encoding to bring them into greater conformity with the TeX norm. In
+particular, the characters dotaccent and hungarumlaut are placed in
+the positions assigned by TeX (\"5F, \"7D), not those enforced by
+dvips.enc (\"C7, \"CD). The f-ligatures, double quotes and dashes are
+also moved from the upper half of the original 8-bit character set to
+their normal TeX positions. As a result, the following characters are
+not found in the lower half of the character set: quotesingle,
+quotedbl, backslash, underscore, braceleft, bar, braceright. These
+characters can, however, be assigned positions in the output font if
+they are needed. (Indeed, they could all be explicitly restored to
+their dvips.enc positions if this were desired.)
+
+Options:
+
+ -d should refer to a font definition file. This file (which could
+ usefully be named, e.g., \"Unicode1.def\") should consist of
+ lines of character definitions, in the form
+ \"number\" \"character\"
+ or
+ \"number\" \"character\" \"accent\"
+ Here \"number\" represents the character's position in the new
+ encoding and may be expressed in decimal, octal or hex;
+ \"character\" names the character (e.g. \"comma\", \"eight\",
+ \"A\") or consists of the word \".notdef\" (indicating that
+ the specified number's \"slot\" in the new encoding is to be
+ empty); and \"accent\" optionally names an accent to be placed
+ on the character. In addition to the standard accents available
+ in PostScript fonts, \"underbar\" and \"underdot\" are also
+ available, as are \"under\" versions of all the normal
+ superscript accents (\"underdieresis\", \"underring\", etc.).
+ The Indian accent \"candrabindu\" may also be specified: it
+ is formed by overprinting a breve with a dotaccent. Finally,
+ \"overdot\" may be used as a synonym for \"dotaccent\".
+
+ Note that all accents used in defining accented characters must
+ themselves be defined in the .def file. Those which exist in the
+ source font should simply be referenced by name in their
+ appropriate Unicode position (e.g. \"0x0304 macron\"); those
+ which do not should be defined as the character \"space\"
+ followed by the name of the accent (e.g. \"0x0310 space
+ candrabindu\").
+
+ If the character named in the \"accent\" position is not in fact
+ a valid accent character, the program interprets the definition
+ as a request for a digraph formed from the \"character\" and the
+ \"accent\". A digraph consisting of, say, \"k\" and \"h\" will be
+ indistinguishable from the letters \"k\" and \"h\" printed
+ consecutively, but the digraph \"kh\" can itself receive accents
+ like any other character: see next paragraph.
+
+ A new character (such as \"amacron\" or \"kh\") may be freely
+ used in the \"character\" position of a further definition (such
+ as \"amacron breve\" or \"kh underbar\"). There is no constraint
+ on the ordering of definitions within a definition file. The
+ definition of \"a macron\" does not have to precede that of
+ \"amacron breve\": requests for \"impossible\" characters are
+ deferred until their constituents have had a chance to come into
+ being.
+
+ \"Slots\" for which no new definition is given retain the
+ definition they have in the input font.
+
+ The definition file may also contain blank lines and comments
+ (introduced by \"\#\").
+
+ -s may optionally give the factor, expressed as a per-thousand
+ value, by which normally superscript accents (such as dieresis,
+ ring) should be shrunk when they are used as subscript accents
+ (such as underdieresis, underring). Values of around 800 may be
+ found useful.
+
+ -c may optionally give two comma-separated numerical values to
+ adjust the x and y coordinates of the dotaccent placed within a
+ breve to form the candrabindu accent. A coordinate scheme using
+ \"DESIGNUNITS R 1000\" is assumed.
+
+ -b may optionally be specified to block the use of predefined
+ accented characters, forcing vpl2ovp to define its own
+ versions. This may be useful to secure a consistent appearance
+ in cases where a font designer does not share vpl2ovp's views
+ on where accents should be placed.
+
+ -h prints this help.
+";
+#------------------------------------------------------------------------#
+
+########################
+# Packages and constants
+########################
+#
+use File::Basename;
+use Getopt::Std;
+$cmdline = basename($0) . " " . join " ", @ARGV;
+getopts('d:s:c:bh');
+if ($opt_h or !$opt_d or $#ARGV != 0) {
+ print STDERR $description;
+ exit 1;
+}
+
+$filename = $ARGV[0];
+$dummycodepoint = 0xF8FF;
+($fontname = $filename) =~ s/\..*$//;
+($encname = basename($opt_d)) =~ s/\..*$//;
+$vtitle = "(VTITLE Font $fontname modified for $encname encoding by vpl2ovp";
+$vtitle .= " v. $version" if $version;
+$vtitle .= ")\n(COMMENT Command line: $cmdline)";
+$vtitle .= "\n(OFMLEVEL H 0)";
+
+#
+# Flags for bold and small caps. These are probably a bit iffy, but
+# there's not much that can be done about it.
+#
+if ($fontname =~ /(^p.*b[oi]?[c]?$|^[^p].*bx[a-z]*[0-9]+$)/) { $bold = 1 }
+if ($fontname =~ /(^p.*c$|^[^p].*csc[a-z]*[0-9]+$)/) { $scaps = 1 }
+if ($opt_s) { $shrink = $opt_s / 1000 } else { $shrink = 1 }
+
+#
+# Array to convert from number to vpl representation
+#
+foreach $i (0 .. 0xFFFF) {
+ $nv[$i] = (chr($i) =~ /[0-9A-Za-z]/ ? "C " . chr $i : sprintf("H %04lX", $i));
+}
+
+#
+# Now the encoding vectors.
+#
+@TeXenc = (
+ "Gamma", "Delta", "Theta", "Lambda",
+ "Xi", "Pi", "Sigma", "Upsilon",
+ "Phi", "Psi", "Omega", "ff",
+ "fi", "fl", "ffi", "ffl",
+ "dotlessi", "dotlessj", "grave", "acute",
+ "caron", "breve", "macron", "ring",
+ "cedilla", "germandbls", "ae", "oe",
+ "oslash", "AE", "OE", "Oslash",
+ "space", "exclam", "quotedblright", "numbersign",
+ "dollar", "percent", "ampersand", "quoteright",
+ "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash",
+ "zero", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine", "colon", "semicolon",
+ "exclamdown", "equal", "questiondown", "question",
+ "at", "A", "B", "C",
+ "D", "E", "F", "G",
+ "H", "I", "J", "K",
+ "L", "M", "N", "O",
+ "P", "Q", "R", "S",
+ "T", "U", "V", "W",
+ "X", "Y", "Z", "bracketleft",
+ "quotedblleft", "bracketright", "circumflex", "dotaccent",
+ "quoteleft", "a", "b", "c",
+ "d", "e", "f", "g",
+ "h", "i", "j", "k",
+ "l", "m", "n", "o",
+ "p", "q", "r", "s",
+ "t", "u", "v", "w",
+ "x", "y", "z", "endash",
+ "emdash", "hungarumlaut", "tilde", "dieresis"
+);
+
+@dvipsenc = (
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", "quotesingle", "exclamdown", "questiondown",
+ "dotlessi", "dotlessj", "grave", "acute",
+ "caron", "breve", "macron", "ring",
+ "cedilla", "germandbls", "ae", "oe",
+ "oslash", "AE", "OE", "Oslash",
+ "space", "exclam", "quotedbl", "numbersign",
+ "dollar", "percent", "ampersand", "quoteright",
+ "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash",
+ "zero", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine", "colon", "semicolon",
+ "less", "equal", "greater", "question",
+ "at", "A", "B", "C",
+ "D", "E", "F", "G",
+ "H", "I", "J", "K",
+ "L", "M", "N", "O",
+ "P", "Q", "R", "S",
+ "T", "U", "V", "W",
+ "X", "Y", "Z", "bracketleft",
+ "backslash", "bracketright", "circumflex", "underscore",
+ "quoteleft", "a", "b", "c",
+ "d", "e", "f", "g",
+ "h", "i", "j", "k",
+ "l", "m", "n", "o",
+ "p", "q", "r", "s",
+ "t", "u", "v", "w",
+ "x", "y", "z", "braceleft",
+ "bar", "braceright", "tilde", "dieresis",
+ "asciicircum", "asciitilde", "Ccedilla", "Iacute",
+ "Icircumflex", "atilde", "edieresis", "egrave",
+ "scaron", "zcaron", "Eth", "ff",
+ "ffi", "ffl", ".notdef", ".notdef",
+ ".notdef", ".notdef", "Scaron", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ "Ydieresis", ".notdef", "Zcaron", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", "cent", "sterling",
+ "fraction", "yen", "florin", "section",
+ "currency", "copyright", "quotedblleft", "guillemotleft",
+ "guilsinglleft", "guilsinglright", "fi", "fl",
+ "degree", "endash", "dagger", "daggerdbl",
+ "periodcentered", ".notdef", "paragraph", "bullet",
+ "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
+ "ellipsis", "perthousand", ".notdef", ".notdef",
+ "Agrave", "Aacute", "Acircumflex", "Atilde",
+ "Adieresis", "Aring", ".notdef", "dotaccent",
+ "Egrave", "Eacute", "Ecircumflex", "Edieresis",
+ "Igrave", "hungarumlaut", "ogonek", "Idieresis",
+ "emdash", "Ntilde", "Ograve", "Oacute",
+ "Ocircumflex", "Otilde", "Odieresis", ".notdef",
+ ".notdef", "Ugrave", "Uacute", "Ucircumflex",
+ "Udieresis", "Yacute", "Thorn", ".notdef",
+ "agrave", "aacute", "acircumflex", "ordfeminine",
+ "adieresis", "aring", ".notdef", "ccedilla",
+ "Lslash", "eacute", "ecircumflex", "ordmasculine",
+ "igrave", "iacute", "icircumflex", "idieresis",
+ ".notdef", "ntilde", "ograve", "oacute",
+ "ocircumflex", "otilde", "odieresis", ".notdef",
+ "lslash", "ugrave", "uacute", "ucircumflex",
+ "udieresis", "yacute", "thorn", "ydieresis"
+);
+
+@adobeenc=(
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ "space", "exclam", "quotedbl", "numbersign",
+ "dollar", "percent", "ampersand", "quoteright",
+ "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash",
+ "zero", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine", "colon", "semicolon",
+ "less", "equal", "greater", "question",
+ "at", "A", "B", "C",
+ "D", "E", "F", "G",
+ "H", "I", "J", "K",
+ "L", "M", "N", "O",
+ "P", "Q", "R", "S",
+ "T", "U", "V", "W",
+ "X", "Y", "Z", "bracketleft",
+ "backslash", "bracketright", "asciicircum", "underscore",
+ "quoteleft", "a", "b", "c",
+ "d", "e", "f", "g",
+ "h", "i", "j", "k",
+ "l", "m", "n", "o",
+ "p", "q", "r", "s",
+ "t", "u", "v", "w",
+ "x", "y", "z", "braceleft",
+ "bar", "braceright", "asciitilde", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", "exclamdown", "cent", "sterling",
+ "fraction", "yen", "florin", "section",
+ "currency", "quotesingle", "quotedblleft", "guillemotleft",
+ "guilsinglleft", "guilsinglright", "fi", "fl",
+ ".notdef", "endash", "dagger", "daggerdbl",
+ "periodcentered", ".notdef", "paragraph", "bullet",
+ "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
+ "ellipsis", "perthousand", ".notdef", "questiondown",
+ ".notdef", "grave", "acute", "circumflex",
+ "tilde", "macron", "breve", "dotaccent",
+ "dieresis", ".notdef", "ring", "cedilla",
+ ".notdef", "hungarumlaut", "ogonek", "caron",
+ "emdash", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", "AE", ".notdef", "ordfeminine",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ "Lslash", "Oslash", "OE", "ordmasculine",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", "ae", ".notdef", ".notdef",
+ ".notdef", "dotlessi", ".notdef", ".notdef",
+ "lslash", "oslash", "oe", "germandbls",
+ ".notdef", ".notdef", ".notdef", ".notdef"
+);
+
+###############
+# Read DEF file
+###############
+#
+open DEF, $opt_d or die "Cannot open $opt_d: $!\n";
+while (<DEF>) {
+ next if (/^\s*$/ || /^\#/);
+ s/\s*(\#.*)?$//;
+ push @deflines, $_;
+}
+close DEF;
+
+###############
+# Read VPL file
+###############
+#
+# File header
+#
+$vplhead = <> or exit 1;
+unless ($vplhead =~ /^\((VTITLE|FAMILY) /) {
+ die "$filename is not a vpl file: giving up\n"
+}
+do {
+ $_ = <>;
+ $vplhead .= $_;
+} until ($_ =~ /^\(LIGTABLE$/ or eof);
+if (eof) {
+ die "$filename does not seem to be a text font (no LIGTABLE): giving up\n";
+}
+if ($vplhead =~ s/\A\(VTITLE(.*)$/$vtitle\n(COMMENT Old vtitle:$1/m) {
+ $vplhead =~ s/\n\(COMMENT Please edit that VTITLE .*\)$//m;
+ @enc = @dvipsenc;
+ $dvips = 1;
+}
+elsif ($vplhead =~ /\A\(FAMILY.*\)\n\(CODINGSCHEME ADOBESTANDARDENCODING\)$/m) {
+ $vplhead =~ s/\A/$vtitle\n/m;
+ @enc = @adobeenc;
+ $dvips = 0;
+}
+else {
+ $vplhead =~ s/\A/$vtitle\n/m;
+ @enc = @TeXenc;
+ $dvips = 0;
+}
+if ($vplhead =~ /^\(CODINGSCHEME TEX MATH SYMBOLS/m) {
+ die "$filename is a TeX math font: giving up\n";
+}
+unless ($vplhead =~ s/^(\(CODINGSCHEME .*\+\s?)(\S+)\)$/$1$encname)/m) {
+ $vplhead =~ s/^(\(CODINGSCHEME .*)\)$/$1 + $encname)/m;
+}
+if ($vplhead =~ s/^\(DESIGNUNITS R (.+)\)\n//m) { $scale = $1 }
+else { $scale = 1 }
+$vplhead =~ s/^\(COMMENT.*DESIGNSIZE.*\)\n//gm;
+$vplhead =~ s/^\(BOUNDARYCHAR.*\)\n//gm;
+if ($vplhead =~ /^ \(SLANT R (.+)\)/m) { $slant = $1 }
+if ($vplhead =~ /^ \(XHEIGHT [DR] (.+)\)/m) { $xheight = $1 }
+unless ($vplhead =~ /^\(MAPFONT /m) {
+ if ($vplhead =~ /^\(DESIGNSIZE R (.*)\)$/m) { $dsize = $1 *$scale }
+ $mapfont = "\n(MAPFONT D 0\n (FONTNAME $fontname)\n (FONTDSIZE R $dsize)\n )";
+ $vplhead =~ s/\n\(LIGTABLE\Z/$mapfont$&/m;
+}
+$vplhead =~ s/^(\(FONTDIMEN)/(SEVENBITSAFEFLAG FALSE)\n$1/m;
+if ($opt_s) {
+ $vplhead =~ s[^(\(MAPFONT D )0(.*?)( \))]
+ [$&\n${1}1$2 (FONTAT R ${ \($shrink * $scale) })\n$3]ms;
+}
+@vplhead = split /^/, $vplhead;
+foreach (@vplhead) {
+ s[(?<!(IGNSIZE|MAPFONT)) [RD] (-?)([0-9.]+)\)]
+ [" R " . $2 . $3/$scale . ")"]ge
+}
+
+#
+# Ligatures and kerns
+#
+do {
+ $_ = <>;
+ s/ \(comment .*$//i;
+ s/^( \((?:LABEL|KRN) )O ([0-7]+)(.*)$/$1 . sprintf("H %04lX", oct $2) . $3/e;
+if (/ \(LIG /) {
+ s/O ([0-7]+)/sprintf("H %04lX", oct $1)/ge;
+ }
+ $ligs .= $_;
+} until $_ =~ /^ \)/;
+#
+# Now build a hash to convert from vpl representation to char name
+# and use it to make ligtable readable
+#
+foreach $i (0 .. 255) { $vc{$nv[$i]} = $enc[$i] }
+$ligs =~ s/^( \((?:LABEL|KRN) )(\S+ \S+)(.*\))$/$1$vc{$2}$3/gm;
+$ligs =~ s/^( \(LIG )(\S+ \S+) (\S+ \S+)\)$/$1$vc{$2} $vc{$3})/gm;
+#
+# Character definitions: store "encoded" defs in @chars, store *all*
+# defs in %allchars
+#
+$_ = <>;
+do {
+ if (/^\(CHARACTER/) {
+ $character = $_;
+ do {
+ $_ = <>;
+ $character .= $_;
+ } until $_ =~ /^ \)/;
+ storeinfo($character);
+ $_ = <>;
+ }
+} until eof;
+foreach $i (0 .. $#chars) {
+ if ($chars[$i] and $enc[$i] ne ".notdef") {
+ $allchars{$enc[$i]} = $chars[$i];
+ }
+}
+
+##################
+# Set up constants
+##################
+
+$subacc = "(cedilla|ogonek|commaaccent)";
+$supacc = "(grave|acute|circumflex|tilde|macron|breve|dotaccent|overdot|dieresis|ring|hungarumlaut|caron|candrabindu)";
+$underacc = "(underdot|under$supacc)";
+$accents = "($subacc|$supacc|$underacc|underbar)";
+$underadp = 0.230; # depth of "under" accs
+$underddp = 0.213; # depth of underdot
+if ($bold) { $thk = 0.072 } else { $thk = 0.052 } # thickness and
+$underbdp = 0.082 + $thk; # depth of underbar
+$capheight = $allchars{"X"}{ht};
+$accheight = $allchars{"macron"}{ht};
+$accdepth = $accheight - $thk * $scale; # probable approx. "depth" of macron
+$v1 = $accheight - $xheight; # vertical offset for double accents
+$v2 = $capheight - $xheight; # vertical offset for accented caps etc
+if ($scaps) { # accented small caps
+ $scoffset = $allchars{"x"}{ht} - $xheight;
+ $v1 += $scoffset;
+}
+if ($opt_c) { # candrabindu
+ ($cbx, $cby) = $opt_c =~ /^(.*),(.*)$/;
+ $cbx += ($allchars{"breve"}{wd} - $allchars{"dotaccent"}{wd}) / 2;
+ $cbx /= 1000;
+ $cby /= 1000;
+}
+
+######################
+# Build the characters
+######################
+#
+# First normalise dvips.enc encoding quirks
+#
+if ($dvips) {
+ chmove("fi", 014);
+ chmove("fl", 015);
+ chmove("quotedblright", 042);
+ chmove("quotedblleft", 0134);
+ chmove("dotaccent", 0137);
+ chmove("endash", 0173);
+ chmove("emdash", 0174);
+ chmove("hungarumlaut", 0175);
+}
+#
+# Now build a list of definitions supplied by user
+#
+for (@deflines) {
+ if (/^\s*(\d+|0[0-7]+|0x[0-9a-fA-F]+)\s+([a-zA-Z]+?|\.notdef)(?:\s+([a-zA-Z]+))?$/) {
+ ($num, $char, $acc) = ($1, $2, $3);
+ $num = oct $num if $num =~ /^0/;
+ if ($num > 0xFFFF) { die "Bad definition (number out of range): $_\n" }
+ $def = {};
+ $def->{qdef} = $_;
+ $def->{num} = $num;
+ $def->{char} = $char;
+ $def->{acc} = $acc;
+ if ($char eq "space") { $def->{nchar} = $acc }
+ else { $def->{nchar} = $char . $acc }
+ push @nchars, $def->{nchar};
+ push @defs, $def;
+ }
+ else { die "Bad definition: $_\n" }
+}
+#
+# Work through the list
+#
+while (@defs) {
+ $def = shift @defs;
+ $qdef = $def->{qdef};
+ $num = $def->{num};
+ $char = $def->{char};
+ $acc = $def->{acc};
+ $nchar = $def->{nchar};
+ #
+ # If we can't handle $char/$acc yet, but believe we will be able
+ # to later, send the definition to the back of the queue. In case
+ # it later turns out we were wrong, allow only five loops before
+ # giving up.
+ #
+ if (!$allchars{$char} and $char ne ".notdef") {
+ if (grep /^$char$/, @nchars) {
+ unless (++$def->{requeue} > 5) {
+ push @defs, $def;
+ next;
+ }
+ }
+ else { die "Bad definition (no such character): $qdef\n" }
+ }
+ if ($acc and !$allchars{$acc} and $acc !~ /^$accents$/) {
+ if (grep /^$acc$/, @nchars) {
+ unless (++$def->{requeue} > 5) {
+ push @defs, $def;
+ next;
+ }
+ }
+ else { die "Bad definition (no such accent): $qdef\n" }
+ }
+ #
+ # Remove any existing claims on $num
+ #
+ @{ $allchars{$chars[$num]{id}}{num} } = grep !/$num/,
+ @{ $allchars{$chars[$num]{id}}{num} };
+ #
+ # First deal with .notdef
+ #
+ if ($nchar eq ".notdef") {
+ undef $chars[$num];
+ }
+ #
+ # Next look among existing chars (unless blocked by -b)
+ #
+ elsif (!($acc and $opt_b) and $allchars{$nchar}) {
+ push( @{ $allchars{$nchar}{num} }, $num);
+ $chars[$num] = $allchars{$nchar};
+ }
+ #
+ # If it can't be built from sub-elements, issue a warning and move on
+ #
+ elsif (!$acc) {
+ warn "No such character - ignoring definition: $qdef\n";
+ undef $chars[$num];
+ }
+ #
+ # Now build the char
+ #
+ else {
+ #
+ # First get rid of predefined/duplicated ligtable statements
+ # and character definitions; also synonyms
+ #
+ $ligs =~ s/\n \((LABEL|KRN|LIG) ($nchar .*|.*$nchar)\)$//gm;
+ $allchars{$nchar} = ();
+ if ($acc eq "overdot") {
+ $nchar2 = $char . "dotaccent";
+ $ligs =~ s/\n \((LABEL|KRN|LIG) ($nchar2 .*|.*$nchar2)\)$//gm;
+ delete $allchars{$nchar2};
+ }
+ #
+ # Store the info that will be needed to have the character
+ # linked into the LIGTABLE
+ #
+ push @newligs, "$char: (LIG $acc $nchar)";
+ #
+ # Go!
+ #
+ if ($acc =~ /^$subacc$/) {
+ subacc($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ elsif ($acc =~ /^$supacc$/) {
+ supacc($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ elsif ($acc =~ /^$underacc$/) {
+ underacc($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ elsif ($acc =~ /^underbar$/) {
+ underb($num, $char, $nchar);
+ fixkerns($char, $acc);
+ }
+ else {
+ digraph($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ }
+}
+
+###################
+# Sort out ligtable
+###################
+#
+# Pull in the newly created ligatures
+#
+foreach $newlig (@newligs) {
+ $newlig =~ s/^(.+)://;
+ $newelm1 = $1;
+ unless ($ligs =~ s/(^ \(LABEL $newelm1\)\n)/$1$newlig\n/m) {
+ $ligs =~ s[^( \)\n)]
+ [ \(LABEL $newelm1\)\n$newlig\n \(STOP\)\n$1]m
+ }
+}
+#
+# Convert to vpl representation, eliminating statements invoking
+# "unencoded" characters
+#
+@liglist = split /\n/, $ligs;
+$ligs = "";
+foreach (@liglist) {
+ if (/^( \(LIG \S+ )(\S+)\)$/) {
+ if ($n = ${ $allchars{$2}{num} }[0]) {
+ s/^( \(LIG \S+ )(\S+)\)$/$1$nv[$n])/;
+ }
+ else { next }
+ }
+ if (/^( \((?:LABEL|LIG|KRN) )([^ )]+)(.*)$/) {
+ ($one, $two, $three) = ($1, $2, $3);
+ foreach $n (@{ $allchars{$two}{num} }) {
+ $ligs .= "$one$nv[$n]$three\n";
+ }
+ }
+ else { $ligs .= "$_\n" }
+}
+#
+# Eliminate sequences orphaned by elimination of a LABEL
+#
+@liglist = split / \(STOP\)\n/, $ligs;
+$ligs = "";
+foreach (@liglist) {
+ if (/^ \(LABEL /m) { $ligs .= "$_ (STOP)\n" }
+ elsif (/^ \)$/m) { $ligs .= $_ }
+}
+#
+# Eliminate empty statements
+#
+$ligs =~ s/(^ \(LABEL .*\)\n)+ \(STOP\)\n//gm;
+@ligs = split /^/, $ligs;
+foreach (@ligs) {
+ s/ [RD] (-?)([0-9.]+)\)/" R " . $1 . $2\/$scale . ")"/ge
+}
+
+####################
+# Output the results
+####################
+#
+print @vplhead, @ligs;
+foreach $i (0 .. 0xFFFF) { if (defined $chars[$i]{id}) { printchar($i) } }
+
+#####################
+# End of main program
+#####################
+
+sub storeinfo {
+ #
+ # Extract info from a character definition and store it in @chars
+ #
+ my $char = shift;
+ my $num;
+ if ($char =~ /\A\(CHARACTER O ([0-7]+)/m) { $num = oct $1 }
+ elsif ($char =~ /\A\(CHARACTER C (.)/m) { $num = ord $1 }
+ $chars[$num]{id} = $enc[$num];
+ push( @{ $chars[$num]{num} }, $num);
+ if ($char =~ /^ \(CHARWD R (.*?)\)$/m) { $chars[$num]{wd} = $1 }
+ if ($char =~ /^ \(CHARHT R (.*?)\)$/m) { $chars[$num]{ht} = $1 }
+ if ($char =~ /^ \(CHARDP R (.*?)\)$/m) { $chars[$num]{dp} = $1 }
+ if ($char =~ /^ \(CHARIC R (.*?)\)$/m) { $chars[$num]{ic} = $1 }
+ if ($char =~ /^ \(MAP\n((.|\n)*)^ \)/m) { $chars[$num]{map} = $1 }
+ else { $chars[$num]{map} = " (SETCHAR $nv[$num])\n" }
+ $chars[$num]{map} =~ s[(\(SETCHAR )O ([0-7]+)\)]
+ [$1 . sprintf("H %04lX", oct $2) . ")"]gme
+}
+
+sub printchar {
+ #
+ # Extract info from @chars and build it into a character definition
+ #
+ my $num = shift;
+ my @ch;
+ push @ch, "(CHARACTER ";
+ if (chr($num) =~ /[0-9A-Za-z]/) { push @ch, "C " . chr($num) }
+ else {
+ push @ch, sprintf("H %04lX", $num);
+ push @ch, " (COMMENT " . $chars[$num]{id} . ")";
+ }
+ push @ch, "\n";
+ push @ch, " (CHARWD R " . $chars[$num]{wd} . ")\n"
+ if defined $chars[$num]{wd};
+ push @ch, " (CHARHT R " . $chars[$num]{ht} . ")\n"
+ if defined $chars[$num]{ht};
+ push @ch, " (CHARDP R " . $chars[$num]{dp} . ")\n" if $chars[$num]{dp};
+ push @ch, " (CHARIC R " . $chars[$num]{ic} . ")\n" if $chars[$num]{ic};
+ push @ch, " (MAP\n";
+ push @ch, $chars[$num]{map};
+ push @ch, " )\n";
+ push @ch, " )\n";
+ foreach (@ch) {
+ s/(?<!SELECTFONT) [RD] (-?)([0-9.]+)\)/" R " . $1 . $2\/$scale . ")"/ge
+ }
+ print @ch
+}
+
+sub chmove {
+ #
+ # Move a character
+ #
+ my ($char, $num) = @_;
+ my $i;
+ foreach $i (@{ $allchars{$char}{num} }) { undef $chars[$i] }
+ @{ $allchars{$char}{num} } = ();
+ @{ $allchars{$chars[$num]{id}}{num} } = grep !/$num/,
+ @{ $allchars{$chars[$num]{id}}{num} };
+ push( @{ $allchars{$char}{num} }, $num);
+ $chars[$num] = $allchars{$char};
+}
+
+sub max {
+ #
+ # Return greater of two values
+ #
+ my ($a, $b) = @_;
+ return $a > $b ? $a : $b;
+}
+
+sub subacc {
+ #
+ # Subscript accents
+ #
+ my ($num, $char, $acc, $id) = @_;
+ my ($h, $s1, $s2, $s3);
+ $allchars{$id}{wd} = $allchars{$char}{wd};
+ $allchars{$id}{ht} = $allchars{$char}{ht};
+ $allchars{$id}{dp} = $allchars{$acc}{dp};
+ $allchars{$id}{ic} = $allchars{$char}{ic};
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ $s1 = $allchars{$char}{map};
+ $s1 =~ s/\A (.*)\n\Z/(PUSH) $1 (POP)/s;
+ $h = sprintf("%.3f", ($allchars{$char}{wd} - $allchars{$acc}{wd}) / 2);
+ if ($h > 0) { $s2 = " (MOVERIGHT R $h) " }
+ elsif ($h < 0) {
+ $h = -$h;
+ $s2 = " (MOVELEFT R $h) ";
+ }
+ else { $s2 = " " }
+ $s3 = $allchars{$acc}{map};
+ $s3 =~ s/\A.*(\(SETCHAR . .+?\)).*\Z/$1/s;
+ $allchars{$id}{map} = " $s1\n$s2$s3\n";
+ $chars[$num] = $allchars{$id};
+}
+
+sub supacc {
+ #
+ # Superscript accents
+ #
+ my ($num, $char, $acc, $id) = @_;
+ my ($cb, $h, $hadj, $tallchar, $ic, $s1, $s2, $s3);
+ if ($char eq "i" and $allchars{"dotlessi"}) { $char = "dotlessi" }
+ if ($char eq "j" and $allchars{"dotlessj"}) { $char = "dotlessj" }
+ if ($acc eq "overdot") { $acc = "dotaccent" }
+ if ($acc eq "candrabindu") {
+ $acc = "breve";
+ ($cb = $allchars{"dotaccent"}{map}) =~ s/\A.*(\(SETCHAR . .+?\)).*\Z/$1/s;
+ }
+ $allchars{$id}{wd} = $allchars{$char}{wd};
+ $allchars{$id}{ht} = $allchars{$acc}{ht};
+ $allchars{$id}{dp} = $allchars{$char}{dp};
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ $s1 = $allchars{$char}{map};
+ $s1 =~ s/\A (.*)\n\Z/(PUSH) $1 (POP)/s;
+ if ($scaps and $char =~ /^[a-z]/) { # accented small caps
+ $tallchar = 1;
+ if ($char =~ /$supacc$/
+ and $char !~ /under$supacc$/) { # double accs
+ $s2 = " (MOVEUP R $v1)";
+ $allchars{$id}{ht} += $v1;
+ $hadj = sprintf("%.3f", $v1 * $slant);
+ $ic = $allchars{$char}{ic};
+ }
+ else { # single accs
+ $s2 = " (MOVEUP R $scoffset)";
+ $allchars{$id}{ht} += $scoffset;
+ $hadj = sprintf("%.3f", $scoffset * $slant);
+ $ic = $allchars{$acc}{ic} + $hadj;
+ }
+ }
+ elsif ($allchars{$char}{ht} >= ($accheight + $v2)) { # double accs
+ $tallchar = 1; # on caps etc.
+ $s2 = " (MOVEUP R ${ \($v1 + $v2) })";
+ $allchars{$id}{ht} += ($v1 + $v2);
+ $hadj = sprintf("%.3f", ($v1 + $v2) * $slant);
+ $ic = $allchars{$char}{ic};
+ }
+ elsif ($allchars{$char}{ht} > 1.15 * $xheight) {
+ $tallchar = 1;
+ if ($char =~ /$supacc$/
+ and $char !~ /under$supacc$/) { # double accs
+ $s2 = " (MOVEUP R $v1)";
+ $allchars{$id}{ht} += $v1;
+ $hadj = sprintf("%.3f", $v1 * $slant);
+ $ic = $allchars{$char}{ic};
+ }
+ else { # caps etc.
+ $s2 = " (MOVEUP R $v2)";
+ $allchars{$id}{ht} += $v2;
+ $hadj = sprintf("%.3f", $v2 * $slant);
+ $ic = $allchars{$char}{ic};
+ }
+ }
+ else { # single accs
+ $s2 = " ";
+ $ic = $allchars{$acc}{ic};
+ }
+ $h = sprintf("%.3f", ($allchars{$char}{wd} - $allchars{$acc}{wd}) / 2);
+ unless ($tallchar) { $ic -= $h }
+ $allchars{$id}{ic} = $ic unless $ic < 0;
+ $h += $hadj;
+ if ($h > 0) { $s2 .= " (MOVERIGHT R $h) " }
+ elsif ($h < 0) {
+ $h = -$h;
+ $s2 .= " (MOVELEFT R $h) ";
+ }
+ else { $s2 .= " " }
+ $s3 = $allchars{$acc}{map};
+ $s3 =~ s/\A.*(\(SETCHAR . .+?\)).*\Z/$1/s;
+ if ($cb) { # candrabindu
+ $cb = $s2 . $cb;
+ if ($cbx) {
+ unless (($cb =~ s/(MOVERIGHT R )([0-9.]+)/$1 . ($2 + $cbx * $scale)/e)
+ or ($cb =~ s/(MOVELEFT R )([0-9.]+)/$1 . ($2 - $cbx * $scale)/e)) {
+ $cb =~ s/^( +)/"$1(MOVERIGHT R " . ($cbx * $scale) . ") "/e;
+ }
+ }
+ if ($cby) {
+ unless ($cb =~ s/(MOVEUP R )([0-9.]+)/$1 . ($2 + $cby * $scale)/e) {
+ $cb =~ s/^( +)/"$1(MOVEUP R " . ($cby * $scale) . ") "/e;
+ }
+ }
+ $cb .= "\n";
+ $s1 = "(PUSH) " . $s1;
+ $s3 .= " (POP)";
+ }
+ $allchars{$id}{map} = " $s1\n$s2$s3\n$cb";
+ $chars[$num] = $allchars{$id};
+}
+
+sub underacc {
+ #
+ # Dropped accents
+ #
+ my ($num, $char, $acc, $id) = @_;
+ my ($h, $v, $s1, $s2, $s3);
+ $acc =~ s/^under//;
+ if ($acc eq "dot") { $acc = "period" }
+ if ($acc eq "candrabindu") { die "Bad definition (no such accent): $qdef\n" }
+ $allchars{$id}{wd} = $allchars{$char}{wd};
+ $allchars{$id}{ht} = $allchars{$char}{ht};
+ $allchars{$id}{ic} = $allchars{$char}{ic};
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ if ($acc =~ /^$supacc$/) {
+ $v = $allchars{$id}{dp} = $underadp * $scale * $shrink;
+ $v += ($accdepth * $shrink);
+ }
+ else {
+ $v = $allchars{$id}{dp} = $underddp * $scale + $allchars{$acc}{dp};
+ }
+ $s1 = $allchars{$char}{map};
+ $s1 =~ s/\A (.*)\n\Z/(PUSH) $1 (POP)/s;
+ if ($acc =~ /^$supacc$/) {
+ $h = ($allchars{$char}{wd} - ($allchars{$acc}{wd} * $shrink)) / 2 - $v * $slant;
+ if ($opt_s) { $s2 = " (SELECTFONT D 1)\n" }
+ }
+ else {
+ $h = ($allchars{$char}{wd} - $allchars{$acc}{wd}) / 2 - $v * $slant;
+ }
+ $h = sprintf("%.3f", $h);
+ if ($h > 0) {
+ $s2 .= " (MOVEDOWN R $v) (MOVERIGHT R $h) ";
+ }
+ elsif ($h < 0) {
+ $h = -$h;
+ $s2 .= " (MOVEDOWN R $v) (MOVELEFT R $h) ";
+ }
+ else { $s2 = " (MOVEDOWN R $v) " }
+ $s3 = $allchars{$acc}{map};
+ $s3 =~ s/\A.*(\(SETCHAR . .+?\)).*\Z/$1/s;
+ if ($opt_s and $acc =~ /^$supacc$/) { $s3 .= "\n (SELECTFONT D 0)" }
+ $allchars{$id}{map} = " $s1\n$s2$s3\n";
+ $chars[$num] = $allchars{$id};
+}
+
+sub underb {
+ #
+ # Underbar
+ #
+ my ($num, $char, $id) = @_;
+ my ($h, $w, $dp, $s1, $s2, $s3);
+ $allchars{$id}{wd} = $allchars{$char}{wd};
+ $allchars{$id}{ht} = $allchars{$char}{ht};
+ $allchars{$id}{dp} = $dp = $underbdp * $scale;
+ $allchars{$id}{ic} = $allchars{$char}{ic};
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ $s1 = $allchars{$char}{map};
+ $s1 =~ s/\A (.*)\n\Z/(PUSH) $1 (POP)/s;
+ $h = sprintf("%.3f", ($allchars{$id}{wd} / 10 - $dp * $slant));
+ $w = sprintf("%.3f", ($allchars{$id}{wd} * 8 / 10));
+ if ($h > 0) {
+ $s2 = " (MOVEDOWN R $dp) (MOVERIGHT R $h) ";
+ }
+ elsif ($h < 0) {
+ $h = -$h;
+ $s2 = " (MOVEDOWN R $dp) (MOVELEFT R $h) ";
+ }
+ else { $s2 .= " (MOVEDOWN R $dp) " }
+ $s3 = "(SETRULE R ${ \($thk) } R $w)";
+ $allchars{$id}{map} = " $s1\n$s2$s3\n";
+ $chars[$num] = $allchars{$id};
+ #
+ # If the character to be underscored is a digraph, fix up the LIGTABLE
+ #
+ if (grep /^$char$/, @digraphs) {
+ pop @newligs;
+ dummychar(0x035F, "uni035F") unless defined $allchars{uni035F};
+ $char =~ /^(.)(.)$/;
+ ($one, $two) = ($1, $2);
+ $one_ = $one . "_uni035F";
+ dummychar($dummycodepoint--, $one_) unless defined $allchars{$one_};
+ push @newligs, "$one: (LIG uni035F $one_)"
+ unless (grep /^$one: \(LIG uni035F $one_\)$/, @newligs);
+ push @newligs, "$one_: (LIG $two $id)";
+ }
+}
+
+sub digraph {
+ #
+ # Make a new character consisting of two existing characters
+ #
+ my ($num, $char, $acc, $id) = @_;
+ my ($one, $two, $kern, $s1, $s2, $charZWJ);
+ #
+ # Remove the ligature info -- we don't want every occurrence of
+ # e.g."kh" to be converted into a digraph.
+ #
+ pop @newligs;
+ #
+ # List all digraphs for future reference
+ #
+ push @digraphs, $id;
+ if ($ligs =~ /^ \(LABEL $char\)\n(.*?)\n \(KRN $acc R (-?[0-9.]+)\)\n/ms) {
+ ($one, $two) = ($1, $2);
+ }
+ $kern = $two if $one !~ /^ \(STOP\)$/m;
+ $allchars{$id}{wd} = $allchars{$char}{wd} + $allchars{$acc}{wd};
+ $allchars{$id}{wd} += $kern;
+ $allchars{$id}{ht} = max($allchars{$char}{ht}, $allchars{$acc}{ht});
+ $allchars{$id}{dp} = max($allchars{$char}{dp}, $allchars{$acc}{dp});
+ $allchars{$id}{ic} = $allchars{$acc}{ic};
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ $s1 = $allchars{$char}{map};
+ chomp ($s2 = $allchars{$acc}{map});
+ $s1 =~ s/(\(SETCHAR .*?\))/$1\n$s2/;
+ if ($kern) {
+ if ($kern < 0) {
+ $kern = -$kern;
+ $s1 =~ s/(\(SETCHAR .*?\))/$1 (MOVELEFT R $kern)/;
+ }
+ else { $s1 =~ s/(\(SETCHAR .*?\))/$1 (MOVERIGHT R $kern)/ }
+ }
+ $allchars{$id}{map} = $s1;
+ $chars[$num] = $allchars{$id};
+}
+
+sub dummychar {
+ #
+ # Make a new dummy character
+ #
+ my ($num, $id) = @_;
+ $allchars{$id}{wd} = 0;
+ $allchars{$id}{ht} = 0;
+ $allchars{$id}{dp} = 0;
+ $allchars{$id}{ic} = 0;
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ $allchars{$id}{map} = " (SETCHAR H 0020)\n";
+ $chars[$num] = $allchars{$id};
+}
+
+sub fixkerns {
+ #
+ # Generalise the kerning info contained in the vpl file by applying
+ # it to new accented chars. Do not kern lower-case chars bearing
+ # superscript accents with capitals, quotes or a preceding "f".
+ #
+ my ($char, $acc) = @_;
+ my ($olabel, $nlabel, @liglist, $lchar, $rchar);
+ return if $char eq "space";
+ if ($acc =~ /^$accents$/) { $lchar = $rchar = $char }
+ else {
+ $lchar = $char;
+ $rchar = $acc;
+ }
+ unless ($char =~ /^[a-z]/ and $acc =~ /^$supacc$/) {
+ $ligs =~ s[(\n \(LABEL )$rchar\)(?!\n \(LIG.*$)]
+ [$&$1$char$acc)]gm
+ unless $ligs =~ /\n \(LABEL $char$acc\)$/m;
+ $ligs =~ s[(\n \(LABEL )$rchar\)(\n \(LIG.*$)+(?!\n \(STOP\))]
+ [$&$1$char$acc)]gm
+ unless $ligs =~ /\n \(LABEL $char$acc\)$/m;
+ $ligs =~ s[(\n \(KRN )$lchar( .*)$]
+ [$&$1$char$acc$2]gm;
+ }
+ else {
+ if ($ligs =~ /\n \(LABEL $char\).*?\(STOP\)/s) {
+ $nlabel = $olabel = $&;
+ $nlabel =~ s/(\n \(LABEL $char)\)/$1$acc)/
+ unless $ligs =~ /\n \(LABEL $char$acc\)/m;
+ $nlabel =~ s/\n \(LIG .*\)$//gm;
+ $nlabel =~ s/\n \(LABEL (?!$char$acc).*\)$//gm;
+ $nlabel =~ s/\n \(KRN ([A-Z]|quote).*\)$//gm;
+ $ligs =~ s/(\n \(LABEL )$char\).*?\(STOP\)/$olabel$nlabel/s;
+ }
+ @liglist = split /\n \(STOP\)/, $ligs;
+ foreach (@liglist) {
+ unless (/\n \(LABEL ([A-Zf]|quote).*\)$/m) {
+ s/(\n \(KRN $char)( .*\))$/$&$1$acc$2/gm;
+ }
+ }
+ $ligs = join("\n (STOP)", @liglist);
+ }
+}
diff --git a/fonts/utilities/accfonts/vpl2vpl b/fonts/utilities/accfonts/vpl2vpl
new file mode 100755
index 0000000000..65ded28ce5
--- /dev/null
+++ b/fonts/utilities/accfonts/vpl2vpl
@@ -0,0 +1,994 @@
+#!/usr/bin/perl
+
+# Vpl2vpl: a program to generate accented virtual fonts for TeX
+# Copyright (C) 1997 John D. Smith
+
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+$version = 0.25;
+#------------------------------------------------------------------------#
+$description =
+"Syntax: vpl2vpl -d definition-file [-s shrink-factor]
+ [-c candrabindu-adjustment] [-b] vpl-file
+
+Vpl2vpl creates new TeX virtual fonts based on existing fonts or
+virtual fonts (\"input fonts\"). A successful run will read a pl
+(Property List) or vpl (Virtual Property List) file and a definition
+file, and will generate a new vpl (Virtual Property List) file on
+standard output. The input font is assumed to adhere to the standard
+TeX encoding for text fonts unless it was created with either of the
+programs afm2pl or afm2tfm, in which case it is assumed to conform to
+(respectively) the Adobe Standard Encoding or the encoding specified
+in the file dvips.enc. In either case, the name of the input font is
+assumed to be the name of the input file without its .vpl or .pl
+extension: it must conform to normal TeX conventions for naming fonts,
+as vpl2vpl attempts to draw conclusions from it about the kind of font
+it is dealing with.
+
+A typical complete sequence of commands to create a new virtual
+font might therefore be
+ tftopl cmr10.tfm cmr10.pl
+ vpl2vpl -d ISO-Latin1.def cmr10.pl >cmr10_isol1.vpl
+ vptovf cmr10_isol1.vpl cmr10_isol1.vf cmr10_isol1.tfm
+for a Computer Modern font, or
+ afm2pl Times-Roman.afm rptmr.pl
+ pltotf rptmr.pl rptmr.tfm
+ vpl2vpl -d ISO-Latin1.def rptmr.pl >ptmr-isol1.vpl
+ vptovf ptmr-isol1.vpl ptmr-isol1.vf ptmr-isol1.tfm
+for a PostScript font.
+
+Another approach for a PostScript font is to use afm2tfm:
+ afm2tfm Times-Roman.afm -t dvips.enc -v ptmr rptmr
+ vpl2vpl -d ISO-Latin1.def ptmr.vpl >ptmr-isol1.vpl
+ vptovf ptmr-isol1.vpl ptmr-isol1.vf ptmr-isol1.tfm
+-- but this is now deprecated, as afm2tfm generates incorrect
+values for the heights of some characters, and this can lead to
+bad accent placing.
+
+In order to keep the whole upper half of the character set free for
+the requirements of the encoding specified in the definition file,
+certain modifications are made to input fonts following the
+dvips.enc encoding to bring them into greater conformity with the
+TeX norm. In particular, the characters dotaccent and hungarumlaut
+are placed in the positions assigned by TeX (\"5F, \"7D), not those
+enforced by dvips.enc (\"C7, \"CD). The f-ligatures, double quotes
+and dashes are also moved from the upper half of the character set
+to their normal TeX positions. As a result, the following characters
+are not found in the lower half of the character set: quotesingle,
+quotedbl, backslash, underscore, braceleft, bar, braceright. These
+characters can, however, be assigned positions in the output font if
+they are needed. (Indeed, they could all be explicitly restored to
+their dvips.enc positions if this were desired.)
+
+Options:
+
+ -d should refer to a font definition file. This file (which could
+ usefully be named, e.g., \"French.def\") should consist of
+ lines of character definitions, in the form
+ \"number\" \"character\"
+ or
+ \"number\" \"character\" \"accent\"
+ Here \"number\" represents the character's position in the new
+ encoding and may be expressed in decimal, octal or hex;
+ \"character\" names the character (e.g. \"comma\", \"eight\",
+ \"A\") or consists of the word \".notdef\" (indicating that
+ the specified number's \"slot\" in the new encoding is to be
+ empty); and \"accent\" optionally names an accent to be placed
+ on the character. In addition to the standard accents available
+ in PostScript fonts, \"underbar\" and \"underdot\" are also
+ available, as are \"under\" versions of all the normal
+ superscript accents (\"underdieresis\", \"underring\", etc.).
+ The Indian accent \"candrabindu\" may also be specified: it
+ is formed by overprinting a breve with a dotaccent. Finally,
+ \"overdot\" may be used as a synonym for \"dotaccent\".
+
+ If the character named in the \"accent\" position is not in fact
+ a valid accent character, the program interprets the definition
+ as a request for a digraph formed from the \"character\" and the
+ \"accent\". A digraph consisting of, say, \"k\" and \"h\" will be
+ indistinguishable from the letters \"k\" and \"h\" printed
+ consecutively, but the digraph \"kh\" can itself receive accents
+ like any other character: see next paragraph.
+
+ A new character (such as \"amacron\" or \"kh\") may be freely
+ used in the \"character\" position of a further definition (such
+ as \"amacron breve\" or \"kh underbar\"). There is no constraint
+ on the ordering of definitions within a definition file. The
+ definition of \"a macron\" does not have to precede that of
+ \"amacron breve\": requests for \"impossible\" characters are
+ deferred until their constituents have had a chance to come into
+ being.
+
+ \"Slots\" for which no new definition is given retain the
+ definition they have in the input font.
+
+ The definition file may also contain blank lines and comments
+ (introduced by \"\#\").
+
+ -s may optionally give the factor, expressed as a per-thousand
+ value, by which normally superscript accents (such as dieresis,
+ ring) should be shrunk when they are used as subscript accents
+ (such as underdieresis, underring). Values of around 800 may be
+ found useful.
+
+ -c may optionally give two comma-separated numerical values to
+ adjust the x and y coordinates of the dotaccent placed within a
+ breve to form the candrabindu accent. A coordinate scheme using
+ \"DESIGNUNITS R 1000\" is assumed.
+
+ -b may optionally be specified to block the use of predefined
+ accented characters, forcing vpl2vpl to define its own
+ versions. This may be useful to secure a consistent appearance
+ in cases where a font designer does not share vpl2vpl's views
+ on where accents should be placed.
+
+ -h prints this help.
+";
+#------------------------------------------------------------------------#
+
+########################
+# Packages and constants
+########################
+#
+use File::Basename;
+use Getopt::Std;
+$cmdline = basename($0) . " " . join " ", @ARGV;
+getopts('d:s:c:bh');
+if ($opt_h or !$opt_d or $#ARGV != 0) {
+ print STDERR $description;
+ exit 1;
+}
+
+$filename = $ARGV[0];
+($fontname = $filename) =~ s/\..*$//;
+($encname = basename($opt_d)) =~ s/\..*$//;
+$vtitle = "(VTITLE Font $fontname modified for $encname encoding by vpl2vpl";
+$vtitle .= " v. $version" if $version;
+$vtitle .= ")\n(COMMENT Command line: $cmdline)";
+
+#
+# Flags for bold and small caps. These are probably a bit iffy, but
+# there's not much that can be done about it.
+#
+if ($fontname =~ /(^p.*b[oi]?[c]?$|^[^p].*bx[a-z]*[0-9]+$)/) { $bold = 1 }
+if ($fontname =~ /(^p.*c$|^[^p].*csc[a-z]*[0-9]+$)/) { $scaps = 1 }
+if ($opt_s) { $shrink = $opt_s / 1000 } else { $shrink = 1 }
+
+#
+# Array to convert from number to vpl representation
+#
+foreach $i (0 .. 255) {
+ $nv[$i] = (chr($i) =~ /[0-9A-Za-z]/ ? "C " . chr $i : sprintf("O %lo", $i));
+}
+
+#
+# Now the encoding vectors.
+#
+@TeXenc = (
+ "Gamma", "Delta", "Theta", "Lambda",
+ "Xi", "Pi", "Sigma", "Upsilon",
+ "Phi", "Psi", "Omega", "ff",
+ "fi", "fl", "ffi", "ffl",
+ "dotlessi", "dotlessj", "grave", "acute",
+ "caron", "breve", "macron", "ring",
+ "cedilla", "germandbls", "ae", "oe",
+ "oslash", "AE", "OE", "Oslash",
+ "space", "exclam", "quotedblright", "numbersign",
+ "dollar", "percent", "ampersand", "quoteright",
+ "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash",
+ "zero", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine", "colon", "semicolon",
+ "exclamdown", "equal", "questiondown", "question",
+ "at", "A", "B", "C",
+ "D", "E", "F", "G",
+ "H", "I", "J", "K",
+ "L", "M", "N", "O",
+ "P", "Q", "R", "S",
+ "T", "U", "V", "W",
+ "X", "Y", "Z", "bracketleft",
+ "quotedblleft", "bracketright", "circumflex", "dotaccent",
+ "quoteleft", "a", "b", "c",
+ "d", "e", "f", "g",
+ "h", "i", "j", "k",
+ "l", "m", "n", "o",
+ "p", "q", "r", "s",
+ "t", "u", "v", "w",
+ "x", "y", "z", "endash",
+ "emdash", "hungarumlaut", "tilde", "dieresis"
+);
+
+@dvipsenc = (
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", "quotesingle", "exclamdown", "questiondown",
+ "dotlessi", "dotlessj", "grave", "acute",
+ "caron", "breve", "macron", "ring",
+ "cedilla", "germandbls", "ae", "oe",
+ "oslash", "AE", "OE", "Oslash",
+ "space", "exclam", "quotedbl", "numbersign",
+ "dollar", "percent", "ampersand", "quoteright",
+ "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash",
+ "zero", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine", "colon", "semicolon",
+ "less", "equal", "greater", "question",
+ "at", "A", "B", "C",
+ "D", "E", "F", "G",
+ "H", "I", "J", "K",
+ "L", "M", "N", "O",
+ "P", "Q", "R", "S",
+ "T", "U", "V", "W",
+ "X", "Y", "Z", "bracketleft",
+ "backslash", "bracketright", "circumflex", "underscore",
+ "quoteleft", "a", "b", "c",
+ "d", "e", "f", "g",
+ "h", "i", "j", "k",
+ "l", "m", "n", "o",
+ "p", "q", "r", "s",
+ "t", "u", "v", "w",
+ "x", "y", "z", "braceleft",
+ "bar", "braceright", "tilde", "dieresis",
+ "asciicircum", "asciitilde", "Ccedilla", "Iacute",
+ "Icircumflex", "atilde", "edieresis", "egrave",
+ "scaron", "zcaron", "Eth", "ff",
+ "ffi", "ffl", ".notdef", ".notdef",
+ ".notdef", ".notdef", "Scaron", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ "Ydieresis", ".notdef", "Zcaron", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", "cent", "sterling",
+ "fraction", "yen", "florin", "section",
+ "currency", "copyright", "quotedblleft", "guillemotleft",
+ "guilsinglleft", "guilsinglright", "fi", "fl",
+ "degree", "endash", "dagger", "daggerdbl",
+ "periodcentered", ".notdef", "paragraph", "bullet",
+ "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
+ "ellipsis", "perthousand", ".notdef", ".notdef",
+ "Agrave", "Aacute", "Acircumflex", "Atilde",
+ "Adieresis", "Aring", ".notdef", "dotaccent",
+ "Egrave", "Eacute", "Ecircumflex", "Edieresis",
+ "Igrave", "hungarumlaut", "ogonek", "Idieresis",
+ "emdash", "Ntilde", "Ograve", "Oacute",
+ "Ocircumflex", "Otilde", "Odieresis", ".notdef",
+ ".notdef", "Ugrave", "Uacute", "Ucircumflex",
+ "Udieresis", "Yacute", "Thorn", ".notdef",
+ "agrave", "aacute", "acircumflex", "ordfeminine",
+ "adieresis", "aring", ".notdef", "ccedilla",
+ "Lslash", "eacute", "ecircumflex", "ordmasculine",
+ "igrave", "iacute", "icircumflex", "idieresis",
+ ".notdef", "ntilde", "ograve", "oacute",
+ "ocircumflex", "otilde", "odieresis", ".notdef",
+ "lslash", "ugrave", "uacute", "ucircumflex",
+ "udieresis", "yacute", "thorn", "ydieresis"
+);
+
+@adobeenc=(
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ "space", "exclam", "quotedbl", "numbersign",
+ "dollar", "percent", "ampersand", "quoteright",
+ "parenleft", "parenright", "asterisk", "plus",
+ "comma", "hyphen", "period", "slash",
+ "zero", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine", "colon", "semicolon",
+ "less", "equal", "greater", "question",
+ "at", "A", "B", "C",
+ "D", "E", "F", "G",
+ "H", "I", "J", "K",
+ "L", "M", "N", "O",
+ "P", "Q", "R", "S",
+ "T", "U", "V", "W",
+ "X", "Y", "Z", "bracketleft",
+ "backslash", "bracketright", "asciicircum", "underscore",
+ "quoteleft", "a", "b", "c",
+ "d", "e", "f", "g",
+ "h", "i", "j", "k",
+ "l", "m", "n", "o",
+ "p", "q", "r", "s",
+ "t", "u", "v", "w",
+ "x", "y", "z", "braceleft",
+ "bar", "braceright", "asciitilde", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", "exclamdown", "cent", "sterling",
+ "fraction", "yen", "florin", "section",
+ "currency", "quotesingle", "quotedblleft", "guillemotleft",
+ "guilsinglleft", "guilsinglright", "fi", "fl",
+ ".notdef", "endash", "dagger", "daggerdbl",
+ "periodcentered", ".notdef", "paragraph", "bullet",
+ "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
+ "ellipsis", "perthousand", ".notdef", "questiondown",
+ ".notdef", "grave", "acute", "circumflex",
+ "tilde", "macron", "breve", "dotaccent",
+ "dieresis", ".notdef", "ring", "cedilla",
+ ".notdef", "hungarumlaut", "ogonek", "caron",
+ "emdash", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", "AE", ".notdef", "ordfeminine",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ "Lslash", "Oslash", "OE", "ordmasculine",
+ ".notdef", ".notdef", ".notdef", ".notdef",
+ ".notdef", "ae", ".notdef", ".notdef",
+ ".notdef", "dotlessi", ".notdef", ".notdef",
+ "lslash", "oslash", "oe", "germandbls",
+ ".notdef", ".notdef", ".notdef", ".notdef"
+);
+
+###############
+# Read DEF file
+###############
+#
+open DEF, $opt_d or die "Cannot open $opt_d: $!\n";
+while (<DEF>) {
+ next if (/^\s*$/ || /^\#/);
+ s/\s*(\#.*)?$//;
+ push @deflines, $_;
+}
+close DEF;
+
+###############
+# Read VPL file
+###############
+#
+# File header
+#
+$vplhead = <> or exit 1;
+unless ($vplhead =~ /^\((VTITLE|FAMILY) /) {
+ die "$filename is not a vpl file: giving up\n"
+}
+do {
+ $_ = <>;
+ $vplhead .= $_;
+} until ($_ =~ /^\(LIGTABLE$/ or eof);
+if (eof) {
+ die "$filename does not seem to be a text font (no LIGTABLE): giving up\n";
+}
+if ($vplhead =~ s/\A\(VTITLE(.*)$/$vtitle\n(COMMENT Old vtitle:$1/m) {
+ $vplhead =~ s/\n\(COMMENT Please edit that VTITLE .*\)$//m;
+ @enc = @dvipsenc;
+ $dvips = 1;
+}
+elsif ($vplhead =~ /\A\(FAMILY.*\)\n\(CODINGSCHEME ADOBESTANDARDENCODING\)$/m) {
+ $vplhead =~ s/\A/$vtitle\n/m;
+ @enc = @adobeenc;
+ $dvips = 0;
+}
+else {
+ $vplhead =~ s/\A/$vtitle\n/m;
+ @enc = @TeXenc;
+ $dvips = 0;
+}
+if ($vplhead =~ /^\(CODINGSCHEME TEX MATH SYMBOLS/m) {
+ die "$filename is a TeX math font: giving up\n";
+}
+unless ($vplhead =~ s/^(\(CODINGSCHEME .*\+\s?)(\S+)\)$/$1$encname)/m) {
+ $vplhead =~ s/^(\(CODINGSCHEME .*)\)$/$1 + $encname)/m;
+}
+if ($vplhead =~ /^\(DESIGNUNITS R (.+)\)/m) { $scale = $1 }
+else {$scale = 1 }
+if ($vplhead =~ /^ \(SLANT R (.+)\)/m) { $slant = $1 }
+if ($vplhead =~ /^ \(XHEIGHT [DR] (.+)\)/m) { $xheight = $1 }
+unless ($vplhead =~ /^\(MAPFONT /m) {
+ if ($vplhead =~ /^\(DESIGNSIZE R (.*)\)$/m) { $dsize = $1 }
+ $mapfont = "\n(MAPFONT D 0\n (FONTNAME $fontname)\n (FONTDSIZE R $dsize)\n )";
+ $vplhead =~ s/\n\(LIGTABLE\Z/$mapfont$&/m;
+}
+if ($opt_s) {
+ $vplhead =~ s[^(\(MAPFONT D )0(.*?)( \))]
+ [$&\n${1}1$2 (FONTAT R ${ \($shrink * $scale) })\n$3]ms;
+}
+
+#
+# Ligatures and kerns
+#
+do {
+ $_ = <>;
+ s/ \(comment .*$//i;
+ $ligs .= $_;
+} until $_ =~ /^ \)/;
+#
+# Now build a hash to convert from vpl representation to char name
+# and use it to make ligtable readable
+#
+foreach $i (0 .. 255) { $vc{$nv[$i]} = $enc[$i] }
+$ligs =~ s/^( \((?:LABEL|KRN) )(\S+ \S+)(.*\))$/$1$vc{$2}$3/gm;
+$ligs =~ s/^( \(LIG )(\S+ \S+) (\S+ \S+)\)$/$1$vc{$2} $vc{$3})/gm;
+
+#
+# Character definitions: store "encoded" defs in @chars, store *all*
+# defs in %allchars
+#
+$_ = <>;
+do {
+ if (/^\(CHARACTER/) {
+ $character = $_;
+ do {
+ $_ = <>;
+ $character .= $_;
+ } until $_ =~ /^ \)/;
+ storeinfo($character);
+ $_ = <>;
+ }
+} until eof;
+foreach $i (0 .. $#chars) {
+ if ($chars[$i] and $enc[$i] ne ".notdef") {
+ $allchars{$enc[$i]} = $chars[$i];
+ }
+}
+
+##################
+# Set up constants
+##################
+
+$subacc = "(cedilla|ogonek|commaaccent)";
+$supacc = "(grave|acute|circumflex|tilde|macron|breve|dotaccent|overdot|dieresis|ring|hungarumlaut|caron|candrabindu)";
+$underacc = "(underdot|under$supacc)";
+$accents = "($subacc|$supacc|$underacc|underbar)";
+$underadp = 0.230; # depth of "under" accs
+$underddp = 0.213; # depth of underdot
+if ($bold) { $thk = 0.072 } else { $thk = 0.052 } # thickness and
+$underbdp = 0.082 + $thk; # depth of underbar
+$capheight = $allchars{"X"}{ht};
+$accheight = $allchars{"macron"}{ht};
+$accdepth = $accheight - $thk * $scale; # probable approx. "depth" of macron
+$v1 = $accheight - $xheight; # vertical offset for double accents
+$v2 = $capheight - $xheight; # vertical offset for accented caps etc
+if ($scaps) { # accented small caps
+ $scoffset = $allchars{"x"}{ht} - $xheight;
+ $v1 += $scoffset;
+}
+if ($opt_c) { # candrabindu
+ ($cbx, $cby) = $opt_c =~ /^(.*),(.*)$/;
+ $cbx += ($allchars{"breve"}{wd} - $allchars{"dotaccent"}{wd}) / 2;
+ $cbx /= 1000;
+ $cby /= 1000;
+}
+
+######################
+# Build the characters
+######################
+#
+# First normalise dvips.enc encoding quirks
+#
+if ($dvips) {
+ chmove("fi", 014);
+ chmove("fl", 015);
+ chmove("quotedblright", 042);
+ chmove("quotedblleft", 0134);
+ chmove("dotaccent", 0137);
+ chmove("endash", 0173);
+ chmove("emdash", 0174);
+ chmove("hungarumlaut", 0175);
+}
+#
+# Now build a list of definitions supplied by user
+#
+for (@deflines) {
+ if (/^\s*(\d+|0[0-7]+|0x[0-9a-fA-F]+)\s+([a-zA-Z]+?|\.notdef)(?:\s+([a-zA-Z]+))?$/) {
+ ($num, $char, $acc) = ($1, $2, $3);
+ $num = oct $num if $num =~ /^0/;
+ if ($num > 255) { die "Bad definition (number out of range): $_\n" }
+ $def = {};
+ $def->{qdef} = $_;
+ $def->{num} = $num;
+ $def->{char} = $char;
+ $def->{acc} = $acc;
+ $def->{nchar} = $char . $acc;
+ push @nchars, $def->{nchar};
+ push @defs, $def;
+ }
+ else { die "Bad definition: $_\n" }
+}
+#
+# Work through the list
+#
+while (@defs) {
+ $def = shift @defs;
+ $qdef = $def->{qdef};
+ $num = $def->{num};
+ $char = $def->{char};
+ $acc = $def->{acc};
+ $nchar = $def->{nchar};
+ #
+ # If we can't handle $char/$acc yet, but believe we will be able
+ # to later, send the definition to the back of the queue. In case
+ # it later turns out we were wrong, allow only five loops before
+ # giving up.
+ #
+ if (!$allchars{$char} and $char ne ".notdef") {
+ if (grep /^$char$/, @nchars) {
+ unless (++$def->{requeue} > 5) {
+ push @defs, $def;
+ next;
+ }
+ }
+ else { die "Bad definition (no such character): $qdef\n" }
+ }
+ if ($acc and !$allchars{$acc} and $acc !~ /^$accents$/) {
+ if (grep /^$acc$/, @nchars) {
+ unless (++$def->{requeue} > 5) {
+ push @defs, $def;
+ next;
+ }
+ }
+ else { die "Bad definition (no such accent): $qdef\n" }
+ }
+ #
+ # Remove any existing claims on $num
+ #
+ @{ $allchars{$chars[$num]{id}}{num} } = grep !/$num/,
+ @{ $allchars{$chars[$num]{id}}{num} };
+ #
+ # First deal with .notdef
+ #
+ if ($nchar eq ".notdef") {
+ undef $chars[$num];
+ }
+ #
+ # Next look among existing chars (unless blocked by -b)
+ #
+ elsif (!($acc and $opt_b) and $allchars{$nchar}) {
+ push( @{ $allchars{$nchar}{num} }, $num);
+ $chars[$num] = $allchars{$nchar};
+ }
+ #
+ # If it can't be built from sub-elements, issue a warning and move on
+ #
+ elsif (!$acc) {
+ warn "No such character - ignoring definition: $qdef\n";
+ undef $chars[$num];
+ }
+ #
+ # Now build the char
+ #
+ else {
+ #
+ # First get rid of predefined/duplicated ligtable statements
+ # and character definitions; also synonyms
+ #
+ $ligs =~ s/\n \((LABEL|KRN|LIG) ($nchar .*|.*$nchar)\)$//gm;
+ $allchars{$nchar} = ();
+ if ($acc eq "overdot") {
+ $nchar2 = $char . "dotaccent";
+ $ligs =~ s/\n \((LABEL|KRN|LIG) ($nchar2 .*|.*$nchar2)\)$//gm;
+ delete $allchars{$nchar2};
+ }
+ #
+ # Go!
+ #
+ if ($acc =~ /^$subacc$/) {
+ subacc($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ elsif ($acc =~ /^$supacc$/) {
+ supacc($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ elsif ($acc =~ /^$underacc$/) {
+ underacc($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ elsif ($acc =~ /^underbar$/) {
+ underb($num, $char, $nchar);
+ fixkerns($char, $acc);
+ }
+ else {
+ digraph($num, $char, $acc, $nchar);
+ fixkerns($char, $acc);
+ }
+ }
+}
+
+###################
+# Sort out ligtable
+###################
+#
+# Convert to vpl representation, eliminating statements invoking
+# "unencoded" characters
+#
+@liglist = split /\n/, $ligs;
+$ligs = "";
+foreach (@liglist) {
+ if (/^( \(LIG \S+ )(\S+)\)$/) {
+ if ($n = ${ $allchars{$2}{num} }[0]) {
+ s/^( \(LIG \S+ )(\S+)\)$/$1$nv[$n])/;
+ }
+ else { next }
+ }
+ if (/^( \((?:LABEL|LIG|KRN) )([^ )]+)(.*)$/) {
+ ($one, $two, $three) = ($1, $2, $3);
+ foreach $n (@{ $allchars{$two}{num} }) {
+ $ligs .= "$one$nv[$n]$three\n";
+ }
+ }
+ else { $ligs .= "$_\n" }
+}
+#
+# Eliminate sequences orphaned by elimination of a LABEL
+#
+@liglist = split / \(STOP\)\n/, $ligs;
+$ligs = "";
+foreach (@liglist) {
+ if (/^ \(LABEL /m) { $ligs .= "$_ (STOP)\n" }
+ elsif (/^ \)$/m) { $ligs .= $_ }
+}
+#
+# Eliminate empty statements
+#
+$ligs =~ s/(^ \(LABEL .*\)\n)+ \(STOP\)\n//gm;
+
+####################
+# Output the results
+####################
+#
+print $vplhead, $ligs;
+foreach $i (0 .. 255) { if (defined $chars[$i]{id}) { printchar($i) } }
+
+#####################
+# End of main program
+#####################
+
+sub storeinfo {
+ #
+ # Extract info from a character definition and store it in @chars
+ #
+ my $char = shift;
+ my $num;
+ if ($char =~ /\A\(CHARACTER O ([0-7]+)/m) { $num = oct $1 }
+ elsif ($char =~ /\A\(CHARACTER C (.)/m) { $num = ord $1 }
+ $chars[$num]{id} = $enc[$num];
+ push( @{ $chars[$num]{num} }, $num);
+ if ($char =~ /^ \(CHARWD R (.*?)\)$/m) { $chars[$num]{wd} = $1 }
+ if ($char =~ /^ \(CHARHT R (.*?)\)$/m) { $chars[$num]{ht} = $1 }
+ if ($char =~ /^ \(CHARDP R (.*?)\)$/m) { $chars[$num]{dp} = $1 }
+ if ($char =~ /^ \(CHARIC R (.*?)\)$/m) { $chars[$num]{ic} = $1 }
+ if ($char =~ /^ \(MAP\n((.|\n)*)^ \)/m) { $chars[$num]{map} = $1 }
+ else { $chars[$num]{map} = " (SETCHAR $nv[$num])\n" }
+}
+
+sub printchar {
+ #
+ # Extract info from @chars and build it into a character definition
+ #
+ my $num = shift;
+ print "(CHARACTER ";
+ if (chr($num) =~ /[0-9A-Za-z]/) { print "C " . chr($num) }
+ else {
+ printf "O %lo", $num;
+ print " (COMMENT " . $chars[$num]{id} . ")";
+ }
+ print "\n";
+ print " (CHARWD R " . $chars[$num]{wd} . ")\n" if $chars[$num]{wd};
+ print " (CHARHT R " . $chars[$num]{ht} . ")\n" if $chars[$num]{ht};
+ print " (CHARDP R " . $chars[$num]{dp} . ")\n" if $chars[$num]{dp};
+ print " (CHARIC R " . $chars[$num]{ic} . ")\n" if $chars[$num]{ic};
+ print " (MAP\n";
+ print $chars[$num]{map};
+ print " )\n";
+ print " )\n";
+}
+
+sub chmove {
+ #
+ # Move a character
+ #
+ my ($char, $num) = @_;
+ my $i;
+ foreach $i (@{ $allchars{$char}{num} }) { undef $chars[$i] }
+ @{ $allchars{$char}{num} } = ();
+ @{ $allchars{$chars[$num]{id}}{num} } = grep !/$num/,
+ @{ $allchars{$chars[$num]{id}}{num} };
+ push( @{ $allchars{$char}{num} }, $num);
+ $chars[$num] = $allchars{$char};
+}
+
+sub max {
+ #
+ # Return greater of two values
+ #
+ my ($a, $b) = @_;
+ return $a > $b ? $a : $b;
+}
+
+sub subacc {
+ #
+ # Subscript accents
+ #
+ my ($num, $char, $acc, $id) = @_;
+ my ($h, $s1, $s2, $s3);
+ $allchars{$id}{wd} = $allchars{$char}{wd};
+ $allchars{$id}{ht} = $allchars{$char}{ht};
+ $allchars{$id}{dp} = $allchars{$acc}{dp};
+ $allchars{$id}{ic} = $allchars{$char}{ic};
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ $s1 = $allchars{$char}{map};
+ $s1 =~ s/\A (.*)\n\Z/(PUSH) $1 (POP)/s;
+ $h = sprintf("%.3f", ($allchars{$char}{wd} - $allchars{$acc}{wd}) / 2);
+ if ($h > 0) { $s2 = " (MOVERIGHT R $h) " }
+ elsif ($h < 0) {
+ $h = -$h;
+ $s2 = " (MOVELEFT R $h) ";
+ }
+ else { $s2 = " " }
+ $s3 = $allchars{$acc}{map};
+ $s3 =~ s/\A.*(\(SETCHAR . .+?\)).*\Z/$1/s;
+ $allchars{$id}{map} = " $s1\n$s2$s3\n";
+ $chars[$num] = $allchars{$id};
+}
+
+sub supacc {
+ #
+ # Superscript accents
+ #
+ my ($num, $char, $acc, $id) = @_;
+ my ($cb, $h, $hadj, $tallchar, $ic, $s1, $s2, $s3);
+ if ($char eq "i" and $allchars{"dotlessi"}) { $char = "dotlessi" }
+ if ($char eq "j" and $allchars{"dotlessj"}) { $char = "dotlessj" }
+ if ($acc eq "overdot") { $acc = "dotaccent" }
+ if ($acc eq "candrabindu") {
+ $acc = "breve";
+ ($cb = $allchars{"dotaccent"}{map}) =~ s/\A.*(\(SETCHAR . .+?\)).*\Z/$1/s;
+ }
+ $allchars{$id}{wd} = $allchars{$char}{wd};
+ $allchars{$id}{ht} = $allchars{$acc}{ht};
+ $allchars{$id}{dp} = $allchars{$char}{dp};
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ $s1 = $allchars{$char}{map};
+ $s1 =~ s/\A (.*)\n\Z/(PUSH) $1 (POP)/s;
+ if ($scaps and $char =~ /^[a-z]/) { # accented small caps
+ $tallchar = 1;
+ if ($char =~ /$supacc$/
+ and $char !~ /under$supacc$/) { # double accs
+ $s2 = " (MOVEUP R $v1)";
+ $allchars{$id}{ht} += $v1;
+ $hadj = sprintf("%.3f", $v1 * $slant);
+ $ic = $allchars{$char}{ic};
+ }
+ else { # single accs
+ $s2 = " (MOVEUP R $scoffset)";
+ $allchars{$id}{ht} += $scoffset;
+ $hadj = sprintf("%.3f", $scoffset * $slant);
+ $ic = $allchars{$acc}{ic} + $hadj;
+ }
+ }
+ elsif ($allchars{$char}{ht} >= ($accheight + $v2)) { # double accs
+ $tallchar = 1; # on caps etc.
+ $s2 = " (MOVEUP R ${ \($v1 + $v2) })";
+ $allchars{$id}{ht} += ($v1 + $v2);
+ $hadj = sprintf("%.3f", ($v1 + $v2) * $slant);
+ $ic = $allchars{$char}{ic};
+ }
+ elsif ($allchars{$char}{ht} > 1.15 * $xheight) {
+ $tallchar = 1;
+ if ($char =~ /$supacc$/
+ and $char !~ /under$supacc$/) { # double accs
+ $s2 = " (MOVEUP R $v1)";
+ $allchars{$id}{ht} += $v1;
+ $hadj = sprintf("%.3f", $v1 * $slant);
+ $ic = $allchars{$char}{ic};
+ }
+ else { # caps etc.
+ $s2 = " (MOVEUP R $v2)";
+ $allchars{$id}{ht} += $v2;
+ $hadj = sprintf("%.3f", $v2 * $slant);
+ $ic = $allchars{$char}{ic};
+ }
+ }
+ else { # single accs
+ $s2 = " ";
+ $ic = $allchars{$acc}{ic};
+ }
+ $h = sprintf("%.3f", ($allchars{$char}{wd} - $allchars{$acc}{wd}) / 2);
+ unless ($tallchar) { $ic -= $h }
+ $allchars{$id}{ic} = $ic unless $ic < 0;
+ $h += $hadj;
+ if ($h > 0) { $s2 .= " (MOVERIGHT R $h) " }
+ elsif ($h < 0) {
+ $h = -$h;
+ $s2 .= " (MOVELEFT R $h) ";
+ }
+ else { $s2 .= " " }
+ $s3 = $allchars{$acc}{map};
+ $s3 =~ s/\A.*(\(SETCHAR . .+?\)).*\Z/$1/s;
+ if ($cb) { # candrabindu
+ $cb = $s2 . $cb;
+ if ($cbx) {
+ unless (($cb =~ s/(MOVERIGHT R )([0-9.]+)/$1 . ($2 + $cbx * $scale)/e)
+ or ($cb =~ s/(MOVELEFT R )([0-9.]+)/$1 . ($2 - $cbx * $scale)/e)) {
+ $cb =~ s/^( +)/"$1(MOVERIGHT R " . ($cbx * $scale) . ") "/e;
+ }
+ }
+ if ($cby) {
+ unless ($cb =~ s/(MOVEUP R )([0-9.]+)/$1 . ($2 + $cby * $scale)/e) {
+ $cb =~ s/^( +)/"$1(MOVEUP R " . ($cby * $scale) . ") "/e;
+ }
+ }
+ $cb .= "\n";
+ $s1 = "(PUSH) " . $s1;
+ $s3 .= " (POP)";
+ }
+ $allchars{$id}{map} = " $s1\n$s2$s3\n$cb";
+ $chars[$num] = $allchars{$id};
+}
+
+sub underacc {
+ #
+ # Dropped accents
+ #
+ my ($num, $char, $acc, $id) = @_;
+ my ($h, $v, $s1, $s2, $s3);
+ $acc =~ s/^under//;
+ if ($acc eq "dot") { $acc = "period" }
+ if ($acc eq "candrabindu") { die "Bad definition (no such accent): $qdef\n" }
+ $allchars{$id}{wd} = $allchars{$char}{wd};
+ $allchars{$id}{ht} = $allchars{$char}{ht};
+ $allchars{$id}{ic} = $allchars{$char}{ic};
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ if ($acc =~ /^$supacc$/) {
+ $v = $allchars{$id}{dp} = $underadp * $scale * $shrink;
+ $v += ($accdepth * $shrink);
+ }
+ else {
+ $v = $allchars{$id}{dp} = $underddp * $scale + $allchars{$acc}{dp};
+ }
+ $s1 = $allchars{$char}{map};
+ $s1 =~ s/\A (.*)\n\Z/(PUSH) $1 (POP)/s;
+ if ($acc =~ /^$supacc$/) {
+ $h = ($allchars{$char}{wd} - ($allchars{$acc}{wd} * $shrink)) / 2 - $v * $slant;
+ if ($opt_s) { $s2 = " (SELECTFONT D 1)\n" }
+ }
+ else {
+ $h = ($allchars{$char}{wd} - $allchars{$acc}{wd}) / 2 - $v * $slant;
+ }
+ $h = sprintf("%.3f", $h);
+ if ($h > 0) {
+ $s2 .= " (MOVEDOWN R $v) (MOVERIGHT R $h) ";
+ }
+ elsif ($h < 0) {
+ $h = -$h;
+ $s2 .= " (MOVEDOWN R $v) (MOVELEFT R $h) ";
+ }
+ else { $s2 = " (MOVEDOWN R $v) " }
+ $s3 = $allchars{$acc}{map};
+ $s3 =~ s/\A.*(\(SETCHAR . .+?\)).*\Z/$1/s;
+ if ($opt_s and $acc =~ /^$supacc$/) { $s3 .= "\n (SELECTFONT D 0)" }
+ $allchars{$id}{map} = " $s1\n$s2$s3\n";
+ $chars[$num] = $allchars{$id};
+}
+
+sub underb {
+ #
+ # Underbar
+ #
+ my ($num, $char, $id) = @_;
+ my ($h, $w, $dp, $s1, $s2, $s3);
+ $allchars{$id}{wd} = $allchars{$char}{wd};
+ $allchars{$id}{ht} = $allchars{$char}{ht};
+ $allchars{$id}{dp} = $dp = $underbdp * $scale;
+ $allchars{$id}{ic} = $allchars{$char}{ic};
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ $s1 = $allchars{$char}{map};
+ $s1 =~ s/\A (.*)\n\Z/(PUSH) $1 (POP)/s;
+ $h = sprintf("%.3f", ($allchars{$id}{wd} / 10 - $dp * $slant));
+ $w = sprintf("%.3f", ($allchars{$id}{wd} * 8 / 10));
+ if ($h > 0) {
+ $s2 = " (MOVEDOWN R $dp) (MOVERIGHT R $h) ";
+ }
+ elsif ($h < 0) {
+ $h = -$h;
+ $s2 = " (MOVEDOWN R $dp) (MOVELEFT R $h) ";
+ }
+ else { $s2 .= " (MOVEDOWN R $dp) " }
+ $s3 = "(SETRULE R ${ \($thk * $scale) } R $w)";
+ $allchars{$id}{map} = " $s1\n$s2$s3\n";
+ $chars[$num] = $allchars{$id};
+}
+
+sub digraph {
+ #
+ # Make a new character consisting of two existing characters
+ #
+ my ($num, $char, $acc, $id) = @_;
+ my ($one, $two, $kern, $s1, $s2);
+ if ($ligs =~ /^ \(LABEL $char\)\n(.*?)\n \(KRN $acc R (-?[0-9.]+)\)\n/ms) {
+ ($one, $two) = ($1, $2);
+ }
+ $kern = $two if $one !~ /^ \(STOP\)$/m;
+ $allchars{$id}{wd} = $allchars{$char}{wd} + $allchars{$acc}{wd};
+ $allchars{$id}{wd} += $kern;
+ $allchars{$id}{ht} = max($allchars{$char}{ht}, $allchars{$acc}{ht});
+ $allchars{$id}{dp} = max($allchars{$char}{dp}, $allchars{$acc}{dp});
+ $allchars{$id}{ic} = $allchars{$acc}{ic};
+ $allchars{$id}{id} = $id;
+ push( @{ $allchars{$id}{num} }, $num);
+ $s1 = $allchars{$char}{map};
+ chomp ($s2 = $allchars{$acc}{map});
+ $s1 =~ s/(\(SETCHAR .*?\))/$1\n$s2/;
+ if ($kern) {
+ if ($kern < 0) {
+ $kern = -$kern;
+ $s1 =~ s/(\(SETCHAR .*?\))/$1 (MOVELEFT R $kern)/;
+ }
+ else { $s1 =~ s/(\(SETCHAR .*?\))/$1 (MOVERIGHT R $kern)/ }
+ }
+ $allchars{$id}{map} = $s1;
+ $chars[$num] = $allchars{$id};
+}
+
+sub fixkerns {
+ #
+ # Generalise the kerning info contained in the vpl file by applying
+ # it to new accented chars. Do not kern lower-case chars bearing
+ # superscript accents with capitals, quotes or a preceding "f".
+ #
+ my ($char, $acc) = @_;
+ my ($olabel, $nlabel, @liglist, $lchar, $rchar);
+ if ($acc =~ /^$accents$/) { $lchar = $rchar = $char }
+ else {
+ $lchar = $char;
+ $rchar = $acc;
+ }
+ unless ($char =~ /^[a-z]/ and $acc =~ /^$supacc$/) {
+ $ligs =~ s[(\n \(LABEL )$rchar\)(?!\n \(LIG.*$)]
+ [$&$1$char$acc)]gm
+ unless $ligs =~ /\n \(LABEL $char$acc\)$/m;
+ $ligs =~ s[(\n \(LABEL )$rchar\)(\n \(LIG.*$)+(?!\n \(STOP\))]
+ [$&$1$char$acc)]gm
+ unless $ligs =~ /\n \(LABEL $char$acc\)$/m;
+ $ligs =~ s[(\n \(KRN )$lchar( .*)$]
+ [$&$1$char$acc$2]gm;
+ }
+ else {
+ if ($ligs =~ /\n \(LABEL $char\).*?\(STOP\)/s) {
+ $nlabel = $olabel = $&;
+ $nlabel =~ s/(\n \(LABEL $char)\)/$1$acc)/
+ unless $ligs =~ /\n \(LABEL $char$acc\)/m;
+ $nlabel =~ s/\n \(LIG .*\)$//gm;
+ $nlabel =~ s/\n \(LABEL (?!$char$acc).*\)$//gm;
+ $nlabel =~ s/\n \(KRN ([A-Z]|quote).*\)$//gm;
+ $ligs =~ s/(\n \(LABEL )$char\).*?\(STOP\)/$olabel$nlabel/s;
+ }
+ @liglist = split /\n \(STOP\)/, $ligs;
+ foreach (@liglist) {
+ unless (/\n \(LABEL ([A-Zf]|quote).*\)$/m) {
+ s/(\n \(KRN $char)( .*\))$/$&$1$acc$2/gm;
+ }
+ }
+ $ligs = join("\n (STOP)", @liglist);
+ }
+}