From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- support/mf2pt1/ChangeLog | 420 +++++++++++++++++ support/mf2pt1/README | 40 ++ support/mf2pt1/mf2pt1.mp | 495 ++++++++++++++++++++ support/mf2pt1/mf2pt1.pdf | Bin 0 -> 229650 bytes support/mf2pt1/mf2pt1.pl | 1090 ++++++++++++++++++++++++++++++++++++++++++++ support/mf2pt1/mf2pt1.texi | 977 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 3022 insertions(+) create mode 100644 support/mf2pt1/ChangeLog create mode 100644 support/mf2pt1/README create mode 100644 support/mf2pt1/mf2pt1.mp create mode 100644 support/mf2pt1/mf2pt1.pdf create mode 100755 support/mf2pt1/mf2pt1.pl create mode 100644 support/mf2pt1/mf2pt1.texi (limited to 'support/mf2pt1') diff --git a/support/mf2pt1/ChangeLog b/support/mf2pt1/ChangeLog new file mode 100644 index 0000000000..57b9ec2b0d --- /dev/null +++ b/support/mf2pt1/ChangeLog @@ -0,0 +1,420 @@ +2014-04-30 Scott Pakin + + * mf2pt1.texi + Updated the formatting to work with Makeinfo 5. + + * mf2pt1.texi, mf2pt1.pl + Updated the version number to 2.5a and the copyright year to 2014. + +2014-04-30 Karl Berry + + * mf2pt1.texi + Standardized the dir entry. + +2012-06-29 Scott Pakin + + * mf2pt1.texi, mf2pt1.pl + Increased the version number from 2.4.6 to 2.5. Updated the + Acknowledgments section. + +2012-06-29 Michael Ummels + + * mf2pt1.mp: + Made the to_bp function round to nearest rather than round up. + +2012-06-29 Michael Ummels + + * mf2pt1.pl: + Changed the computation of character widths to use TeX points + instead of PostScript points. + +2012-03-24 Scott Pakin + + * README, mf2pt1.pl, mf2pt1.texi, mf2pt1.mp: + Updated the copyright date from 2011 to 2012 and increased the + version number from 2.4.5 to 2.4.6. + +2012-03-24 Werner Lemberg + + * mf2pt1.pl: + Modified the code to pass "nonstopmode" to the Metafont + invocation. + +2011-08-02 Scott Pakin + + * README, mf2pt1.pl, mf2pt1.texi: + Updated the copyright date from 2008 to 2011 and increased the version + number from 2.4.4 to 2.4.5. + +2011-08-02 Werner Lemberg + + * mf2pt1.pl: + Prevented non-integer arguments from being passed to hsbw in the + definition of ".notdef". + +2008-01-27 Scott Pakin + + * mf2pt1.pl, mf2pt1.texi: + Increased the version number from 2.4.3 to 2.4.4 + +2008-01-27 Werner Lemberg + + * mf2pt1.pl: Modified to sort the MetaPost output files so that + the glyph order in the PFB is the same as in the MF sources. + +2008-01-13 Scott Pakin + + * README, mf2pt1.mp, mf2pt1.pl: + Updated the copyright year from 2007 to 2008 and increased the version + number from 2.4.2 to 2.4.3. + + * mf2pt1.texi: + Modified to format the document with a ragged bottom instead of the + default flush bottom. + +2008-01-13 Werner Lemberg + + * mf2pt1.mp: Bug fix: Patched the is_clockwise macro to prevent it + from failing so often. + + * mf2pt1.mp: + Bug fix: Changed "=" to ":=" in the makeline function. + +2007-06-30 Werner Lemberg + + * mf2pt1.mp, mf2pt1.pl: + Renamed "bbox" to "glyph_dimensions". + +2007-05-28 Scott Pakin + + * mf2pt1.texi: Updated the version to 2.4 and documented --bpppix. + +2007-05-28 Werner Lemberg + + * mf2pt1.pl: + Bug fix: Modified to set bpppix before calling get_bboxes. + + * mf2pt1.mp, mf2pt1.pl: + Added a --bpppix option to change the number of big points per pixel. + +2007-05-26 Scott Pakin + + * mf2pt1.pl: + Documented --version. Rewrote the option descriptions as full + sentences. Increased the version number to 2.4. + +2007-02-04 Scott Pakin + + * mf2pt1.texi: + Retypeset the parameter example and added a section showing how to + recover the original definitions of filldraw, unfilldraw, and + pencircle. + + * mf2pt1.mp: Made minor modifications. + + * README, mf2pt1.mp, mf2pt1.pl, mf2pt1.texi: + Updated the copyright date and increased the version number from 2.2 to 2.3. + + * mf2pt1.mp: + Modified to back up the original (mfplain.mp) definitions of + pencircle, filldraw, and unfilldraw. + +2007-02-04 Werner Lemberg + + * mf2pt1.pl: + Bug fix: Made the default underline thickness a positive number. + +2006-07-08 Scott Pakin + + * README: + Rewrote the description to compare mf2pt1 to TeXtrace and mftrace. + +2006-05-29 Scott Pakin + + * mf2pt1.texi: + Updated the documentation to match the latest code. Specifically, the + new format for .enc files and the new new defaults for underline + thickness and position are now correct. + + * mf2pt1.pl: + Corrected the handling of the underline thickness and position. + + * README, mf2pt1.mp: Updated the license agreement to LPPL 1.3c. + + * mf2pt1.pl: + Completely rewrote the command-line processing code so that (a) + command-line options override options specified in the .mf file and + (b) the --encoding flag works as intended. + +2005-12-04 Scott Pakin + + * README, mf2pt1.mp, mf2pt1.pl, mf2pt1.texi: + Increased the acceptable LPPL version number from 1.2 to 1.3a. + +2005-12-04 Werner Lemberg + + * mf2pt1.mp: Patched the clockwise and counterclockwise functions + to circumvent the turning-number bug in MetaPost. + +2005-02-27 Scott Pakin + + * mf2pt1.texi: + Proofread and updated accordingly. Also, increased the version number + from 1.2 to 2.0. + + * mf2pt1.pl: Increased the version number from 1.2 to 2.0. + +2005-02-26 Scott Pakin + + * mf2pt1.texi: + Wrote an Acknowledgments section. Corrected the @MF macro. Added PDF + metadata. Added a @dircategory and @direntry. + +2005-02-20 Scott Pakin + + * mf2pt1.pl, mf2pt1.texi: + Added a --ffscript option which lets the user override the default + FontForge script. + + * mf2pt1.texi: + Removed the mention of roex.mf because, according to Werner Lemberg, + it doesn't work with MetaPost. Inserted in its place a pointer to a + 6Jan2005 article on the MetaPost mailing list which includes an + overlap-removal library as an attachment. + + * mf2pt1.texi: Added mention of the "t1" and "asis" font encodings. + + * mf2pt1.pl: + Added Ralf Stubner's T1 encoding vector. Replaced "FontType-1.0" with + "FontType1-1.0", as directed by Ralf. Added Werner Lemberg's "asis" + font encoding. + + * mf2pt1.mp: + Reintroduced the Angle macro as it turns out it's still needed. + +2005-02-20 Werner Lemberg + + * mf2pt1.pl: + Replaced the FontForge script with one that performs a lot more + font cleanup. + +2005-02-14 Werner Lemberg + + * mf2pt1.mp: + Replaced the Angle and is_clockwise functions with the improved + versions provided by Boguslaw Jackowski. + +2005-02-06 Werner Lemberg + + * mf2pt1.mp: + Incorporated a turningnumber bug workaround. + +2005-02-06 Scott Pakin + + * mf2pt1.texi: + Documented the environment variables that mf2pt1 honors and replaced + all occurrences of @ifinfo with @ifnottex so as not to preclude HTML + generation. + + * mf2pt1.texi: + Documented the glyph_name command, the new way of dumping MetaPost + memory, the --rounding option, and the fact that mf2pt1 now invokes + t1asm and fontforge automatically. + + * mf2pt1.pl: + Modified to tell FontForge to fix any overlapping paths found in + the font. + + * mf2pt1.mp: + Added a user-callable glyph_name macro which enables a character to + specify explicitly the PostScript glyph name associated with it. + + * mf2pt1.pe: + Removed; .pe is now generated automatically by mf2pt1.pl. + + * mf2pt1.pl: + Modified to automatically try running the output through t1asm and + fontforge. + + * mf2pt1.pl: + Hoisted extraction of the font extension above MF2PT1_CMD and assigned + the value to $charnum instead of leaving it for a long time in $1. + Renamed $dx[123]m and $dy[123]m to $dx[123]d and $dy[123]d (for + "denominator"). Renamed "precision" to "rounding". Added blank lines + after each section of output. + + * mf2pt1.pl: + Made the following changes: replaced --mem with -mem; renamed $gn + to $gname and used ?: for assignment to it; cleaned up the spacing + around the frac_string and frac_approx uses; cleaned up the + `rmoveto' comment; fixed the "good" lines comment; renamed $dxm + and $dym to $dxd and $dyd (for "denominator"); fixed the precision + warnings; moved Werner's new functions to the top of the file with + the others; added prototypes for those functions; and, added a SEE + ALSO for FontForge. + + * mf2pt1.mp: Modified the comments to be more compatible with mftinc. + +2005-02-06 Werner Lemberg + + * mf2pt1.pl: + Incorporated various changes up to and including 4Feb2005. + +2005-01-30 Scott Pakin + + * mf2pt1.pe: + Created: FontForge script to autohint all of the characters in a + given font. + +2005-01-30 Werner Lemberg + + * mf2pt1.mp: Patched charwd. + + * mf2pt1.pl: Performed a major revision of the code. + +2005-01-08 Scott Pakin + + * mf2pt1.pl: + Bug fix: Corrected rounding to work properly on negative numbers. + Bug fix: Corrected the check for hvcurveto suitability. + Added my e-mail address to the --help output. + Cleaned up the code by moving subroutine definitions above the main program. + +2005-01-03 Scott Pakin + + * mf2pt1.pl: + Made rounding actually round. Added code to dump font parameters. + Corrected definitions of $underlinepos and $underlinethick to defer + computation until $designsize is defined. + + * mf2pt1.texi: + Changed "PfaEdit" in all occurences to "FontForge" and mentioned its + "Remove Overlap" feature. + + * mf2pt1.pl: Cleaned up command-line processing. + +2005-01-02 Scott Pakin + + * README, mf2pt1.mp, mf2pt1.pl, mf2pt1.texi: + Updated the year from 2004 to 2005. + + * README, mf2pt1.mp, mf2pt1.pl, mf2pt1.texi: + Added support for custom encodings and updated the copyright year and + my e-mail address. + +2001-06-19 Scott Pakin + + * README: Removed angled brackets to avoid confusing HTML renderings. + + * README: Description of mf2pt1 and a pointer to the user manual + + * mf2pt1.texi: Proofread and modified text accordingly. + +2001-06-17 Scott Pakin + + * mf2pt1.texi: + Added more Future Work (specifically, additional encodings). + + * mf2pt1.texi: Added a Future Work section. + +2001-06-04 Scott Pakin + + * mf2pt1.mp, mf2pt1.pl, mf2pt1.texi: Added license information. + N.B. The previous log message was supposed to indicate that + font_underline_position and font_underline_thickness now work in + Metafont units within the .mf file. + +2001-06-02 Scott Pakin + + * mf2pt1.texi: Made various modifications. + + * mf2pt1.pl: + Wrote some POD documentation and added a --help option to display + excerpts from it. + + * mf2pt1.texi: Added a font parameter usage example. + + * mf2pt1.texi: Added more text to the Usage section. + + * mf2pt1.texi: Added the start of a Usage section. + + * mf2pt1.texi: User documentation for mf2pt1 + +2001-06-01 Scott Pakin + + * mf2pt1.mp: Modified comments to use LaTeX and mftinc. + +2001-05-30 Scott Pakin + + * mf2pt1.mp, mf2pt1.pl: + Added PostScript-specific font parameters. + +2001-05-21 Scott Pakin + + * mf2pt1.mp, mf2pt1.pl: + Modified to convert the Metafont font_slant to a Type 1 ItalicAngle. + +2001-05-20 Scott Pakin + + * mf2pt1.pl: Added command-line options. + +2001-05-16 Scott Pakin + +2001-05-15 Scott Pakin + + * mf2pt1.mp: + Rewrote to use the turningnumber to determine if a path runs + clockwise or counterclockwise instead of calculating that + manually. + +2001-05-12 Scott Pakin + + * mf2pt1.pl: + Added a warning message for characters that lack a beginchar. + +2001-05-10 Scott Pakin + + * mf2pt1.pl: + Bug fix: Argument to font_size is now correctly treated as TeX + points, not PostScript points. + + * mf2pt1.mp: + Made using_pencircle robust to scaling (although not to rotation). + + * mf2pt1.mp: + Introduced a special case to drawdot and undrawdot: If the pen + looks like a circular pen, draw a clean circle instead of the + jagged pen path. + +2001-05-09 Scott Pakin + + * mf2pt1.mp, mf2pt1.pl: + Modified mf2pt1 to honor the font-specified design size (the font_size + command in Metafont). + + * mf2pt1.mp: + Added and improved the implementations of more Plain Metafont + primitives. + +2001-05-05 Scott Pakin + + * mf2pt1.mp: Added a draw macro. + +2001-05-04 Scott Pakin + + * mf2pt1.mp: Added an undrawdot macro. + + * mf2pt1.mp: Defined "safe" versions of the various fill commands. + Made is_clockwise more robust. + + * mf2pt1.mp: + Added code to replace the primitive pencircle with a non-primitive + approximation. + + * mf2pt1.mp: + Added (but do not yet use) a clockwise function for determining path + direction. + +2001-04-29 Scott Pakin + + * mf2pt1.pl: Corrected curveto handling. diff --git a/support/mf2pt1/README b/support/mf2pt1/README new file mode 100644 index 0000000000..4ba418f279 --- /dev/null +++ b/support/mf2pt1/README @@ -0,0 +1,40 @@ + +------------------------------------+ + | MF2PT1: | + | Produce PostScript Type 1 | + | fonts from Metafont source | + | | + | By Scott Pakin, scott+mf@pakin.org | + +------------------------------------+ + +Description +----------- + +mf2pt1 facilitates producing PostScript Type 1 fonts from a Metafont +source file. mf2pt1's advantage over tools such as TeXtrace and +mftrace is that it does not rely on bitmap tracing and therefore can +produce higher-quality Type 1 fonts than trace-based tools. The catch +is that mf2pt1 imposes a number of restrictions on the Metafont input +so it is not, as the name may imply, an automatic converter of +arbitrary Metafont fonts to Type 1 format. + + +Installation +------------ + +For installation instructions, see the mf2pt1 manual (mf2pt1.pdf). + + +Copyright and license +--------------------- + +Copyright (C) 2014 Scott Pakin, scott+mf@pakin.org + +This package may be distributed and/or modified under the conditions +of the LaTeX Project Public License, either version 1.3c of this +license or (at your option) any later version. The latest version of +this license is in: + + http://www.latex-project.org/lppl.txt + +and version 1.3c or later is part of all distributions of LaTeX +version 2006/05/20 or later. diff --git a/support/mf2pt1/mf2pt1.mp b/support/mf2pt1/mf2pt1.mp new file mode 100644 index 0000000000..588bc57cbb --- /dev/null +++ b/support/mf2pt1/mf2pt1.mp @@ -0,0 +1,495 @@ +%%%% +%%%% MF2PT1.MP, by Scott Pakin, scott+mf@pakin.org +%%%% +%%%% This file is used to dump a special version of MetaPost with: +%%%% mpost -progname=mpost -ini mf2pt1 \\dump +%%%% +%%%% To pretty-print this file, you'll need LaTeX and the mftinc package +%%%% (available from CTAN). +%%%% + +%%%% ==================================================================== %%%% +%%%% mf2pt1 %%%% +%%%% Copyright (C) 2014 Scott Pakin %%%% +%%%% %%%% +%%%% This program may be distributed and/or modified under the conditions %%%% +%%%% of the LaTeX Project Public License, either version 1.3c of this %%%% +%%%% license or (at your option) any later version. %%%% +%%%% %%%% +%%%% The latest version of this license is in: %%%% +%%%% %%%% +%%%% http://www.latex-project.org/lppl.txt %%%% +%%%% %%%% +%%%% and version 1.3c or later is part of all distributions of LaTeX %%%% +%%%% version 2006/05/20 or later. %%%% +%%%% ==================================================================== %%%% + +input mfplain; + +%%% addto makepath makepen +%%% length clockwise counterclockwise +%%% scaled dashed withcolor + +%% \begin{explaincode} +%% Enable a \MF\ file to determine if it's being built with +%% \texttt{mf2pt1}. +%% \end{explaincode} + +newinternal ps_output; +ps_output := 1; + + +%% \begin{explaincode} +%% The following was taken right out of \texttt{mfplain.mp}. The \mfcomment +% |def| and the |special|s at the end +%% are the sole additions. Normally, MetaPost outputs a tight bounding +%% box around the character in its PostScript output. The purpose of the +%% first \mfcomment +% |special| +%% is to pass \texttt{mf2pt1} a bounding box that includes the proper +%% surrounding whitespace. The purpose of the second special is to +%% provide \texttt{mf2pt1} with a default PostScript font name. +%% \end{explaincode} + +def beginchar(expr c,w_sharp,h_sharp,d_sharp) = + begingroup + charcode:=if known c: byte c else: 0 fi; + charwd:=w_sharp; charht:=h_sharp; chardp:=d_sharp; + w:=charwd*pt; h:=charht*pt; d:=chardp*pt; + charic:=0; clearxy; clearit; clearpen; scantokens extra_beginchar; + + def to_bp (expr num) = decimal (round (num*bp_per_pixel)) enddef; + special "% MF2PT1: glyph_dimensions 0 " & to_bp (-d) & " " & to_bp(w) & " " & to_bp(h); + special "% MF2PT1: font_size " & decimal designsize; + special "% MF2PT1: font_slant " & decimal font_slant_; + special "% MF2PT1: charwd " & decimal charwd; % Must come after the |font_size| |special| + for fvar = "font_identifier", "font_coding_scheme", "font_version", + "font_comment", "font_family", "font_weight", "font_unique_id", + "font_name": + if known scantokens (fvar & "_"): + special "% MF2PT1: " & fvar & " " & scantokens (fvar & "_"); + fi; + endfor; + for fvar = "font_underline_position", "font_underline_thickness": + if known scantokens (fvar & "_"): + special "% MF2PT1: " & fvar & " " & + scantokens ("decimal " & fvar & "_"); + fi; + endfor; + special "% MF2PT1: font_fixed_pitch " & + (if font_fixed_pitch_: "1" else: "0" fi); +enddef; + + +%% \begin{explaincode} +%% Enable a character to specify explicitly the PostScript glyph +%% name associated with it. +%% \end{explaincode} +def glyph_name expr name = + special "% MF2PT1: glyph_name " & name; +enddef; + + +%% \begin{explaincode} +%% Store the value of \mfcomment +% |font_slant_|, so we can recall it at each |beginchar|. +%% \end{explaincode} + +font_slant_ := 0; + +def font_slant expr x = + font_slant_ := x; + fontdimen 1: x +enddef; + + +%% \begin{explaincode} +%% Redefine \mfcomment +% |bpppix_|, the number of ``big'' points per pixel. \mfcomment +% This in turn redefines |mm|, |in|, |pt|, and other derived units. +%% \end{explaincode} + +def bpppix expr x = + bpppix_ := x; + mm := 2.83464 / bpppix_; + pt := 0.99626 / bpppix_; + dd := 1.06601 / bpppix_; + bp := 1 / bpppix_; + cm := 28.34645 / bpppix_; + pc := 11.95517 / bpppix_; + cc := 12.79213 / bpppix_; + in := 72 / bpppix_; + hppp := pt; + vppp := pt; +enddef; + + +%% \begin{explaincode} +%% Define a bunch of PostScript font parameters to be used by +%% \texttt{mf2pt1.pl}. Default values are specified in +%% \texttt{mf2pt1.pl}, not here. +%% \end{explaincode} + +forsuffixes fvar = font_version, font_comment, font_family, font_weight, + font_name, font_unique_id: + scantokens ("string " & str fvar & "_;"); + scantokens ("def " & str fvar & " expr x = " & str fvar & "_ := x enddef;"); +endfor; + +forsuffixes fvar = font_underline_position, font_underline_thickness: + scantokens ("numeric " & str fvar & "_;"); + scantokens ("def " & str fvar & " expr x = " & str fvar & "_ := x enddef;"); +endfor; + +boolean font_fixed_pitch_; +font_fixed_pitch_ := false; +def font_fixed_pitch expr x = font_fixed_pitch_ := x enddef; + + +%% \begin{explaincode} +%% We'd like to be able to use calligraphic pens. Normally, MetaPost's +%% output routine does all the work for us of converting these to filled +%% PostScript paths. The only exception occurs for paths drawn using a +%% pen that was transformed from \mfcomment +% |pencircle|. MetaPost outputs these paths as stroked PostScript +%% paths. The following code tricks MetaPost into using a filled path +%% for \mfcomment +% |pencircle| by replacing the primitive |pencircle| pen with a +%% non-primitive approximation. Note that we use a 20-gon for our circle +%% instead of a diamond, so we get better results from \mfcomment +% |draw|. +%% \end{explaincode} + +pen fakepencircle, mfplain_pencircle; +mfplain_pencircle := pencircle; +fakepencircle := makepen (for deg=0 step 360/20 until 359: + (0.5 cosd deg, 0.5 sind deg)-- + endfor cycle); +save pencircle; +pen pencircle; +pencircle := fakepencircle; + + +%% \begin{explaincode} +%% Return \mfcomment +% |true| if a path is cyclic, |false| otherwise. +%% \end{explaincode} + +def is_cyclic expr cpath = + (point 0 of cpath = point (length cpath) of cpath) +enddef; + + +%% \begin{explaincode} +%% Determine the direction of a path which doesn't intersect +%% itself. \mfcomment +% Returns |true| if the curve is clockwise, |false| if +%% counterclockwise. For non-cyclic paths the result is not +%% predictable. +%% \bigskip +%% +%% The \mfcomment +% |crossproduct|, |makeline|, and |is_clockwise| functions were +%% provided by Werner Lemberg. +%% \bigskip +%% +%% The algorithm used is quite simple: +%% +%% \begin{itemize} +%% \item Find a point~$P$ on the path which has a non-zero direction, +%% and which is on a not-too-short path element. +%% +%% \item Construct a ray of ``infinite'' length, starting in the +%% vicinity of~$P$ which intersects the path at this point. +%% +%% \item Use \mfcomment +% |intersectiontimes| to find the intersection. If the direction of +%% the path at this point is (near) zero, or if we have a grazing +%% intersection or even a tangent, get a new ray. +%% +%% \item Shorten the ray so that it starts right after the +%% intersection. Repeat the previous step until no intersection is +%% found. Then go back to the last intersection and compare the path's +%% direction with the direction of the ray. According to the +%% \emph{nonzero winding number} rule we have found a clockwise +%% oriented path if it crosses the ray from left to right. +%% \end{itemize} +%% +%% This method completely avoids any problems with the geometry of +%% B\'{e}zier curves. If problems arise, a different ray is tried. +%% Since it isn't necessary to analyze the whole path it runs quite fast +%% in spite of using \mfcomment +% |intersectiontimes| which is a slow MetaPost command. +%% \end{explaincode} + +vardef crossproduct (expr u, v) = + save u_, v_; + pair u_, v_; + + u_ := unitvector u; + v_ := unitvector v; + + abs (xpart u_ * ypart v_ - ypart u_ * xpart v_) +enddef; + +vardef makeline primary p = + save start, bad_n, loop, distance, d, i, n; + pair start, d; + + loop := 0; + bad_n := -1; + for i := 0 step 1 until length p - 1: + distance := length (point i of p - point (i + 1) of p); + if distance <> 0: + if distance < 1: + % In case we don't find something better. + bad_n := i; + else: + n := i; + loop := 1; + fi; + fi; + exitif loop = 1; + endfor; + + if loop = 0: + if bad_n <> -1: + n := bad_n; + loop = 1; + fi; + fi; + + % Add some randomness to get different lines for each function call. + n := n + uniformdeviate 0.8 + 0.1; + start := point n of p; + + if loop = 0: + % Construct a line which misses the degenerated path. + start + (1, 0) + -- start + (1, 1) + else: + d := direction n of p; + + % Again, some added randomness. + n := uniformdeviate 150 + 15; + d := unitvector (d rotated n); + + % Construct a line which intersects the path at least once. + start - eps * d + -- infinity * d + fi +enddef; + +vardef is_clockwise primary p = + save line, cut, cut_new, res, line_dir, tangent_dir; + path line; + pair cut, cut_new, line_dir, tangent_dir; + + line := makeline p; + line_dir := direction 0 of line; + + % Find the outermost intersection. + cut := (0, 0); + forever: + cut_new := line intersectiontimes p; + exitif cut_new = (-1, -1); + + % Compute a new line if we have a strange intersection. + tangent_dir := direction (ypart cut_new) of p; + if abs tangent_dir < eps: + % The vector is zero or too small. + line := makeline p; + line_dir := direction 0 of line; + + elseif abs (ypart cut_new - floor (ypart cut_new + 0.5)) < eps: + % Avoid possible tangent touching in a corner or cusp. + line := makeline p; + line_dir := direction 0 of line; + + elseif crossproduct (tangent_dir, line_dir) < 0.2: + % Grazing intersection (arcsin 0.2 ~= 11.5 degrees). + line := makeline p; + line_dir := direction 0 of line; + + else: + % Go ahead. + cut := cut_new; + line := subpath (xpart cut + eps, infinity) of line; + fi; + endfor; + + tangent_dir := direction (ypart cut) of p; + if tangent_dir <> (0, 0): + res := (angle tangent_dir - angle line_dir + 180) mod 360 - 180; + res < 0 + else: + false + fi +enddef; + + +%% \begin{explaincode} +%% Make a given path run clockwise or counterclockwise. \mfcomment +% (|counterclockwise| is defined by \texttt{mfplain} but we override +%% it here.) +%% \end{explaincode} + +vardef counterclockwise primary c = + (if is_clockwise c: (reverse c) else: c fi) +enddef; + +vardef clockwise primary c = + (if is_clockwise c: c else: (reverse c) fi) +enddef; + + +%% \begin{explaincode} +%% Redefine \mfcomment +% |fill| and |unfill| to ensure that filled paths run +%% counterclockwise and unfilled paths run clockwise, as is required +%% by PostScript Type~1 fonts. +%% \end{explaincode} + +def fill expr c = + addto currentpicture contour counterclockwise c t_ pc_ +enddef; + +def unfill expr c = + addto currentpicture contour clockwise c t_ pc_ withcolor background +enddef; + + +%% \begin{explaincode} +%% Convert \mfcomment +% |filldraw| and |unfilldraw| to |fill| and |unfill|. +%% \end{explaincode} + +let mfplain_filldraw := filldraw; +def filldraw expr c = + begingroup + message "! Warning: Replacing filldraw with fill."; + fill c + endgroup +enddef; + +let mfplain_unfilldraw := unfilldraw; +def unfilldraw expr c = + begingroup + message "! Warning: Replacing unfilldraw with unfill."; + unfill c + endgroup +enddef; + + +%% \begin{explaincode} +%% Return \mfcomment +% |true| if |currentpen| looks like a |pencircle|. +%% \end{explaincode} + +def using_pencircle = + begingroup + path qpath, circlepath; + qpath = makepath currentpen; + numeric circlediv; + circlepath = makepath pencircle; + circlediv = xpart (lrcorner circlepath); + + (length qpath = length circlepath) and (pen_rt <> 0) and (pen_top <> 0) + for pp = 0 upto (length qpath)-1: + and ((xpart (point pp of qpath) / pen_rt, + ypart (point pp of qpath) / pen_top) = + point pp of circlepath / circlediv) + endfor + endgroup +enddef; + + +%% \begin{explaincode} +%% If the pen looks like a circular pen, draw a nice circle. Otherwise, +%% draw the pen as is. +%% \end{explaincode} + +def drawdot expr z = + if using_pencircle: + begingroup + path cpath; + numeric clength; + cpath = makepath currentpen; + clength = length cpath; + fill ((point 0 of cpath) + ..(point clength/4 of cpath) + ..(point clength/2 of cpath) + ..(point 3*clength/4 of cpath) + ..cycle) shifted z t_ + endgroup + else: + addto currentpicture contour makepath currentpen shifted z + t_ pc_ + fi +enddef; + + +%% \begin{explaincode} +%% Do the same as the above, but unfill the current pen. +%% \end{explaincode} + +def undrawdot expr z = + if using_pencircle: + begingroup + path cpath; + numeric clength; + cpath = makepath currentpen; + clength = length cpath; + unfill ((point 0 of cpath) + ..(point clength/4 of cpath) + ..(point clength/2 of cpath) + ..(point 3*clength/4 of cpath) + ..cycle) shifted z t_ + endgroup + else: + unfill makepath currentpen shifted z t_ + fi +enddef; + + +%% \begin{explaincode} +%% MetaPost renders \mfcomment +% |draw| with a filled curve. +%% Hence, we need to ensure the orientation is correct (i.e., +%% counterclockwise). Unfortunately, we have no way to check for +%% overlap, and it's fairly common for MetaPost to output +%% self-overlapping curve outlines, even if the curve itself has no +%% overlap. +%% \end{explaincode} + +def draw expr p = + addto currentpicture + if picture p: + also p + elseif is_cyclic p: + doublepath counterclockwise p t_ withpen currentpen + else: + if is_clockwise (p--cycle): + doublepath (reverse p) t_ withpen currentpen + else: + doublepath p t_ withpen currentpen + fi + fi + pc_ +enddef; + +def undraw expr p = + addto currentpicture + if picture p: + also p + elseif is_cyclic p: + doublepath clockwise p t_ withpen currentpen + else: + if is_clockwise (p--cycle): + doublepath p t_ withpen currentpen + else: + doublepath (reverse p) t_ withpen currentpen + fi + fi + pc_ withcolor background +enddef; diff --git a/support/mf2pt1/mf2pt1.pdf b/support/mf2pt1/mf2pt1.pdf new file mode 100644 index 0000000000..94b586a4d2 Binary files /dev/null and b/support/mf2pt1/mf2pt1.pdf differ diff --git a/support/mf2pt1/mf2pt1.pl b/support/mf2pt1/mf2pt1.pl new file mode 100755 index 0000000000..abfd02c2f8 --- /dev/null +++ b/support/mf2pt1/mf2pt1.pl @@ -0,0 +1,1090 @@ +#! /usr/bin/perl + +################################################## +# Convert stylized Metafont to PostScript Type 1 # +# By Scott Pakin # +################################################## + +######################################################################## +# mf2pt1 # +# Copyright (C) 2014 Scott Pakin # +# # +# This program may be distributed and/or modified under the conditions # +# of the LaTeX Project Public License, either version 1.3c of this # +# license or (at your option) any later version. # +# # +# The latest version of this license is in: # +# # +# http://www.latex-project.org/lppl.txt # +# # +# and version 1.3c or later is part of all distributions of LaTeX # +# version 2006/05/20 or later. # +######################################################################## + +our $VERSION = "2.5a"; # mf2pt1 version number +require 5.6.1; # I haven't tested mf2pt1 with older Perl versions + +use File::Basename; +use File::Spec; +use Getopt::Long; +use Pod::Usage; +use Math::Trig; +use warnings; +use strict; + +# Define some common encoding vectors. +my @standardencoding = + ((map {"_a$_"} (0..31)), + qw (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), + (map {"_a$_"} (127..160)), + qw (exclamdown cent sterling fraction yen florin section currency + quotesingle quotedblleft guillemotleft guilsinglleft + guilsinglright fi fl _a176 endash dagger daggerdbl + periodcentered _a181 paragraph bullet quotesinglbase + quotedblbase quotedblright guillemotright ellipsis + perthousand _a190 questiondown _a192 grave acute circumflex + tilde macron breve dotaccent dieresis _a201 ring cedilla + _a204 hungarumlaut ogonek caron emdash), + (map {"_a$_"} (209..224)), + qw (AE _a226 ordfeminine _a228 _a229 _a230 _a231 Lslash Oslash OE + ordmasculine _a236 _a237 _a238 _a239 _a240 ae _a242 _a243 + _a244 dotlessi _a246 _a247 lslash oslash oe germandbls _a252 + _a253 _a254 _a255)); +my @isolatin1encoding = + ((map {"_a$_"} (0..31)), + qw (space exclam quotedbl numbersign dollar percent ampersand + quoteright parenleft parenright asterisk plus comma minus + 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), + (map {"_a$_"} (128..143)), + qw (dotlessi grave acute circumflex tilde macron breve dotaccent + dieresis _a153 ring cedilla _a156 hungarumlaut ogonek + caron space exclamdown cent sterling currency yen brokenbar + section dieresis copyright ordfeminine guillemotleft + logicalnot hyphen registered macron degree plusminus + twosuperior threesuperior acute mu paragraph periodcentered + cedilla onesuperior ordmasculine guillemotright onequarter + onehalf threequarters questiondown Agrave Aacute Acircumflex + Atilde Adieresis Aring AE Ccedilla Egrave Eacute Ecircumflex + Edieresis Igrave Iacute Icircumflex Idieresis Eth Ntilde + Ograve Oacute Ocircumflex Otilde Odieresis multiply Oslash + Ugrave Uacute Ucircumflex Udieresis Yacute Thorn germandbls + agrave aacute acircumflex atilde adieresis aring ae ccedilla + egrave eacute ecircumflex edieresis igrave iacute icircumflex + idieresis eth ntilde ograve oacute ocircumflex otilde + odieresis divide oslash ugrave uacute ucircumflex udieresis + yacute thorn ydieresis)); +my @ot1encoding = + qw (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 + suppress 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); +my @t1encoding = + qw (grave acute circumflex tilde dieresis hungarumlaut ring caron + breve macron dotaccent cedilla ogonek quotesinglbase + guilsinglleft guilsinglright quotedblleft quotedblright + quotedblbase guillemotleft guillemotright endash emdash cwm + perthousand dotlessi dotlessj ff fi fl ffi ffl 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 + sfthyphen Abreve Aogonek Cacute Ccaron Dcaron Ecaron Eogonek + Gbreve Lacute Lcaron Lslash Nacute Ncaron Eng Ohungarumlaut + Racute Rcaron Sacute Scaron Scedilla Tcaron Tcedilla + Uhungarumlaut Uring Ydieresis Zacute Zcaron Zdotaccent IJ + Idotaccent dcroat section abreve aogonek cacute ccaron dcaron + ecaron eogonek gbreve lacute lcaron lslash nacute ncaron eng + ohungarumlaut racute rcaron sacute scaron scedilla tcaron + tcedilla uhungarumlaut uring ydieresis zacute zcaron zdotaccent + ij exclamdown questiondown sterling Agrave Aacute Acircumflex + Atilde Adieresis Aring AE Ccedilla Egrave Eacute Ecircumflex + Edieresis Igrave Iacute Icircumflex Idieresis Eth Ntilde Ograve + Oacute Ocircumflex Otilde Odieresis OE Oslash Ugrave Uacute + Ucircumflex Udieresis Yacute Thorn SS agrave aacute acircumflex + atilde adieresis aring ae ccedilla egrave eacute ecircumflex + edieresis igrave iacute icircumflex idieresis eth ntilde ograve + oacute ocircumflex otilde odieresis oe oslash ugrave uacute + ucircumflex udieresis yacute thorn germandbls); + +# Define font parameters that the user can override. +my $fontversion; +my $creationdate; +my $comment; +my $familyname; +my $weight; +my $fullname; +my $fixedpitch; +my $italicangle; +my $underlinepos; +my $underlinethick; +my $fontname; +my $uniqueID; +my $designsize; +my ($mffile, $pt1file, $pfbfile, $ffscript); +my $encoding; +my $rounding; +my $bpppix; + +# Define all of our other global variables. +my $progname = basename $0, ".pl"; +my $mag; +my @fontbbox; +my @charbbox; +my @charwd; +my @glyphname; +my @charfiles; +my $filebase; +my $filedir; +my $filenoext; +my $versionmsg = "mf2pt1 version $VERSION + +Copyright (C) 2012 Scott Pakin + +This program may be distributed and/or modified under the conditions +of the LaTeX Project Public License, either version 1.3c of this +license or (at your option) any later version. + +The latest version of this license is in: + + http://www.latex-project.org/lppl.txt + +and version 1.3c or later is part of all distributions of LaTeX +version 2006/05/20 or later. +"; + + +###################################################################### + +# The routines to compute the fractional approximation of a real number +# are heavily based on code posted by Ben Tilly +# on Nov 16th, 2000, to the +# PerlMonks list. See . + + +# Takes numerator/denominator pairs. +# Returns a PS fraction string representation (with a trailing space). +sub frac_string (@) +{ + my $res = ""; + + while (@_) { + my $n = shift; + my $d = shift; + $res .= $n . " "; + $res .= $d . " div " if $d > 1; + } + + return $res; +} + + +# Takes a number. +# Returns a numerator and denominator with the smallest denominator +# so that the difference of the resulting fraction to the number is +# smaller or equal to $rounding. +sub frac_approx ($) +{ + my $num = shift; + my $f = ret_frac_iter ($num); + + while (1) { + my ($n, $m) = $f->(); + my $approx = $n / $m; + my $delta = abs ($num - $approx); + return ($n, $m) if ($delta <= $rounding); + } +} + + +# Takes a number, returns the best integer approximation and (in list +# context) the error. +sub best_int ($) +{ + my $x = shift; + my $approx = sprintf '%.0f', $x; + if (wantarray) { + return ($approx, $x - $approx); + } + else { + return $approx; + } +} + + +# Takes a numerator and denominator, in scalar context returns +# the best fraction describing them, in list the numerator and +# denominator. +sub frac_standard ($$) +{ + my $n = best_int(shift); + my $m = best_int(shift); + my $k = gcd($n, $m); + $n /= $k; + $m /= $k; + if ($m < 0) { + $n *= -1; + $m *= -1; + } + if (wantarray) { + return ($n, $m); + } + else { + return "$n/$m"; + } +} + + +# Euclidean algorithm for calculating a GCD. +# Takes two integers, returns the greatest common divisor. +sub gcd ($$) +{ + my ($n, $m) = @_; + while ($m) { + my $k = $n % $m; + ($n, $m) = ($m, $k); + } + return $n; +} + + +# Takes a list of terms in a continued fraction, and converts it +# into a fraction. +sub ints_to_frac (@) +{ + my ($n, $m) = (0, 1); # Start with 0 + while (@_) { + my $k = pop; + if ($n) { + # Want frac for $k + 1/($n/$m) + ($n, $m) = frac_standard($k*$n + $m, $n); + } + else { + # Want $k + ($n, $m) = frac_standard($k, 1); + } + } + return frac_standard($n, $m); +} + + +# Takes a number, returns an anon sub which iterates through a set of +# fractional approximations that converges very quickly to the number. +sub ret_frac_iter ($) +{ + my $x = shift; + my $term_iter = ret_next_term_iter($x); + my @ints; + return sub { + push @ints, $term_iter->(); + return ints_to_frac(@ints); + } +} + + +# Terms of a continued fraction converging on that number. +sub ret_next_term_iter ($) +{ + my $x = shift; + return sub { + (my $n, $x) = best_int($x); + if (0 != $x) { + $x = 1/$x; + } + return $n; + } +} + +###################################################################### + +# Round a number to the nearest integer. +sub round ($) +{ + return int($_[0] + 0.5*($_[0] <=> 0)); +} + + +# Round a number to a given precision. +sub prec ($) +{ + return round ($_[0] / $rounding) * $rounding; +} + + +# Set a variable's value to the first defined value in the given list. +# If the variable was not previously defined and no value in the list +# is defined, do nothing. +sub assign_default (\$@) +{ + my $varptr = shift; # Pointer to variable to define + return if defined $$varptr && $$varptr ne "UNSPECIFIED"; + foreach my $val (@_) { + next if !defined $val; + $$varptr = $val; + return; + } +} + + +# Print and execute a shell command. An environment variable with the +# same name as the command overrides the command name. Return 1 on +# success, 0 on failure. Optionally abort if the command fails, based +# on the first argument to execute_command. +sub execute_command ($@) +{ + my $abort_on_failure = shift; + my @command = @_; + $command[0] = $ENV{uc $command[0]} || $command[0]; + my $prettyargs = join (" ", map {/[\\ ]/ ? "'$_'" : $_} @command); + print "Invoking \"$prettyargs\"...\n"; + my $result = system @command; + die "${progname}: \"$prettyargs\" failed ($!)\n" if $result && $abort_on_failure; + return !$result; +} + + +# Output the font header. +sub output_header () +{ + # Show the initial boilerplate. + print OUTFILE <<"ENDHEADER"; +%!FontType1-1.0: $fontname $fontversion +%%CreationDate: $creationdate +% Font converted to Type 1 by mf2pt1, written by Scott Pakin. +11 dict begin +/FontInfo 11 dict dup begin +/version ($fontversion) readonly def +/Notice ($comment) readonly def +/FullName ($fullname) readonly def +/FamilyName ($familyname) readonly def +/Weight ($weight) readonly def +/ItalicAngle $italicangle def +/isFixedPitch $fixedpitch def +/UnderlinePosition $underlinepos def +/UnderlineThickness $underlinethick def +end readonly def +/FontName /$fontname def +ENDHEADER + + # If we're not using an encoding that PostScript knows about, then + # create an encoding vector. + if ($encoding==\@standardencoding) { + print OUTFILE "/Encoding StandardEncoding def\n"; + } + else { + print OUTFILE "/Encoding 256 array\n"; + print OUTFILE "0 1 255 {1 index exch /.notdef put} for\n"; + foreach my $charnum (0 .. $#{$encoding}) { + if ($encoding->[$charnum] && $encoding->[$charnum]!~/^_a\d+$/) { + print OUTFILE "dup $charnum /$encoding->[$charnum] put\n"; + } + } + print OUTFILE "readonly def\n"; + } + + # Show the final boilerplate. + print OUTFILE <<"ENDHEADER"; +/PaintType 0 def +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0] readonly def +/UniqueID $uniqueID def +/FontBBox{@fontbbox}readonly def +currentdict end +currentfile eexec +dup /Private 5 dict dup begin +/RD{string currentfile exch readstring pop}executeonly def +/ND{noaccess def}executeonly def +/NP{noaccess put}executeonly def +ENDHEADER +} + + +# Use MetaPost to generate one PostScript file per character. We +# calculate the font bounding box from these characters and store them +# in @fontbbox. If the input parameter is 1, set other font +# parameters, too. +sub get_bboxes ($) +{ + execute_command 1, ("mpost", "-mem=mf2pt1", "-progname=mpost", + "\\mode:=localfont; mag:=$mag; bpppix $bpppix; nonstopmode; input $mffile"); + opendir (CURDIR, ".") || die "${progname}: $! ($filedir)\n"; + @charfiles = sort + { ($a=~ /\.(\d+)$/)[0] <=> ($b=~ /\.(\d+)$/)[0] } + grep /^$filebase.*\.\d+$/, readdir(CURDIR); + close CURDIR; + @fontbbox = (1000000, 1000000, -1000000, -1000000); + foreach my $psfile (@charfiles) { + # Read the character number from the output file's extension. + $psfile =~ /\.(\d+)$/; + my $charnum = $1; + + # Process in turn each line of the current PostScript file. + my $havebbox = 0; + open (PSFILE, "<$psfile") || die "${progname}: $! ($psfile)\n"; + while () { + my @tokens = split " "; + if ($tokens[0] eq "%%BoundingBox:") { + # Store the MetaPost-produced bounding box, just in case + # the given font doesn't use beginchar. + @tokens = ("%", "MF2PT1:", "glyph_dimensions", @tokens[1..4]); + $havebbox--; + } + next if $#tokens<1 || $tokens[1] ne "MF2PT1:"; + + # Process a "special" inserted into the generated PostScript. + MF2PT1_CMD: + { + # glyph_dimensions llx lly urx ury -- specified glyph dimensions + $tokens[2] eq "glyph_dimensions" && do { + my @bbox = @tokens[3..6]; + $fontbbox[0]=$bbox[0] if $bbox[0]<$fontbbox[0]; + $fontbbox[1]=$bbox[1] if $bbox[1]<$fontbbox[1]; + $fontbbox[2]=$bbox[2] if $bbox[2]>$fontbbox[2]; + $fontbbox[3]=$bbox[3] if $bbox[3]>$fontbbox[3]; + $charbbox[$charnum] = \@bbox; + $havebbox++; + last MF2PT1_CMD; + }; + + # If all we want is the bounding box, exit the loop now. + last MF2PT1_CMD if !$_[0]; + + # glyph_name name -- glyph name + $tokens[2] eq "glyph_name" && do { + $glyphname[$charnum] = $tokens[3]; + last MF2PT1_CMD; + }; + + # charwd wd -- character width as in TFM + $tokens[2] eq "charwd" && do { + $charwd[$charnum] = $tokens[3]; + last MF2PT1_CMD; + }; + + # font_identifier name -- full font name + $tokens[2] eq "font_identifier" && do { + $fullname = $tokens[3]; + last MF2PT1_CMD; + }; + + # font_size number -- font design size (pt, not bp) + $tokens[2] eq "font_size" && $tokens[3] && do { + $designsize = $tokens[3] * 72 / 72.27; + last MF2PT1_CMD; + }; + + # font_slant number -- italic amount + $tokens[2] eq "font_slant" && do { + $italicangle = 0 + rad2deg (atan(-$tokens[3])); + last MF2PT1_CMD; + }; + + # font_coding_scheme string -- font encoding + $tokens[2] eq "font_coding_scheme" && do { + $encoding = $tokens[3]; + last MF2PT1_CMD; + }; + + # font_version string -- font version number (xxx.yyy) + $tokens[2] eq "font_version" && do { + $fontversion = $tokens[3]; + last MF2PT1_CMD; + }; + + # font_comment string -- font comment notice + $tokens[2] eq "font_comment" && do { + $comment = join (" ", @tokens[3..$#tokens]); + last MF2PT1_CMD; + }; + + # font_family string -- font family name + $tokens[2] eq "font_family" && do { + $familyname = $tokens[3]; + last MF2PT1_CMD; + }; + + # font_weight string -- font weight (e.g., "Book" or "Heavy") + $tokens[2] eq "font_weight" && do { + $weight = $tokens[3]; + last MF2PT1_CMD; + }; + + # font_fixed_pitch number -- fixed width font (0=false, 1=true) + $tokens[2] eq "font_fixed_pitch" && do { + $fixedpitch = $tokens[3]; + last MF2PT1_CMD; + }; + + # font_underline_position number -- vertical underline position + $tokens[2] eq "font_underline_position" && do { + # We store $underlinepos in points and later + # scale it by 1000/$designsize. + $underlinepos = $tokens[3]; + last MF2PT1_CMD; + }; + + # font_underline_thickness number -- thickness of underline + $tokens[2] eq "font_underline_thickness" && do { + # We store $underlinethick in points and later + # scale it by 1000/$designsize. + $underlinethick = $tokens[3]; + last MF2PT1_CMD; + }; + + # font_name string -- font name + $tokens[2] eq "font_name" && do { + $fontname = $tokens[3]; + last MF2PT1_CMD; + }; + + # font_unique_id number (as string) -- globally unique font ID + $tokens[2] eq "font_unique_id" && do { + $uniqueID = 0+$tokens[3]; + last MF2PT1_CMD; + }; + } + } + close PSFILE; + if (!$havebbox) { + warn "${progname}: No beginchar in character $charnum; glyph dimensions are probably incorrect\n"; + } + } +} + + +# Convert ordinary, MetaPost-produced PostScript files into Type 1 +# font programs. +sub output_font_programs () +{ + # Iterate over all the characters. We convert each one, line by + # line and token by token. + print "Converting PostScript graphics to Type 1 font programs...\n"; + foreach my $psfile (@charfiles) { + # Initialize the font program. + $psfile =~ /\.(\d+)$/; + my $charnum = $1; + my $gname = $glyphname[$charnum] || $encoding->[$charnum]; + my @fontprog; + push @fontprog, ("/$gname {", + frac_string (frac_approx ($charbbox[$charnum]->[0]), + frac_approx ($charbbox[$charnum]->[2])) + . "hsbw"); + my ($cpx, $cpy) = + ($charbbox[$charnum]->[0], 0); # Current point (PostScript) + + # Iterate over every line in the current file. + open (PSFILE, "<$psfile") || die "${progname}: $! ($psfile)\n"; + while (my $oneline=) { + next if $oneline=~/^\%/; + next if $oneline=~/set/; # Fortunately, "set" never occurs on "good" lines. + my @arglist; # Arguments to current PostScript function + + # Iterate over every token in the current line. + TOKENLOOP: + foreach my $token (split " ", $oneline) { + # Number: Round and push on the argument list. + $token =~ /^[-.\d]+$/ && do { + push @arglist, prec ($&); + next TOKENLOOP; + }; + + # curveto: Convert to vhcurveto, hvcurveto, or rrcurveto. + $token eq "curveto" && do { + my ($dx1, $dy1) = ($arglist[0] - $cpx, + $arglist[1] - $cpy); + my ($dx1n, $dx1d) = frac_approx ($dx1); + my ($dy1n, $dy1d) = frac_approx ($dy1); + $cpx += $dx1n / $dx1d; + $cpy += $dy1n / $dy1d; + + my ($dx2, $dy2) = ($arglist[2] - $cpx, + $arglist[3] - $cpy); + my ($dx2n, $dx2d) = frac_approx ($dx2); + my ($dy2n, $dy2d) = frac_approx ($dy2); + $cpx += $dx2n / $dx2d; + $cpy += $dy2n / $dy2d; + + my ($dx3, $dy3) = ($arglist[4] - $cpx, + $arglist[5] - $cpy); + my ($dx3n, $dx3d) = frac_approx ($dx3); + my ($dy3n, $dy3d) = frac_approx ($dy3); + $cpx += $dx3n / $dx3d; + $cpy += $dy3n / $dy3d; + + if (!$dx1n && !$dy3n) { + push @fontprog, frac_string ($dy1n, $dy1d, + $dx2n, $dx2d, + $dy2n, $dy2d, + $dx3n, $dx3d) + . "vhcurveto"; + } + elsif (!$dy1n && !$dx3n) { + push @fontprog, frac_string ($dx1n, $dx1d, + $dx2n, $dx2d, + $dy2n, $dy2d, + $dy3n, $dy3d) + . "hvcurveto"; + } + else { + push @fontprog, frac_string ($dx1n, $dx1d, + $dy1n, $dy1d, + $dx2n, $dx2d, + $dy2n, $dy2d, + $dx3n, $dx3d, + $dy3n, $dy3d) + . "rrcurveto"; + } + next TOKENLOOP; + }; + + # lineto: Convert to vlineto, hlineto, or rlineto. + $token eq "lineto" && do { + my ($dx, $dy) = ($arglist[0] - $cpx, + $arglist[1] - $cpy); + my ($dxn, $dxd) = frac_approx ($dx); + my ($dyn, $dyd) = frac_approx ($dy); + $cpx += $dxn / $dxd; + $cpy += $dyn / $dyd; + + if (!$dxn) { + push @fontprog, frac_string ($dyn, $dyd) + . "vlineto" if $dyn; + } + elsif (!$dyn) { + push @fontprog, frac_string ($dxn, $dxd) + . "hlineto"; + } + else { + push @fontprog, frac_string ($dxn, $dxd, $dyn, $dyd) + . "rlineto"; + } + next TOKENLOOP; + }; + + # moveto: Convert to vmoveto, hmoveto, or rmoveto. + $token eq "moveto" && do { + my ($dx, $dy) = ($arglist[0] - $cpx, + $arglist[1] - $cpy); + my ($dxn, $dxd) = frac_approx ($dx); + my ($dyn, $dyd) = frac_approx ($dy); + $cpx += $dxn / $dxd; + $cpy += $dyn / $dyd; + + if (!$dxn) { + push @fontprog, frac_string ($dyn, $dyd) + . "vmoveto"; + } + elsif (!$dyn) { + push @fontprog, frac_string ($dxn, $dxd) + . "hmoveto"; + } + else { + push @fontprog, frac_string ($dxn, $dxd, $dyn, $dyd) + . "rmoveto"; + } + next TOKENLOOP; + }; + + # closepath: Output as is. + $token eq "closepath" && do { + push @fontprog, $token; + next TOKENLOOP; + }; + } + } + close PSFILE; + push @fontprog, ("endchar", + "} ND"); + print OUTFILE join ("\n\t", @fontprog), "\n"; + } +} + + +# Output the final set of code for the Type 1 font. +sub output_trailer () +{ + print OUTFILE <<"ENDTRAILER"; +/.notdef { + 0 @{[frac_string (frac_approx ($fontbbox[2] - $fontbbox[0]))]} hsbw + endchar + } ND +end +end +readonly put +noaccess put +dup/FontName get exch definefont pop +mark currentfile closefile +cleartomark +ENDTRAILER +} + +###################################################################### + +# Parse the command line. Asterisks in the following represents +# commands also defined by Plain Metafont. +my %opthash = (); +GetOptions (\%opthash, + "fontversion=s", # font_version + "comment=s", # font_comment + "family=s", # font_family + "weight=s", # font_weight + "fullname=s", # font_identifier (*) + "fixedpitch!", # font_fixed_pitch + "italicangle=f", # font_slant (*) + "underpos=f", # font_underline_position + "underthick=f", # font_underline_thickness + "name=s", # font_name + "uniqueid=i", # font_unique_id + "designsize=f", # font_size (*) + "encoding=s", # font_coding_scheme (*) + "rounding=f", + "bpppix=f", + "ffscript=s", + "h|help", + "V|version") || pod2usage(2); +if (defined $opthash{"h"}) { + pod2usage(-verbose => 1, + -output => \*STDOUT, # Bug workaround for Pod::Usage + -exitval => "NOEXIT"); + print "Please e-mail bug reports to scott+mf\@pakin.org.\n"; + exit 1; +} +do {print $versionmsg; exit 1} if defined $opthash{"V"}; +pod2usage(2) if $#ARGV != 0; + +# Extract the filename from the command line. +$mffile = $ARGV[0]; +my @fileparts = fileparse $mffile, ".mf"; +$filebase = $fileparts[0]; +$filedir = $fileparts[1]; +$filenoext = File::Spec->catfile ($filedir, $filebase); +$pt1file = $filebase . ".pt1"; +$pfbfile = $filebase . ".pfb"; + +assign_default $bpppix, $opthash{bpppix}, 0.02; + +# Make our first pass through the input, to set values for various options. +$mag = 100; # Get a more precise bounding box. +get_bboxes(1); # This might set $designsize. + +# Sanity-check the specified precision. +assign_default $rounding, $opthash{rounding}, 1; +if ($rounding<=0.0 || $rounding>1.0) { + die sprintf "%s: Invalid rounding amount \"%g\"; value must be a positive number no greater than 1.0\n", $progname, $rounding; +} + +# Ensure that every user-definable parameter is assigned a value. +assign_default $fontversion, $opthash{fontversion}, "001.000"; +assign_default $creationdate, scalar localtime; +assign_default $comment, $opthash{comment}, "Font converted to Type 1 by mf2pt1, written by Scott Pakin."; +assign_default $weight, $opthash{weight}, "Medium"; +assign_default $fixedpitch, $opthash{fixedpitch}, 0; +assign_default $uniqueID, $opthash{uniqueid}, int(rand(1000000)) + 4000000; +assign_default $designsize, $opthash{designsize}; +die "${progname}: a design size must be specified in $mffile or on the command line\n" if !defined $designsize; +die "${progname}: the design size must be a positive number\n" if $designsize<=0.0; +assign_default $underlinepos, $opthash{underpos}, -1; +$underlinepos = round(1000*$underlinepos/$designsize); +assign_default $underlinethick, $opthash{underthick}, 0.5; +$underlinethick = round(1000*$underlinethick/$designsize); +assign_default $fullname, $opthash{fullname}, $filebase; +assign_default $familyname, $opthash{family}, $fullname; +assign_default $italicangle, $opthash{italicangle}, 0; +assign_default $fontname, $opthash{name}, "$familyname-$weight"; +$fontname =~ s/\s//g; +assign_default $encoding, $opthash{encoding}, "standard"; +my $encoding_name = $encoding; +ENCODING: +{ + if (-e $encoding) { + # Filenames take precedence over built-in encodings. + my @enc_array; + open (ENCFILE, "<$encoding") || die "${progname}: $! ($encoding)\n"; + while (my $oneline = ) { + $oneline =~ s/\%.*$//; + foreach my $word (split " ", $oneline) { + push @enc_array, substr($word, 1) if substr($word, 0, 1) eq "/"; + } + } + close ENCFILE; + $encoding_name = substr (shift @enc_array, 1); + $encoding = \@enc_array; + last ENCODING; + } + $encoding=\@standardencoding, last ENCODING if $encoding eq "standard"; + $encoding=\@isolatin1encoding, last ENCODING if $encoding eq "isolatin1"; + $encoding=\@ot1encoding, last ENCODING if $encoding eq "ot1"; + $encoding=\@t1encoding, last ENCODING if $encoding eq "t1"; + $encoding=\@glyphname, last ENCODING if $encoding eq "asis"; + warn "${progname}: Unknown encoding \"$encoding\"; using standard Adobe encoding\n"; + $encoding=\@standardencoding; # Default to standard encoding +} +assign_default $fixedpitch, $opthash{fixedpitch}, 0; +$fixedpitch = $fixedpitch ? "true" : "false"; +assign_default $ffscript, $opthash{ffscript}; + +# Output the final values of all of our parameters. +print "\n"; +print <<"PARAMVALUES"; +mf2pt1 is using the following font parameters: + font_version: $fontversion + font_comment: $comment + font_family: $familyname + font_weight: $weight + font_identifier: $fullname + font_fixed_pitch: $fixedpitch + font_slant: $italicangle + font_underline_position: $underlinepos + font_underline_thickness: $underlinethick + font_name: $fontname + font_unique_id: $uniqueID + font_size: $designsize (bp) + font_coding_scheme: $encoding_name +PARAMVALUES + ; +print "\n"; + +# Scale by a factor of 1000/design size. +$mag = 1000.0 / $designsize; +get_bboxes(0); +print "\n"; + +# Output the font in disassembled format. +open (OUTFILE, ">$pt1file") || die "${progname}: $! ($pt1file)\n"; +output_header(); +printf OUTFILE "2 index /CharStrings %d dict dup begin\n", + 1+scalar(grep {defined($_)} @charbbox); +output_font_programs(); +output_trailer(); +close OUTFILE; +unlink @charfiles; +print "\n"; + +# Convert from the disassembled font format to Type 1 binary format. +if (!execute_command 0, ("t1asm", $pt1file, $pfbfile)) { + die "${progname}: You'll need either to install t1utils and rerun $progname or find another way to convert $pt1file to $pfbfile\n"; + exit 1; +} +print "\n"; +unlink $pt1file; + +# Use FontForge to autohint the result. +my $user_script = 0; # 1=script file was provided by the user; 0=created here +if (defined $ffscript) { + # The user provided his own script. + $user_script = 1; +} +else { + # Create a FontForge script file. + $ffscript = $filebase . ".pe"; + open (FFSCRIPT, ">$ffscript") || die "${progname}: $! ($ffscript)\n"; + print FFSCRIPT <<'AUTOHINT'; +Open($1); +SelectAll(); +RemoveOverlap(); +AddExtrema(); +Simplify(0, 2); +CorrectDirection(); +Simplify(0, 2); +RoundToInt(); +AutoHint(); +Generate($1); +Quit(0); +AUTOHINT + ; + close FFSCRIPT; +} +if (!execute_command 0, ("fontforge", "-script", $ffscript, $pfbfile)) { + warn "${progname}: You'll need to install FontForge if you want $pfbfile autohinted (not required, but strongly recommended)\n"; +} +unlink $ffscript if !$user_script; +print "\n"; + +# Finish up. +print "*** Successfully generated $pfbfile! ***\n"; +exit 0; + +###################################################################### + +__END__ + +=head1 NAME + +mf2pt1 - produce a PostScript Type 1 font program from a Metafont source + + +=head1 SYNOPSIS + +mf2pt1 +[B<--help>] +[B<--version>] +[B<--comment>=I] +[B<--designsize>=I] +[B<--encoding>=I] +[B<--family>=I] +[B<-->[B]B] +[B<--fontversion>=I] +[B<--fullname>=I] +[B<--italicangle>=I] +[B<--name>=I] +[B<--underpos>=I] +[B<--underthick>=I] +[B<--uniqueid>=I] +[B<--weight>=I] +[B<--rounding>=I] +[B<--bpppix>=I] +[B<--ffscript>=I] +I.mf + + +=head1 WARNING + +The B Info file is the main source of documentation for +B. This man page is merely a brief summary. + + +=head1 DESCRIPTION + +B facilitates producing PostScript Type 1 fonts from a +Metafont source file. It is I, as the name may imply, an +automatic converter of arbitrary Metafont fonts to Type 1 format. +B imposes a number of restrictions on the Metafont input. If +these restrictions are met, B will produce valid Type 1 +output. (Actually, it produces "disassembled" Type 1; the B +program from the B suite will convert this to a true Type 1 +font.) + +=head2 Usage + + mf2pt1 myfont.mf + +=head1 OPTIONS + +Font parameters are best specified within a Metafont program. If +necessary, though, command-line options can override any of these +parameters. The B Info page, the primary source of B +documentation, describes the following in greater detail. + +=over 4 + +=item B<--help> + +Provide help on B's command-line options. + +=item B<--version> + +Output the B version number, copyright, and license. + +=item B<--comment>=I + +Include a font comment, usually a copyright notice. + +=item B<--designsize>=I + +Specify the font design size in points. + +=item B<--encoding>=I + +Designate the font encoding, either the name of a---typically +F<.enc>---file which contains a PostScript font-encoding vector or one +of C (the default), C, C, or C. + +=item B<--family>=I + +Specify the font family. + +=item B<--fixedpitch>, B<--nofixedpitch> + +Assert that the font uses either monospaced (B<--fixedpitch>) or +proportional (B<--nofixedpitch>) character widths. + +=item B<--fontversion>=I + +Specify the font's major and minor version number. + +=item B<--fullname>=I + +Designate the full font name (family plus modifiers). + +=item B<--italicangle>=I + +Designate the italic angle in degrees counterclockwise from vertical. + +=item B<--name>=I + +Provide the font name. + +=item B<--underpos>=I + +Specify the vertical position of the underline in thousandths of the +font height. + +=item B<--underthick>=I + +Specify the thickness of the underline in thousandths of the font +height. + +=item B<--uniqueid>=I + +Specify a globally unique font identifier. + +=item B<--weight>=I + +Provide a description of the font weight (e.g., ``Heavy''). + +=item B<--rounding>=I + +Specify the fraction of a font unit (0.0 < I <= 1.0) to which +to round coordinate values [default: 1.0]. + +=item B<--bpppix>=I + +Redefine the number of big points per pixel from 0.02 to I. + +=item B<--ffscript>=I + +Name a script to pass to FontForge. + +=back + + +=head1 FILES + +F (which is generated from F and F) + + +=head1 NOTES + +As stated in L, the complete source of documentation for +B is the Info page, not this man page. + + +=head1 SEE ALSO + +mf(1), mpost(1), t1asm(1), fontforge(1) + + +=head1 AUTHOR + +Scott Pakin, I diff --git a/support/mf2pt1/mf2pt1.texi b/support/mf2pt1/mf2pt1.texi new file mode 100644 index 0000000000..45fe6e309d --- /dev/null +++ b/support/mf2pt1/mf2pt1.texi @@ -0,0 +1,977 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename mf2pt1.info +@settitle mf2pt1 +@setchapternewpage off +@dircategory TeX +@direntry +* mf2pt1: (mf2pt1). PostScript Type 1 fonts from Metafont source. +@end direntry +@finalout +@c %**end of header + +@copying +Copyright @copyright{} 2014 Scott Pakin + +@sp 2 + +This program may be distributed and/or modified under the conditions +of the @LaTeX{} Project Public License, either version 1.3c of this +license or (at your option) any later version. + +@sp 1 + +The latest version of this license is in: +@sp 1 +@center @uref{http://www.latex-project.org/lppl.txt} +@sp 1 +and version 1.3c or later is part of all distributions of @LaTeX{} +version 2006/05/20 or later. + +@end copying + +@set VERSION 2.5a +@set DATE 30 April 2014 + +@c Define some fonts we intend to use. +@iftex +@tex +@global@font@tenlogo=logo10 % font used for the METAFONT logo +@global@font@eightrm=cmr8 % needed for the "A" in "LaTeX" +@end tex +@end iftex + +@c Define a macro for the Metafont logo. +@iftex +@macro MF {} +@tex +@tenlogo @leavevmode@hbox{METAFONT}@unskip +@end tex +@end macro +@end iftex +@ifnottex +@macro MF {} +Metafont +@end macro +@end ifnottex + +@macro copt {option} +@w{@code{--\option\}} +@end macro + +@c %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +@iftex +@tex +% If we're using pdfTeX in PDF-generating mode then include some +% document metadata. +\ifx\pdfoutput\undefined +\else + \ifx\pdfoutput\relax + \else + \ifcase\pdfoutput + \else + \pdfinfo { + /Title (mf2pt1) + /Subject (Produce PostScript Type 1 fonts from Metafont source) + /Author (Scott Pakin ) + /Keywords (PostScript Type 1 fonts, Metafont, MetaPost, FontForge) + } + \fi + \fi +\fi +@end tex +@end iftex + +@titlepage +@title mf2pt1 +@subtitle Produce PostScript @w{Type 1} fonts from Metafont source +@author Scott Pakin, @email{scott+mf@@pakin.org} + +@page + +@vskip 0pt plus 2filll + +This file documents @command{mf2pt1} version @value{VERSION}, dated +@value{DATE}. + +@vskip 0pt plus 1filll + +@insertcopying + +@contents + +@end titlepage + +@ifnottex +@node Top, Introduction, (dir), (dir) +@top mf2pt1 + +@command{mf2pt1} is a tool that lets font designers design PostScript +@w{Type 1} fonts using the @MF{} language. The same source file can be +used to produce both @w{Type 1} (@file{.pfb}) and bitmap (@file{.pk}) +fonts. +@end ifnottex + +@menu +* Introduction:: Introduction to mf2pt1 +* Usage:: How to use mf2pt1 +* Future Work:: Features I may one day add to mf2pt1 +* Acknowledgments:: People who helped with mf2pt1 +@end menu + + +@node Introduction, Usage, Top, Top +@chapter Introduction + +@MF{} is a high-level, mathematically oriented language for producing +fonts. The @MF{} interpreter produces device-dependent bitmaps, which +render well at the target resolution on the target device, but poorly +at other resolutions or on other devices. Adobe's PostScript @w{Type 1} +font format is the de facto font standard for printers these days. It +is a vector format, which implies that it scales better than bitmaps, +and it delegates the device- and resolution-dependent tweaking from +the font source to the target device's PostScript renderer. However, +@w{Type 1} fonts are extremely difficult to code by hand. Usually, one +uses a @acronym{WYSIWYG} program to design a @w{Type 1} font. @MF{}, with +its font-specific programming language, is an elegant alternative. A +font designer can write reusable subroutines for repeated features, +such as serifs and accents. He can define a font in terms of +arbitrary parameters, such as ``boldness'' or ``italicness'', making +it trivial to produce entire families of fonts from a single source +(hence the ``meta'' in the name ``@MF{}''). Ideally, we would like to +design a font using the @MF{} language, but produce PostScript @w{Type 1} +output instead of bitmaps. + +@command{mf2pt1} helps bridge the gap between @MF{} and @w{Type 1} fonts. +@command{mf2pt1} facilitates producing PostScript @w{Type 1} fonts from a +@MF{} source file. It is @emph{not}, as the name may imply, an +automatic converter of arbitrary @MF{} fonts to @w{Type 1} format. +@command{mf2pt1} imposes a number of restrictions on the @MF{} input. +If these restrictions are met, @command{mf2pt1} will produce valid +@w{Type 1} output. + +@menu +* Requirements:: Pre-installation checklist +* Installation:: How to install mf2pt1 +@end menu + + +@node Requirements, Installation, Introduction, Introduction +@section Requirements + +Before using @command{mf2pt1}, you will need to install the following +programs: + +@table @asis +@item Perl +@command{mf2pt1} is written in Perl. You will need a Perl interpreter +to run it. + +@item MetaPost +@command{mf2pt1} actually uses MetaPost, not @MF{}, to produce +PostScript output. Specifically, you will need the @command{mpost} +executable and the @file{mfplain.mp} base file. + +@item @w{Type 1} Utilities +Producing properly encoded @w{Type 1} fonts is tricky. +@command{mf2pt1} delegates the effort to the @w{Type 1} Utilities, +specifically, to the @command{t1asm} program within that suite. + +@item FontForge (optional) +FontForge is a @acronym{WYSIWYG}, but scriptable, @w{Type 1} +font-editing program. Although FontForge is not strictly required for +@command{mf2pt1} to produce a @w{Type 1} font, @command{mf2pt1} uses +FontForge when available to autohint the generated @w{Type 1} font, +thereby making it look better especially at lower resolutions. +@end table + +Perl is available from @uref{http://www.cpan.org, the Comprehensive +Perl Archive Network}; MetaPost and the @w{Type 1} utilities are +available from @uref{http://www.ctan.org, the Comprehensive @TeX{} +Archive Network}; and, FontForge is available from +@uref{http://fontforge.sourceforge.net/}. In addition, MetaPost's +home page is @uref{http://cm.bell-labs.com/who/hobby/MetaPost.html}, +and the @w{Type 1} utilities' home page is +@uref{http://www.lcdf.org/type/}. + +Besides being useful for autohinting fonts, FontForge enables a font +designer to hint fonts manually for additional fine-tuning and to +convert among a variety of font formats, such as PostScript, TrueType, +and @w{X Window} fonts. FontForge is strongly recommended as a +complement to @command{mf2pt1}. + + +@node Installation, , Requirements, Introduction +@section Installation + +To install @command{mf2pt1}, move the @file{mf2pt1} executable +someplace where your operating system can find it. If you're running +Microsoft Windows, you should rename the program to @file{mf2pt1.pl}, +so that Windows knows it's a Perl script. (Alternatively, if you have +@command{pl2bat}, use that to produce a @file{mf2pt1.bat} file, which +you can run as simply @file{mf2pt1}.) + +The next step is to produce a @file{mf2pt1.mem} file from the supplied +@file{mf2pt1.mp}. The command to do this differs from system to +system but is usually something like the following: + +@example +mpost -progname=mpost -ini mf2pt1 \\dump +@end example + +Move the resulting @file{mf2pt1.mem} file someplace where MetaPost can +find it. + +@sp 1 + +The @command{mf2pt1} documentation (what you're reading now) is written +in Texinfo and can therefore easily be converted to a variety of +formats: + +@table @asis +@item PDF (@file{mf2pt1.pdf}) +@example +texi2pdf mf2pt1.texi +@end example + +@item PostScript (@file{mf2pt1.ps}) +@example +texi2dvi mf2pt1.texi +dvips mf2pt1.dvi -o mf2pt1.ps +@end example + +@item HTML (@file{mf2pt1.html}) +@example +makeinfo --html mf2pt1.texi +@end example + +@item Info (@file{mf2pt1.info}) +@example +makeinfo mf2pt1.texi +@end example +@end table + +@noindent +N.B@. The @command{install-info} command is a convenient way to install +@file{mf2pt1.info} on your system. + +@sp 1 + +On Unix, you may also want to generate an @command{mf2pt1} man page. +The man page is embedded within the @file{mf2pt1} Perl script and can be +extracted with @command{pod2man}: + +@example +pod2man --center="User Commands" --date="@value{DATE}" \ + --release="v@value{VERSION}" mf2pt1 > mf2pt1.1 +@end example + +@noindent +You can then move @file{mf2pt1.1} into @file{/usr/man/man1} or any other +man page directory. Note that the @command{mf2pt1} man page is fairly +rudimentary. It is primarily a list of the command-line options +(@pxref{Font information}) and a pointer to the document that you're +reading now. + + +@node Usage, Future Work, Introduction, Top +@chapter Usage + +@command{mf2pt1} is fairly straightforward to use. To process a +@MF{} source file, merely specify the filename: + +@example +mf2pt1 myfont.mf +@end example + +@noindent +That simple command automatically performs all of the following +operations: + +@enumerate +@item +Read @file{myfont.mf}. + +@item +Use @command{mpost} to convert each character to a separate +Encapsulated PostScript (@acronym{EPS}) file named +@file{myfont.@var{num}}. + +@item +Process and merge the @acronym{EPS} files into a single +``disassembled'' @w{Type 1} font called @file{myfont.pt1}. + +@item +Run @command{t1asm} from the @w{Type 1} Utilities to convert the +disassembled font into a true, binary @w{Type 1} font called +@file{myfont.pfb}. + +@item +Invoke @command{fontforge} to apply rendering hints to +@file{myfont.pfb} and to attempt to remove overlapping paths. +@end enumerate + +The external programs launched by @command{mf2pt1}---@command{mpost}, +@command{t1asm}, and @command{fontforge}---can be overridden by +setting the eponymous, uppercase environment variable. For example, +invoking FontForge's predecessor, PfaEdit, instead of FontForge is +simply a matter of setting the @samp{FONTFORGE} environment variable +to @samp{pfaedit} before invoking @command{mf2pt1}. As a corollary, +you can inhibit an @command{mf2pt1} external program from running by +setting the corresponding environment variable to the name of a +nonexistent program. + +@menu +* Restrictions:: Restrictions imposed on the font source code +* Font information:: Specifying PostScript font characteristics +* Additional command-line options:: Options unrelated to font characteristics +* Custom font encodings:: Altering the mapping from character name to number +* Restoring mfplain defaults:: Using the original (un)filldraw and pencircle +@end menu + + +@node Restrictions, Font information, Usage, Usage +@section Restrictions + +If @command{mf2pt1} sounds too good to be true, it is---somewhat. +@command{mf2pt1} is not a general-purpose @MF{}-to-@w{Type 1} +converter. Rather, it can convert only certain @MF{} constructs. +This is not a showstopper for new fonts designed with @command{mf2pt1} +in mind, but it is unlikely that @command{mf2pt1} will work on an +arbitrary @MF{} source file. + +@command{mf2pt1}'s biggest restriction is that each glyph must be +drawn entirely from closed paths, using @MF{}'s @strong{fill} and +@strong{unfill} commands. (@command{mf2pt1} has limited support for +@strong{draw} and @strong{undraw}, but their use is currently +discouraged. @strong{filldraw} and @strong{unfilldraw} issue a +warning message and invoke @strong{draw} and @strong{undraw}, +respectively.) The @w{Type 1} format requires that these paths be +nonoverlapping. The following are some of the alternatives for +removing path overlaps: + +@enumerate +@item +Install FontForge. As part of its final step in producing a @w{Type +1} font, @command{mf2pt1} instructs FontForge to replace overlapping +paths with nonoverlapping paths. + +@item +Remove overlaps using @MF{} code within the font program itself. A +@file{.zip} file attachment to +@uref{http://tug.org/mailman/htdig/metapost/2005-January/000080.html, +a @w{6 January} 2005 article} by +@iftex +@tex +Bogus\l{}aw +@end tex +@end iftex +@ifnottex +Boguslaw +@end ifnottex +Jackowski on the MetaPost mailing list (subject: ``Re: all +intersections between two paths'') includes a MetaPost library which +assists with that task. The library provides a @strong{find_outlines} +command which can be used to define a path as the union of two other +paths. A number of MetaPost example programs are also included in the +@file{.zip} file. + +@item +Design your fonts from the beginning without using overlapping paths. +@end enumerate + +A secondary restriction is that @command{mf2pt1} redefines a number of +Plain @MF{} commands, such as @strong{beginchar}, @strong{fill}, and +@strong{unfill}. @MF{} font programs which redefine or bypass these +(using @MF{} primitives) will not be convertible with +@command{mf2pt1}. + +A far less severe restriction is due to @command{mf2pt1}'s utilizing +MetaPost's @MF{} interface instead of @MF{} itself. The implication +is that commands not defined by MetaPost's @file{mfplain.mp} cannot be +handled by @command{mf2pt1}, either. Very few fonts will have a +problem with this restriction but see the MetaPost manual for more +information. + + +@node Font information, Additional command-line options, Restrictions, Usage +@section Specifying font information + +@iftex +@tex +@leavevmode +@end tex +@end iftex +@MF{} fonts normally specify a set of @strong{fontdimen}s which +provide information about a particular font that cannot otherwise be +inferred. These include features such as the font's x-height, quad +width, interword stretchability and shrinkability, and other design +characteristics that @TeX{} makes use of. PostScript fonts utilize a +largely different set of font parameters, such as the underline +position and thickness, font family name, and copyright notice. +@command{mf2pt1} provides @MF{} commands to define the PostScript font +parameters in the generated @w{Type 1} font. These parameters should +appear in the @MF{} source file as follows: + +@display +@b{if} known @i{ps_output}: + @dots{} +@b{fi} +@end display + +@noindent +@code{ps_output} is defined by @command{mf2pt1} but not by Plain +@MF{}. Checking if it is known is the recommended way to determine if +the font is being built under @command{mf2pt1}. + +@ifnottex +@menu +* Parameters:: Font-information commands available to Metafont +* Command-line equivalents:: Specifying font features on the command line +* Default values:: Types and default values of each parameter +* Parameter example:: Metafont example which specifies all parameters +@end menu + + +@node Parameters, Command-line equivalents, Font information, Font information +@subsection Parameters +@end ifnottex + +The following list presents all of the font-information commands +provided by @command{mf2pt1} and describes what each command means. +Commands marked with an asterisk are also defined by Plain @MF{} and +therefore do not need to be enveloped within a test for +@code{ps_output}. + +@table @strong +@item font_coding_scheme +The mapping between character numbers and PostScript names. If this +is the name of a file, @command{mf2pt1} expects it to contain +PostScript code defining a font-encoding vector. @xref{Custom font +encodings}, for an example of such a file. If +@strong{font_coding_scheme} is not the name of a file, +@command{mf2pt1} expects it to be one of the literal strings +@code{standard} (Adobe standard encoding), @code{isolatin1} (ISO Latin +1 encoding), @code{ot1} (@TeX{} 7-bit encoding), @code{t1} (@TeX{} +8-bit encoding), or @code{asis} (encoding integrated with the +character programs using the @strong{glyph_name} command as described +in @ref{Custom font encodings}). Anything else will generate a +warning message and cause @command{mf2pt1} to use @code{standard} +instead. + +@item font_comment +A textual comment that will appear within the generated font. This is +often used for copyright notices. + +@item font_family +The family that this font belongs to. For example, ``Utopia Bold +Italic'' belongs to the @code{Utopia} family. + +@item font_fixed_pitch +Whether the font is monospaced (if @strong{true}) or or proportionally +spaced (if @strong{false}). + +@item font_identifier (*) +The full name of the font, e.g., @code{Utopia Bold Italic}. + +@item font_name +The symbolic font name, used to load the font from a PostScript +document. Spaces are forbidden. Generally, the font name is of the +form @code{@var{family}-@var{modifiers}}. For example, the font name +of Utopia Bold Italic would be @code{Utopia-BoldItalic}. + +@item font_size (*) +The font design size. This is specified in ``sharped'' units within +@MF{} code or as a point size on the command line. + +@item font_slant (*) +When specified with @strong{font_slant}, the amount of slant per +point. When specified with @copt{italicangle}, the angle in +counterclockwise degrees from the vertical (i.e., zero for an upright +font, negative for a right-slanting italic font). + +@item font_underline_position +The vertical position at which an underline should lie, specified in +``sharped'' units within @MF{} code or as a number of points on the +command line. + +@item font_underline_thickness +The thickness of an underline, specified in ``sharped'' units within +@MF{} code or as a number of points on the command line. + +@item font_unique_id +The unique ID for this font. The ID should be between 0 and +16,777,215. If not specified, @command{mf2pt1} will choose an ID at +random from the ``open'' range, 4,000,000-4,999,999. All IDs not in +that range are allocated by contacting Adobe's UniqueID Coordinator. +(I don't believe a fee is involved, but I don't know for sure.) + +@item font_version +The version number of the font. This should be of the form +@code{@var{MMM}.@var{mmm}}, where @var{MMM} is the major version +number and @var{mmm} is the minor version number. + +@item font_weight +The font weight. For example, the font weight of Utopia Bold Italic +is @code{Bold}. +@end table + + +@ifnottex +@node Command-line equivalents, Default values, Parameters, Font information +@subsection Command-line equivalents +@end ifnottex + +Each of the +@iftex +preceding font-information commands +@end iftex +@ifnottex +font-information commands listed in @ref{Parameters} +@end ifnottex +has a command-line equivalent. Their use is discouraged but they are +listed here for completeness: + +@multitable {@strong{font_underline_thickness}} {@copt{fontversion}} +@item +@strong{font_coding_scheme} +@tab @copt{encoding} + +@item +@strong{font_comment} +@tab @copt{comment} + +@item +@strong{font_family} +@tab @copt{family} + +@item +@strong{font_fixed_pitch} +@tab @copt{fixedpitch} + +@item +@strong{font_identifier} +@tab @copt{fullname} + +@item +@strong{font_name} +@tab @copt{name} + +@item +@strong{font_size} +@tab @copt{designsize} + +@item +@strong{font_slant} +@tab @copt{italicangle} + +@item +@strong{font_underline_position} +@tab @copt{underpos} + +@item +@strong{font_underline_thickness} +@tab @copt{underthick} + +@item +@strong{font_unique_id} +@tab @copt{uniqueid} + +@item +@strong{font_version} +@tab @copt{fontversion} + +@item +@strong{font_weight} +@tab @copt{weight} +@end multitable + +A special case is @copt{fixedpitch} which does not take an argument. +Rather, you should use @copt{fixedpitch} as the equivalent of +@samp{font_fixed_pitch true} and @copt{nofixedpitch} as the equivalent +of @samp{font_fixed_pitch false}. + + +@ifnottex +@node Default values, Parameter example, Command-line equivalents, Font information +@subsection Default values +@end ifnottex + +The next table lists the @MF{} type and default value of each of the +parameters listed in +@ifnottex +@ref{Parameters}. +@end ifnottex +@ifnotinfo +the previous table. +@end ifnotinfo + +@multitable {@strong{font_underline_thickness}} {@strong{numeric}} {MMMMMMMMMMMMMMMMMMMMMMMMM} +@item @strong{font_coding_scheme} +@tab @strong{string} +@tab @code{"standard"} + +@item @strong{font_comment} +@tab @strong{string} +@tab @code{"Font converted to @w{Type 1} by mf2pt1, written by Scott Pakin."} + +@item @strong{font_family} +@tab @strong{string} +@tab (The value of @strong{font_identifier}) + +@item @strong{font_fixed_pitch} +@tab @strong{boolean} +@tab @strong{false} + +@item @strong{font_identifier} +@tab @strong{string} +@tab (The input filename, minus @file{.mf}) + +@item @strong{font_name} +@tab @strong{string} +@tab (The value of @strong{font_family}, plus an underscore, plus the + value of @strong{font_weight}, with all spaces removed) + +@item @strong{font_size} +@tab @strong{numeric} +@tab (Must be specified or @command{mf2pt1} will abort with an error message) + +@item @strong{font_slant} +@tab @strong{numeric} +@tab 0 + +@item @strong{font_underline_position} +@tab @strong{numeric} +@tab -1 + +@item @strong{font_underline_thickness} +@tab @strong{numeric} +@tab 0.5 + +@item @strong{font_unique_id} +@tab @strong{string} +@tab (Randomly generated in the range 4000000-4999999) + +@item @strong{font_version} +@tab @strong{string} +@tab @code{"001.000"} + +@item @strong{font_weight} +@tab @strong{string} +@tab @code{"Medium"} +@end multitable + +@sp 1 + + +@ifnottex +@node Parameter example, , Default values, Font information +@subsection Parameter example +@end ifnottex + +As an example, the following @MF{} code shows the usage of all of the +parameters that @command{mf2pt1} accepts: + +@noindent +@b{if} known @i{ps_output}: +@multitable {@b{if}} {@b{font_underline_thickness}} {@t{"Copyright (C) 2014 Scott Pakin.";}} +@item @tab @b{font_coding_scheme} @tab @t{"ot1"}; +@item @tab @b{font_comment} @tab @t{"Copyright (C) 2014 Scott Pakin."}; +@item @tab @b{font_family} @tab @t{"Kerplotz"}; +@item @tab @b{font_fixed_pitch} @tab @b{false}; +@item @tab @b{font_identifier} @tab @t{"Kerplotz Light Oblique"}; +@item @tab @b{font_name} @tab @t{"Kerplotz-LightOblique"}; +@item @tab @b{font_size} @tab 10@i{pt}#; @ @ @ @ @ % Important to include this. +@item @tab @b{font_slant} @tab 1/6; +@item @tab @b{font_underline_position} @tab -1@i{pt}#; +@item @tab @b{font_underline_thickness} @tab 1/2@i{pt}#; +@item @tab @b{font_unique_id} @tab @t{"4112233"}; @ @ @ @ @ % Better to omit this. +@item @tab @b{font_version} @tab @t{"002.005"}; +@item @tab @b{font_weight} @tab @t{"Light"}; +@end multitable +@noindent +@b{fi} + +@noindent +In the above, the @strong{font_fixed_pitch} call could have been +omitted, as it defaults to @strong{false}. Also, unless you've +requested a unique ID from Adobe, it's generally better not to assign +@strong{font_unique_id}; let @command{mf2pt1} choose a random value +itself. + +The same parameters can also be specified on the command line as +follows: + +@example +mf2pt1 --encoding=ot1 --comment="Copyright (C) 2014 Scott Pakin." + --family=Kerplotz --nofixedpitch --fullname="Kerplotz Light Oblique" + --name=Kerplotz-LightOblique --designsize=10 --italicangle=-9.5 + --underpos=-100 --underthick=50 --uniqueid=4112233 --version=002.005 + --weight=Light kerplotz.mf +@end example + +@noindent +Note that a @MF{} font slant of 1/6 is equal to a PostScript italic +angle of approximately -9.5. The conversion formula is +@iftex +@tex +$s = -@tan @theta$, in which $s$ is the slant and $@theta$ is the +italic angle. +@end tex +@end iftex +@ifnottex +slant = -tan(angle). +@end ifnottex +In addition, the underline position and thickness must be multiplied by +1000/@strong{font_size} to convert from the @MF{} units that are used +within the @file{.mf} file to the PostScript units that are used on the +command line. + + +@node Additional command-line options, Custom font encodings, Font information, Usage +@section Additional command-line options + +In addition to the command-line options for setting font parameters +that were presented in +@iftex +@ref{Font information}, +@end iftex +@ifnottex +@ref{Parameters}, +@end ifnottex +@command{mf2pt1} supports a @copt{rounding} option. While +@command{mf2pt1} normally rounds all font coordinates to the nearest +integer, @copt{rounding} increases coordinate precision by +instructing @command{mf2pt1} to round instead to the nearest multiple +of a given fractional number. For example, @samp{--rounding=0.25} +rounds the coordinate @math{(7.4, 10.3)} to @math{(7.5, 10.25)} while +it would otherwise be rounded to the less-precise @math{(7, 10)}. + +Large glyphs can be problematic in MetaPost and therefore in +@command{mf2pt1}. Unlike @MF{}, MetaPost does not honor @samp{mag} +for magnifying dimensions. Rather, the number of PostScript +(a.k.a. ``big'') points per pixel---@samp{bpppix}---is hardwired @w{to +0.02} and all other dimensions (@samp{mm}, @samp{in}, @samp{pt}, +etc.@:) are expressed in terms of that. Consequently, glyphs that +multiply a large number of font units by a dimension are likely to +exceed 4096, the largest value that MetaPost can represent in its +fixed-point format. If numerical overflow becomes a problem you can +use the @copt{bpppix} option to @command{mf2pt1} to change the value +of @samp{bpppix}. For example, specifying @samp{--bpppix=0.2} enables +a tenfold increase in maximum glyph size (with a corresponding +decrease in precision). + +After generating a @w{Type 1} font, @command{mf2pt1} runs it through +FontForge to add hinting information, remove overlaps, and otherwise +clean up the generated font. The @copt{ffscript} option specifies +the filename of a FontForge script to use instead of the default +script, which is listed below: + +@example +Open($1); +SelectAll(); +RemoveOverlap(); +AddExtrema(); +Simplify(0, 2); +CorrectDirection(); +Simplify(0, 2); +RoundToInt(); +AutoHint(); +Generate($1); +Quit(0); +@end example + +@noindent +See the FontForge documentation for an explanation of each of those +commands and a description of other commands made available to +FontForge scripts. @command{mf2pt1} runs the script with one argument +(@code{$1}), which is the name of the generated @file{.pfb} file. + +@command{mf2pt1} also supports a @copt{help} option which summarizes +all of the program's command-line options. + +@c Improve formatting by keeping the large cartouche on the same +@c page as the text that introduces it. +@page + +@node Custom font encodings, Restoring mfplain defaults, Additional command-line options, Usage +@section Custom font encodings + +@iftex +@ref{Font information}, +@end iftex +@ifnottex +@ref{Parameters}, +@end ifnottex +lists the font encodings currently supported by @command{mf2pt1} and +mentions that an alternate encoding can be specified by providing the +name of an encoding file. To elaborate, the following example +represents the contents of an encoding file which defines a---largely +useless nowadays---@acronym{EBCDIC} font encoding: + +@cartouche +@quotation +@code{% Sample encoding vector: @acronym{EBCDIC}@* +@* +% The encoding vector must have a name and be defined as a PostScript array.@* +/ebcdic_encoding [@* +/_a0 /_a1 /_a2 /_a3 /_a4 /_a5 /_a6 /_a7 /_a8 /_a9 /_a10 /_a11 /_a12 +/_a13 /_a14 /_a15 /_a16 /_a17 /_a18 /_a19 /_a20 /_a21 /_a22 /_a23 +/_a24 /_a25 /_a26 /_a27 /_a28 /_a29 /_a30 /_a31 /_a32 /_a33 /_a34 +/_a35 /_a36 /_a37 /_a38 /_a39 /_a40 /_a41 /_a42 /_a43 /_a44 /_a45 +/_a46 /_a47 /_a48 /_a49 /_a50 /_a51 /_a52 /_a53 /_a54 /_a55 /_a56 +/_a57 /_a58 /_a59 /_a60 /_a61 /_a62 /_a63 /space /_a65 /_a66 /_a67 +/_a68 /_a69 /_a70 /_a71 /_a72 /_a73 /bracketleft /period /less +/parenleft /plus /exclam /ampersand /_a81 /_a82 /_a83 /_a84 /_a85 +/_a86 /_a87 /_a88 /_a89 /bracketright /dollar /asterisk /parenright +/semicolon /asciicircum /hyphen /slash /_a98 /_a99 /_a100 /_a101 +/_a102 /_a103 /_a104 /_a105 /bar /comma /percent /underscore /greater +/question /_a112 /_a113 /_a114 /_a115 /_a116 /_a117 /_a118 /_a119 +/_a120 /_a121 /colon /numbersign /at /quoteright /equal /quotedbl +/_a128 /a /b /c /d /e /f /g /h /i /_a138 /_a139 /_a140 /_a141 /_a142 +/_a143 /_a144 /j /k /l /m /n /o /p /q /r /_a154 /_a155 /_a156 /_a157 +/_a158 /_a159 /_a160 /asciitilde /s /t /u /v /w /x /y /z /_a170 /_a171 +/_a172 /_a173 /_a174 /_a175 /_a176 /_a177 /_a178 /_a179 /_a180 /_a181 +/_a182 /_a183 /_a184 /quoteleft /_a186 /_a187 /_a188 /_a189 /_a190 +/_a191 /braceleft /A /B /C /D /E /F /G /H /I /_a202 /_a203 /_a204 +/_a205 /_a206 /_a207 /braceright /J /K /L /M /N /O /P /Q /R /_a218 +/_a219 /_a220 /_a221 /_a222 /_a223 /backslash /_a225 /S /T /U /V /W /X +/Y /Z /_a234 /_a235 /_a236 /_a237 /_a238 /_a239 /zero /one /two /three +/four /five /six /seven /eight /nine /_a250 /_a251 /_a252 /_a253 +/_a254 /_a255@* +% Don't forget to end the array.@* +] def} +@end quotation +@end cartouche + +All entries in the encoding vector are PostScript ``names'' and +therefore must be prefixed with a slash. Unnamed characters such as +control characters are commonly named @samp{_a@var{number}}, where +@var{number} is the decimal offset into the character table. +Undefined characters are indicated by @samp{.notdef}. In the +@acronym{EBCDIC} example, the character at @w{position 0} in the font +will be named @samp{a0}; the character at @w{position 1} will be named +@samp{a1}; the character at @w{position 74} will be named +@samp{bracketleft}; the character at @w{position 129} will be named +@samp{a}; and so forth. + +Individual characters can be mapped to an encoding either numerically +or by executing a @strong{glyph_name} command within a character +definition. For example, the following code overrides the character +position passed to @strong{beginchar} @w{(i.e., 123)} with whatever +character position the current encoding has designated for the +@samp{ohungarumlaut} glyph: + +@display +@b{beginchar} (123, cap_height#-1/2pt#, cap_height#, 0); + @b{if} known @i{ps_output}: + @i{glyph_name} @t{"ohungarumlaut"}; + @b{fi} + @dots{} +@b{endchar}; +@end display + + +@node Restoring mfplain defaults, , Custom font encodings, Usage +@section Restoring @file{mfplain} defaults + +@command{mf2pt1} normally redefines @strong{filldraw} as @strong{fill} +and @strong{unfilldraw} and @strong{unfill} because @w{Type 1} fonts +don't allow overlapping curves. Similarly, @command{mf2pt1} redefines +@strong{pencircle} as a 20-gon to coerce MetaPost into drawing it +using a filled instead of a stroked PostScript path. + +If you know you'll be postprocessing your fonts using FontForge, which +can automatically convert overlapping paths to nonoverlapping paths, +then you can restore the original @file{mfplain.mp} definitions of +@strong{filldraw}, @strong{unfilldraw}, and @strong{pencircle} as +follows: + +@display +@b{if} known @i{ps_output}: + @b{pencircle} := @i{mfplain_pencircle}; + @b{let filldraw} := @i{mfplain_filldraw}; + @b{let unfilldraw} := @i{mfplain_unfilldraw}; +@b{fi} +@end display + + +@node Future Work, Acknowledgments, Usage, Top +@chapter Future Work + +One avenue for future work is to enable the font designer to specify +@w{Type 1} font hints directly in the @MF{} font program. Hinting is +a way for a font designer to specify how a font should be rendered at +low resolutions, for example, at typical monitor resolutions. In +@MF{}, this is done by controlling the way that points are mapped to +pixel locations, using commands such as +@strong{define_corrected_pixels}, @strong{define_blacker_pixels}, and +@strong{lowres_fix}. @w{Type 1} fonts are hinted in a completely +different manner. @w{Type 1} hints distinguish key character +features, such as stems and dots, from decorations which can be +discarded at low resolutions. The PostScript interpreter uses that +information to determine how to map points to pixels. Although +@command{mf2pt1} employs FontForge to autohint the fonts it generates, +the approach is mechanical and unlikely to hint as well as a human can +do manually. It would be convenient for @command{mf2pt1} one day to +provide @MF{} commands for @strong{hstem}, @strong{vstem}, +@strong{dotsection}, and the other @w{Type 1} hints. That way, hints +will no longer need to be re-added manually every time +@command{mf2pt1} regenerates a @w{Type 1} font. + +Another future addition to @command{mf2pt1} is the addition of more +font encodings. The following are the encodings that @command{mf2pt1} +will most likely accept: + +@table @code +@item TeXMathItalicEncoding +Upper- and lowercase Greek and Latin letters, old-style digits, and a +few symbols and accents. + +@item TeXMathSymbolEncoding +A variety of symbols, as well as calligraphic Latin majuscules. + +@item TeXMathExtensionEncoding +Variable-sized symbols, such as braces, integrals, and radicals. + +@item AdobeExpert +Small caps, currency symbols, old-style digits, and various superior and +inferior letters and digits. +@end table + + +@node Acknowledgments, , Future Work, Top +@unnumbered Acknowledgments + +Many thanks are owed to Werner Lemberg for writing the code underlying +the @copt{rounding} option; for introducing the @strong{glyph_name} +command and @code{asis} encoding vector; for providing the default +FontForge script listed in @ref{Additional command-line options}; for +fixing some code-generation bugs in @command{mf2pt1}; for finding a +more robust way to dump @file{mf2pt1.mem}; for directing me to the +overlap-removal code mentioned in @ref{Restrictions}; for supplying +the @emph{crossproduct}, @emph{makeline}, and @emph{is_clockwise} +functions used by @file{mf2pt1.mp}; for proposing the @copt{bpppix} +command-line option; and, for suggesting various features and +improvements to @command{mf2pt1}. Thanks also go to Werner Lemberg +and +@iftex +@tex +Bogus\l{}aw +@end tex +@end iftex +@ifnottex +Boguslaw +@end ifnottex +Jackowski for updating the @strong{is_clockwise} function in +@file{mf2pt1.mp} to work around a bug in MetaPost which relates to the +@strong{turningnumber} command. Finally, thanks go to Ralf Stubner +for providing the T1 encoding vector and for pointing out a typo in +the generated font programs; to Michael Zedler for alerting me to +problems with @copt{encoding} and suggesting I modify that option to +accept PostScript @file{.enc} files; and to Michael Ummels for fixing +a couple of bugs that made character widths in the generated fonts +slightly too large. + +@bye -- cgit v1.2.3