3

In "The Concept of a Metafont" Donald E. Knuth explores in a visual way the possibilities of parametric variations. But I have some questions:

  • Did he used TeX to typeset the article?
  • Does TeX allows continuous variation of parameters? Sometimes, even in the same paragraph the changes letter to letter are visible. How is the communication between Metafont and TeX processed in this cases?

Thank you

Henri Menke
  • 109,596
  • 1
    LuaTeX has support for MetaPost fonts (at least in ConTeXt). See http://www.pragma-ade.nl/general/manuals/fonts-mkiv.pdf (search for "punknova") – Henri Menke Aug 29 '19 at 08:35
  • Thank you, Henri Menke. But, this example has to do with choosing alternates. It is the same process like in Knuth's article? In page 15 he has one paragraph with continuous variation from start to end. Every single letter is different. How does he do this? Does TeX allows this? How? (probably its a good ideia to say that I'm not familiarized with code language) – Ana Fernandes Aug 29 '19 at 09:19
  • 1
    Welcome! Yes, Knuth used TeX to typeset the article. If you mean the “The LORD is my shepherd…” example on page 15, it is done as an insert, i.e. similar to inserting a figure. Of course, this figure was itself done (separately) with TeX (superficially), but with some trickery like creating a special “font” just for that figure, in which the kth character in the font was the kth character desired in the output. If you know exactly what you want, you can do anything. :-) – ShreevatsaR Aug 29 '19 at 10:00
  • Thank you, @ShreevatsaR ! Tell me just two more things. The continuous variations in the font in that example were created with Metafont and then composed in TeX? Or TeX allows to do that kind of variations directly? And, Metafont can "communicate directly" with TeX, or Metafont needs to generate every font (roman, bold, slanted, italic) and just then TeX can use it (i.e. as if it were a font library in common typesetting systems like indesign)? – Ana Fernandes Aug 29 '19 at 11:14
  • 1
    As far as I know, there isn't any generally available version of TeX that is closely coupled with TeX to make such interaction available. There is an implementation of LuaTeX that has Metapost as an available library, but that's not quite the same thing. There was a paper at TUG 2019 that included a demonstration of an interactive TeX/MF hybrid that might make what you describe possible; however, that produces output with bitmap fonts, so would not be useful unless the image will always appear on a surface matching the resolution at which it was created. – barbara beeton Aug 29 '19 at 13:26
  • @barbarabeeton thank you. But I'm sill not understanding if in that example of "The LORD is my shepherd..." if it is TeX or Metafont that makes those variations in every single letter of the composition. – Ana Fernandes Aug 29 '19 at 15:47
  • As @ShreevatsaR noted, Metafont was used to create a custom collection of fonts, which were then used by TeX to prepare the example. I don't know whether these fonts are generally available (I expect not); they wouldn't be very easy to use in a "routine" setup, but would require a carefully crafted input strategy. – barbara beeton Aug 29 '19 at 16:30
  • 1
    For Metafont, a font is just a collection of (up to) 256 pictures (glyphs). (So think something like “Computer Modern Italic at 8pt”, not “Computer Modern”.) In the example, Knuth created a “font” whose 256 characters were “T (with certain params)”, ”h (with certain params)”, “e (with certain params)”, “L (with certain params)” etc. (Switching to a new font after every 256 slots.) For example, the 3 “e”s in the first line are simply 3 different glyphs in the same font. But TeX can directly induce the variations, as (in TeX Live etc) if a font is missing Metafont will be invoked to create it. – ShreevatsaR Aug 29 '19 at 16:39
  • Thank you all for the answers! :) – Ana Fernandes Aug 29 '19 at 16:59
  • @ShreevatsaR does he need to export the "font" from Metafont to use in TeX? Or can he use directly? – Ana Fernandes Aug 29 '19 at 17:12

1 Answers1

6

Knuth's The Concept of a Meta-Font (abstract, PDF) is not just a paper but a performance, as he uses the visual appearance of each paragraph itself to illustrate the ideas in it. Between two particular paragraphs is a separate page containing a setting of Psalm 23, which also marks a transition in the paper itself from one font to another:

concept of a metafont, psalm 23

Here, the characters progressively get larger (even within the same line) in width (“em width”) and height (“x-height”) while retaining the same “h-height” (ascender height I think).

The paper was of course typeset with TeX, including this insert.

To show how it was or could be done, while keeping it simple (for my own sake, being not very familiar with Metafont), I'll use a particularly simple font containing just the numerals 0–9, from this question.

No tricks

Just to repeat the example from the other question (just being included here to make it easier to understand the later examples): you can put the following definition of the font in a file called postal.mf:

leftgap := 0.1;
rightgap := 0.1;
penthickness := 0.08;
midlineheight := 0.5;
toplineheight := 1;
width# := 9pt#;
height# := 10pt#;

mode_setup;
def begincchar(expr c) =
  beginchar(c, width#, height#, 0);
    t := toplineheight * h;
    m := midlineheight * h;
    a := leftgap * w;  b := w - rightgap * w;
    z1=(a,t); z2=(b,t);
    z3=(a,m); z4=(b,m);
    z5=(a,0); z6=(b,0);
    pickup pencircle scaled (penthickness * w);
    penlabels(1,2,3,4,5,6);
enddef;

def drawzero  = draw z2--z1--z5--z6--cycle; endchar; enddef;
def drawone   = draw z3--z2--z6; endchar; enddef;
def drawtwo   = draw z1--z2--z4--z5--z6; endchar; enddef;
def drawthree = draw z1--z2--z3--z4--z5; endchar; enddef;
def drawfour  = draw z1--z3--z4; draw z2--z6; endchar; enddef;
def drawfive  = draw z2--z1--z3--z4--z6--z5; endchar; enddef;
def drawsix   = draw z2--z3--z5--z6--z4--z3; endchar; enddef;
def drawseven = draw z1--z2--z3--z5; endchar; enddef;
def draweight = draw z2--z1--z5--z6--cycle; draw z3--z4; endchar; enddef;
def drawnine  = draw z4--z3--z1--z2--z4--z5; endchar; enddef;

begincchar("0"); drawzero;
begincchar("1"); drawone;
begincchar("2"); drawtwo;
begincchar("3"); drawthree;
begincchar("4"); drawfour;
begincchar("5"); drawfive;
begincchar("6"); drawsix;
begincchar("7"); drawseven;
begincchar("8"); draweight;
begincchar("9"); drawnine;
end

and then use the font in your .tex file:

\font\postalfont=postal
$\pi$ is roughly three point {\postalfont 14159265} in value.
\bye

to get:

simple case

Manually defining the font

For the "The LORD is my shepherd" example, Knuth defined a special “font” whose 256 characters were “T (with certain params)”, ”h (with certain params)”, “e (with certain params)”, “L (with certain params)” and so on. (Switching to a new font after every 256 slots.) For example, the 3 “e”s in the first line are simply 3 different glyphs in the same font. Here's an example of something similar with our postal-digits font. This time, after deleting anything leftover from last time (postal.*), put the following in your postal.mf font:

leftgap := 0.1;
rightgap := 0.1;
penthickness := 0.08;
midlineheight := 0.5;
toplineheight := 1;
width# := 9pt#;
height# := 10pt#;
scale := 1;

mode_setup;
def begincchar(expr c) =
  beginchar(c, width# * scale, height# * scale, 0);
    t := toplineheight * h;
    m := midlineheight * h;
    a := leftgap * w;  b := w - rightgap * w;
    z1=(a,t); z2=(b,t);
    z3=(a,m); z4=(b,m);
    z5=(a,0); z6=(b,0);
    pickup pencircle scaled (penthickness * w / scale);
    penlabels(1,2,3,4,5,6);
enddef;

def drawzero  = draw z2--z1--z5--z6--cycle; endchar; enddef;
def drawone   = draw z3--z2--z6; endchar; enddef;
def drawtwo   = draw z1--z2--z4--z5--z6; endchar; enddef;
def drawthree = draw z1--z2--z3--z4--z5; endchar; enddef;
def drawfour  = draw z1--z3--z4; draw z2--z6; endchar; enddef;
def drawfive  = draw z2--z1--z3--z4--z6--z5; endchar; enddef;
def drawsix   = draw z2--z3--z5--z6--z4--z3; endchar; enddef;
def drawseven = draw z1--z2--z3--z5; endchar; enddef;
def draweight = draw z2--z1--z5--z6--cycle; draw z3--z4; endchar; enddef;
def drawnine  = draw z4--z3--z1--z2--z4--z5; endchar; enddef;

begincchar(0); "1"; scale := scale*0.95; drawone;
begincchar(1); "4"; scale := scale*0.95; drawfour;
begincchar(2); "1"; scale := scale*0.95; drawone;
begincchar(3); "5"; scale := scale*0.95; drawfive;
begincchar(4); "9"; scale := scale*0.95; drawnine;
begincchar(5); "2"; scale := scale*0.95; drawtwo;
begincchar(6); "6"; scale := scale*0.95; drawsix;
begincchar(7); "5"; scale := scale*0.95; drawfive;
begincchar(8); "3"; scale := scale*0.95; drawthree;
begincchar(9); "5"; scale := scale*0.95; drawfive;
begincchar(10);"8"; scale := scale*0.95; draweight;
begincchar(11);"9"; scale := scale*0.95; drawnine;
begincchar(12);"7"; scale := scale*0.95; drawseven;
begincchar(13);"9"; scale := scale*0.95; drawnine;
begincchar(14);"3"; scale := scale*0.95; drawthree;
end

Observe the last part of the above, where we modify scale before drawing the characters: the earlier font put a glyph for the numeral “1” at the slot corresponding to the ASCII code for “1” (namely, position 49 in the font), as normal fonts do. In this case, instead we've defined the font to have a certain kind of "1" as the glyph in its earliest slot (position 0), then the next slot (position 1) has a certain kind of "4", then the next slot (position 2) has a different kind of "1", and so on — we've defined the characters based on what we want in the output.

Starting with the .mf file, you can first run Metafont on it (with the right arguments, which I can't figure out right now) to generate the glyphs and font metrics (.tfm file), then run the following .tex file that uses it:

\font\postalfont=postal
$\pi$ is roughly three point {\postalfont \char0 \char1 \char2 \char3 \char4 \char5 \char6 \char7 \char8 \char9 \char10 \char11 \char12 \char13 \char14} in value.
\bye

scaling, done manually

Here in the .tex file we manually wrote out "\char0 \char1..." etc to be explicit, but of course TeX has macros for making it easier. Not only that, but modern TeX distributions will automatically invoke Metafont if a font is not found. Also, TeX can write to files. Using all that, we can get the following.

Automatic, single-file solution

Delete anything leftover from earlier, and create a single .tex file containing:

\newwrite\fontfile
\immediate\openout\fontfile=postal.mf
\catcode`\^^M=\active \def^^M{^^J} \catcode`\#=12 \immediate\write\fontfile{
leftgap := 0.1;
rightgap := 0.1;
penthickness := 0.08;
midlineheight := 0.5;
toplineheight := 1;
width# := 9pt#;
height# := 10pt#;
scale := 1;

mode_setup;
def begincchar(expr c) =
  beginchar(c, width# * scale, height# * scale, 0);
    t := toplineheight * h;
    m := midlineheight * h;
    a := leftgap * w;  b := w - rightgap * w;
    z1=(a,t); z2=(b,t);
    z3=(a,m); z4=(b,m);
    z5=(a,0); z6=(b,0);
    pickup pencircle scaled (penthickness * w / scale);
    penlabels(1,2,3,4,5,6);
enddef;

def drawzero  = draw z2--z1--z5--z6--cycle; endchar; enddef;
def drawone   = draw z3--z2--z6; endchar; enddef;
def drawtwo   = draw z1--z2--z4--z5--z6; endchar; enddef;
def drawthree = draw z1--z2--z3--z4--z5; endchar; enddef;
def drawfour  = draw z1--z3--z4; draw z2--z6; endchar; enddef;
def drawfive  = draw z2--z1--z3--z4--z6--z5; endchar; enddef;
def drawsix   = draw z2--z3--z5--z6--z4--z3; endchar; enddef;
def drawseven = draw z1--z2--z3--z5; endchar; enddef;
def draweight = draw z2--z1--z5--z6--cycle; draw z3--z4; endchar; enddef;
def drawnine  = draw z4--z3--z1--z2--z4--z5; endchar; enddef;
} \catcode`\^^M=5 \catcode`\#=6

\newcount\n
\n=0
\newcount\m
\m=0

\def\name#1{%
  \ifcase#1
    zero
    \or one%
    \or two%
    \or three%
    \or four%
    \or five%
    \or six%
    \or seven%
    \or eight%
    \or nine%
    \fi
}
\def\addchar#1{%
  \immediate\write\fontfile{
    begincchar(\number\n); "#1"; scale := scale*0.95; draw\name#1;}%
  \advance\n by 1}

% Add the next character as char \n to the current font, and repeat
% When \relax is seen, define \postalfont and print chars 0 to \n from it.
\def\vanishing#1{%
  \ifx#1\relax
  \immediate\write\fontfile{end}%
  \immediate\closeout\fontfile
  \font\postalfont=postal
  \postalfont
  \loop \char\m \advance\m by 1 \ifnum\m<\n \repeat
  \tenrm
  \ \else%
  \addchar#1%
  \expandafter\vanishing\fi}

$\pi$ is roughly three point \vanishing 141592653589793\relax in value.
\bye

Everything before the last two lines is setup, which defines some macros and writes out the initial part of the .mf file from TeX itself. The last two lines is the actual usage: from TeX you can write \vanishing 141592653589793\relax and "automatically" get the corresponding characters produced according to varying parameters. The output is the same as before:

automatic

(Of course this is only proof-of-concept and will fail under various conditions and I know nothing about font design and there are much better ways to do this, but I think this gives you some idea.)

ShreevatsaR
  • 45,428
  • 10
  • 117
  • 149
  • Thank you!!! @ShreevatsaR – Ana Fernandes Sep 02 '19 at 15:59
  • @AnaFernandes You're welcome. Maybe I didn't answer the actual question: In principle METAFONT is written as a batch program, to run and generate its output before TeX can use it. In practice, as TeX and METAFONT sources are basically programs, it is possible with some trickery (as above) to communicate between them in many surprising ways. See also (1) mplib in LuaTeX, which turns MetaPost (which is almost METAFONT) into a library and allows even more kinds of communication and calling it from TeX, (2) TikZ etc., (3) this site with interactive Meta-fonts. – ShreevatsaR Sep 02 '19 at 16:14