. 2
( 13)


it does de¬ne a closed region. How can be instructed to ¬ll that region?

The black triangle ˜ ™ that appears in the statement of exercises in this
book was drawn with the command
¬ll z1 - - z2 - - z3 - - cycle
after appropriate corner points z1 , z2 , and z3 had been speci¬ed. In this case the
outline of the region to be ¬lled was speci¬ed in terms of the symbol ˜- -™ instead
of ˜. .™; this is a convention we haven™t discussed before. Each ˜- -™ introduces
a straight line segment, which is independent of the rest of the path that it
belongs to; thus it is quite di¬erent from ˜. .™, which speci¬es a possibly curved
Chapter 4: Pens 25

line segment that connects smoothly with neighboring points and lines of a path. equilateral
In this case ˜- -™ was used so that the triangular region would have straight edges un¬ll
and sharp corners. We might say informally that ˜. .™ means “Connect the points
with a nice curve,” while ˜- -™ means “Connect the points with a straight line.”
The corner points z1 , z2 , and z3 were de¬ned care- (0,h) (w,h)
fully so that the triangle would be equilateral, i.e.,
so that all three of its sides would have the same length.
Since an equilateral triangle has 60—¦ angles, the following
equations did the job:
(Figure 4e will be inserted
x1 = x2 = w ’ x3 = s; here; too bad you can™t see
it now.)
y3 = .5h;
z1 ’ z2 = (z3 ’ z2 ) rotated 60.

Here w and h represent the character™s width and height,
and s is the distance of the triangle from the left and right
(0,0) (w,0)
edges of the type.

The ¬ll command has a companion called un¬ll, which changes pixels from
black to white inside a given region. For example, the solid bean shape on the
previous page can be changed to

(Figure 4f will be inserted here; too bad you can™t see it now.)

if we say also ˜un¬ll 1 [z4 , z2 ] . . 3 [z4 , z2 ] . . cycle; un¬ll 1 [z6 , z2 ] . . 3 [z6 , z2 ] . . cycle™.
4 4 4 4
This example shows, incidentally, that converts a two-point speci¬cation
like ˜z1 . . z2 . . cycle™ into a more-or-less circular path, even though two points by
themselves de¬ne only a straight line.

Let z0 be the point (.8[x1 , x2 ], .5[y1 , y4 ]), and introduce six new points by
letting zk = .2[zk , z0 ] for k = 1, 2, . . . , 6. Explain how to obtain the shape

(Figure 4g will be inserted here; too bad you can™t see it now.)

in which the interior region is de¬ned by z1 . . . z6 instead of by z1 . . . z6 .
26 Chapter 4: Pens

The ability to ¬ll between outlines makes it possible to pretend that we broad-edge pens
angle of pen
have broad-edge pens that change in direction and pressure as they glide over “
the paper, if we consider the separate paths traced out by the pen™s left edge penpos
compass directions
and right edge. For example, the stroke

(Figure 4h will be inserted here; too bad you can™t see it now.)

can be regarded as drawn by a pen that starts at the left, inclined at a 30—¦ angle;
as the pen moves, it turns gradually until its edge is strictly vertical by the time
it reaches the right end. The pen motion was horizontal at positions 2 and 3.
This stroke was actually obtained by the command
¬ll z1l . . z2l {right } . . {right } z3l
- - z3r {left } . . {left } z2r . . z1r
- - cycle;
i.e., was asked to ¬ll a region bounded by a “left path” from z1l to
z2l to z3l , followed by a straight line to z3r , then a reversed “right path” from
z3r to z2r to z1r , and ¬nally a straight line back to the starting point z1l .
Key positions of the “pen” are represented in this example by sets of
three points, like (z1l , z1 , z1r ), which stand for the pen™s left edge, its midpoint,
and its right edge. The midpoint doesn™t actually occur in the speci¬cation of
the outline, but we™ll see examples of its usefulness. The relationships between
such triples of points are established by a ˜penpos ™ command, which states the
breadth of the pen and its angle of inclination at a particular position. For
example, positions 1, 2, and 3 in the stroke above were established by saying
penpos1 (1.2pt , 30); penpos2 (1.0pt , 45); penpos3 (0.8pt , 90);
this made the pen 1.2 pt broad and tipped 30—¦ with respect to the horizontal at
position 1, etc. In general the idea is to specify ˜penposk (b, d)™, where k is the
position number or position name, b is the breadth (in pixels), and d is the angle
(in degrees). Pen angles are measured counterclockwise from the horizontal.
Thus, an angle of 0 makes the right edge of the pen exactly b pixels to the right
of the left edge; an angle of 90 makes the right pen edge exactly b pixels above
the left; an angle√ ’90 makes it exactly b pixels below. An angle of 45 makes
of √
the right edge b/ 2 pixels above and b/ 2 pixels to the right of the left edge;
√ √
an angle of ’45 makes it b/ 2 pixels below and b/ 2 to the right. When the
pen angle is between 90—¦ and 180—¦ , the “right” edge actually lies to the left of
the “left” edge. In terms of compass directions on a conventional map, an angle
of 0—¦ points due East, while 90—¦ points North and ’90—¦ points South. The angle
corresponding to Southwest is ’135—¦ , also known as +225—¦ .
What angle corresponds to the direction North-Northwest?
Chapter 4: Pens 27

EXERCISE 4.8 rotated
What are the pen angles at positions 1, 2, 3, and 4 in e
the circular shape shown here? [Hint: Each angle is a
multiple of 30—¦ . Note that z3r lies to the left of z3l .] (Figure 4i will be inserted
here; too bad you can™t see
it now.)
What are the coordinates of z1l and z1r after the com-
mand ˜penpos1 (10, ’90)™, if z1 = (25, 25)?
The statement ˜penposk (b, d)™ is simply an abbreviation for two equations,
˜zk = 1 [zkl , zkr ]™ and ˜zkr = zkl + (b, 0) rotated d ™. You might want to use
other equations to de¬ne the relationship between zkl , zk , and zkr , instead of giving a
penpos command, if an alternative formulation turns out to be more convenient.
After ˜penpos ™ has speci¬ed the relations between three points, we still
don™t know exactly where they are; we only know their positions relative to each
other. Another equation or two is needed in order to ¬x the horizontal and
vertical locations of each triple. For example, the three penpos commands that
led to the pen stroke on the previous page were accompanied by the equations
z1 = (0, 2pt ); z2 = (4pt , 0); x3 = 9pt ; y3l = y2r ;
these made the information complete. There should be one x equation and one
y equation for each position; or you can use a z equation, which de¬nes both x
and y simultaneously.
It™s a nuisance to write long-winded ¬ll commands when broad-edge
pens are being simulated in this way, so provides a convenient ab-
breviation: You can write simply
penstroke z1e . . z2e {right } . . {right }z3e
instead of the command ˜ ¬ll z1l . . z2l {right } . . {right } z3l - - z3r {left } . .
{left } z2r . . z1r - - cycle™ that was stated earlier. The letter ˜e™ stands for the
pen™s edge. A penstroke command ¬lls the region ˜p.l - - reverse p.r - - cycle™,
where p.l and p.r are the left and right paths formed by changing each ˜e™ into
˜l™ or ˜r™, respectively.
The penstroke abbreviation can be used to draw cyclic paths as well as
ordinary ones. For example, the circle in exercise 4.8 was created by saying
simply ˜penstroke z1e . . z2e . . z3e . . z4e . . cycle™. This type of penstroke essentially
expands into
¬ll z1r . . z2r . . z3r . . z4r . . cycle;
un¬ll z1l . . z2l . . z3l . . z4l . . cycle;
or the operations ˜¬ll™ and ˜un¬ll™ are reversed, if points (z1r , z2r , z3r , z4r ) are on the
inside and (z1l , z2l , z3l , z4l ) are on the outside.
The circle of exercise 4.8 was actually drawn with a slightly more complicated
penstroke command than just claimed: The edges of the curve were forced to be
vertical at positions 1 and 3, horizontal at 2 and 4. How did the author do this?
28 Chapter 4: Pens

Here™s an example of how this new sort of pen can be used to draw a sans- I
serif letter ˜ ™. As usual, we assume that two variables, h and w, have been set up assignment
to give the height and width of the character in pixels. We :=
(0,h) (w,h) hex
shall also assume that there™s a stem parameter, which
speci¬es the nominal pen breadth. The breadth decreases
to .9stem in the middle of the stroke, and the pen angle
changes from 15—¦ to 10—¦ :
penpos1 (stem , 15); penpos2 (.9stem , 12); (Figure 4j will be
inserted here; too
penpos3 (stem , 10); x1 = x2 = x3 = .5w; bad you can™t see it
y1 = h; y2 = .55h; y3 = 0;
x2l := 1 [x2l , x2 ];
penstroke z1e . . z2e {down} . . z3e .
Setting x1 = x2 = x3 = .5w centers the stroke; setting
y1 = h and y3 = 0 makes it sit in the type box, protruding (0,0) (w,0)

just slightly at the top and bottom.
The second-last line of this program is something that we haven™t seen
before: It resets x2l to a value 1/6 of the way towards the center of the pen,
thereby making the stroke taper a bit at the left. The ˜:=™ operation is called an
assignment; we shall study the di¬erences between ˜:=™ and ˜=™ in Chapter 10.
It is important to note that these simulated pens have a serious limitation
compared to the way a real calligrapher™s pen works: The left and right edges
of a penpos -made pen must never cross, hence it is necessary to turn the pen when
going around a curve. Consider, for example, the following two curves:

(Figure 4k will be inserted here; too bad you can™t see it now.)

The left-hand circle was drawn with a broad-edge pen of ¬xed breadth, held at a ¬xed
angle; consequently the left edge of the pen was responsible for the outer boundary on
the left, but the inner boundary on the right. (This curve was produced by saying
˜pickup pencircle xscaled 0.8pt rotated 25; draw z1 . . z2 . . cycle™.) The right-hand
shape was produced by ˜penpos1 (0.8pt , 25); penpos2 (0.8pt , 25); penstroke z1e . . z2e . .
cycle™; important chunks of the shape are missing at the crossover points, because they
don™t lie on either of the circles z1l . . z2l . . cycle or z1r . . z2r . . cycle.

To conclude this chapter we shall improve the hex character of Chapter 2,
which is too dark in the middle because it has been drawn with a pen of
uniform thickness. The main trouble with unvarying pens is that they tend to produce
black blotches where two strokes meet, unless the pens are comparatively thin or unless
the strokes are nearly perpendicular. We want to thin out the lines at the center just
Chapter 4: Pens 29

enough to cure the darkness problem, without destroying the illusion that the lines still angle
seem (at ¬rst glance) to have uniform thickness.
It isn™t di¬cult to produce ˜ ™ instead of
˜ ™ when we work with dynamic pens:
pickup pencircle scaled b;
top z1 = (0, h); top z2 = (.5w, h); top z3 = (w, h);
bot z4 = (0, 0); bot z5 = (.5w, 0); bot z6 = (w, 0); draw z2 . . z5 ;
z1 = .25[z1 , z6 ]; z6 = .75[z1 , z6 ]; z3 = .25[z3 , z4 ]; z4 = .75[z3 , z4 ];
theta 1 := angle(z6 ’ z1 ) + 90;
(0,h) (w,h)
theta 3 := angle(z4 ’ z3 ) + 90;
penpos1 (b, theta 1 ); penpos6 (b, theta 1 );
penpos3 (b, theta 3 ); penpos4 (b, theta 3 ); (Figure 4l will be inserted here;
too bad you can™t see it now.)
penpos7 (.6b, theta 1 ); penpos8 (.6b, theta 3 );
z7 = z8 = .5[z1 , z6 ];
draw z1 . . z1 ; draw z6 . . z6 ; (0,0) (w,0)
draw z3 . . z3 ; draw z4 . . z4 ;
penstroke z1 e {z6 ’ z1 } . . z7e . . {z6 ’ z1 }z6 e ;
penstroke z3 e {z4 ’ z3 } . . z8e . . {z4 ’ z3 }z4 e .
Here b is the diameter of the pen at the terminal points; ˜angle™ computes the direction
angle of a given vector. Adding 90—¦ to a direction angle gives a perpendicular direction
(see the de¬nitions of theta 1 and theta 3 ). It isn™t necessary to take anything o¬ of the
vertical stroke z2 . . z5 , because the two diagonal strokes ¬ll more than the width of
the vertical stroke at the point where they intersect.
(0,h) (w,h)
Modify the hex character so that its ends are
(Figure 4m will be inserted
cut sharply and con¬ned to the bounding box, as shown. here; too bad you can™t see it

(0,0) (w,0)

It is very important that the nib be cut “sharp,”
and as often as its edge wears blunt it must be resharpened.
It is impossible to make “clean cut” strokes with a blunt pen.
” EDWARD JOHNSTON, Writing & Illuminating, & Lettering (1906)

I might compare the high-speed computing machine
to a remarkably large and awkward pencil
which takes a long time to sharpen and
cannot be held in the ¬ngers in the usual manner so that it
gives the illusion of responding to my thoughts,
but is ¬tted with a rather delicate engine
and will write like a mad thing
provided I am willing to let it dictate pretty much
the subjects on which it writes.
” R. H. BRUCK, Computational Aspects of Certain
Combinatorial Problems (1956)
(page 30)

Chapter 5: Running 31

It™s high time now for you to stop reading and to start playing with the computer, mf
since is an interactive system that is best learned by trial and error. backslash
(In fact, one of the nicest things about computer graphics is that errors are often return
more interesting and more fun than “successes.”) *
You probably will have to ask somebody how to deal with the idiosyn- showit
crasies of your particular version of the system, even though itself end
works in essentially the same way on all machines; di¬erent computer terminals mfput
and di¬erent hardcopy devices make it necessary to have somewhat di¬erent
interfaces. In this chapter we shall assume that you have a computer terminal
with a reasonably high-resolution graphics display; that you have access to a
(possibly low-resolution) output device; and that you can rather easily get that
device to work with newly created fonts.
OK, are you ready to run the program? First you need to log in, of
course; then start , which is usually called mf for short. Once you™ve
¬gured out how to do it, you™ll be welcomed by a message something like
This is METAFONT, Version 2.0 (preloaded base=plain 89.11.8)
The ˜**™ is ™s way of asking you for an input ¬le name.
Now type ˜\relax™”that™s backslash, r, e, l, a, x”and hit return
(or whatever stands for “end-of-line” on your keyboard). is all geared
up for action, ready to make a big font; but you™re saying that it™s all right to take
things easy, since this is going to be a real simple run. The backslash means that
should not read a ¬le, it should get instructions from the keyboard;
the ˜relax™ means “do nothing.”
The machine will respond by typing a single asterisk: ˜*™. This means
it™s ready to accept instructions (not the name of a ¬le). Type the following,
just for fun:
drawdot (35,70); showit;
and return ”don™t forget to type the semicolons along with the other stu¬. A
more-or-less circular dot should now appear on your screen! And you should also
be prompted with another asterisk. Type
drawdot (65,70); showit;
and return , to get another dot. (Henceforth we won™t keep mentioning the
necessity of return ing after each line of keyboard input.) Finally, type
draw (20,40)..(50,25)..(80,40); showit; shipit; end.
This draws a curve through three given points, displays the result, ships it to an
output ¬le, and stops. should respond with ˜[0]™, meaning that it
has shipped out a character whose number is zero, in the “font” just made; and
it should also tell you that it has created an output ¬le called ˜mfput.2602gf™.
(The name mfput is used when you haven™t speci¬ed any better name in response
32 Chapter 5: Running

to the ** at the beginning. The su¬x 2602gf stands for “generic font at 2602 **
pixels per inch.” The data in mfput.2602gf can be converted into fonts suitable generic font
for a wide assortment of typographical output devices; since it doesn™t match GFtoDVI
the font ¬le conventions of any name-brand manufacturer, we call it generic.) mode setup
This particular ¬le won™t make a very interesting font, because it con-
tains only one character, and because it probably doesn™t have the correct res-
olution for your output device. However, it does have the right resolution for
hardcopy proofs of characters; your next step should therefore be to convert the
data of mfput.2602gf into a picture, suitable for framing. There should be a
program called GFtoDVI on your computer. Apply it to mfput.2602gf, thereby
obtaining a ¬le called mfput.dvi that can be printed. Your friendly local com-
puter hackers will tell you how to run GFtoDVI and how to print mfput.dvi; then
you™ll have a marvelous souvenir of your very ¬rst encounter with .
Once you have made a complete test run as just described, you will know
how to get through the whole cycle, so you™ll be ready to tackle a more complex
project. Our next experiment will therefore be to work from a ¬le, instead of
typing the input online.
Use your favorite text editor to create a ¬le called io.mf that contains
the following 23 lines of text (no more, no less):
em#:=10pt#; cap#:=7pt#;
thin#:=1/3pt#; thick#:=5/6pt#;
curve_sidebar=round 1/18em;
beginchar("O",0.8em#,cap#,0); "The letter O";
penpos1(thick,10); penpos2(.1[thin,thick],90-10);
penpos3(thick,180+10); penpos4(thin,270-10);
x1l=w-x3l=curve_sidebar; x2=x4=.5w;
y1=.49h; y2l=-o; y3=.51h; y4l=h+o;
penstroke z1e{down}..z2e{right}
penlabels(1,2,3,4); endchar;
def test_I(expr code,trial_stem,trial_width) =
stem#:=trial_stem*pt#; define_blacker_pixels(stem);
beginchar(code,trial_width*em#,cap#,0); "The letter I";
penpos1(stem,15); penpos2(stem,12); penpos3(stem,10);
x1=x2=x3=.5w; y1=h; y2=.55h; y3=0; x2l:=1/6[x2l,x2];
penstroke z1e..z2e{down}..z3e;
penlabels(1,2,3); endchar; enddef;

(But don™t type the numbers at the left of these lines; they™re only for reference.)
Chapter 5: Running 33

This example ¬le is dedicated to Io, the Greek goddess of input and Io
output. It™s a tri¬‚e long, but you™ll be able to get worthwhile experience by units of measure
typing it; so go ahead and type it now. For your own good. And think about pt
what you™re typing, as you go; the example introduces several important features de¬ne pixels
of that you can learn as you™re creating the ¬le. de¬ne blacker pixels
Here™s a brief explanation of what you™ve just typed: Line 1 contains a
command that usually appears near the beginning of every ¬le; it
tells the computer to get ready to work in whatever “mode” is currently desired.
(A ¬le like io.mf can be used to generate proofsheets as well as to make fonts
for a variety of devices at a variety of magni¬cations, and ˜mode setup™ is what
adapts to the task at hand.) Lines 2“8 de¬ne parameters that will
be used to draw the letters in the font. Lines 9“16 give a complete program for
the letter ˜O™; and lines 17“23 give a program that will draw the letter ˜I™ in a
number of related ways.
It all looks pretty frightening at ¬rst glance, but a closer look shows
that Io is not so mysterious once we penetrate her disguise. Let™s spend a few
minutes studying the ¬le in more detail.
Lines 2“4 de¬ne dimensions that are independent of the mode; the ˜#™
signs are meant to imply “sharp” or “true” units of measure, which remain the
same whether we are making a font at high or low resolution. For example, one
˜pt#™ is a true printer™s point, one 72.27th of an inch. This is quite di¬erent from
the ˜pt ™ we have discussed in previous chapters, because ˜pt ™ is the number of
pixels that happen to correspond to a printer™s point when the current resolu-
tion is taken into account. The value of ˜pt#™ never changes, but mode setup
establishes the appropriate value of ˜pt ™.
The assignments ˜em#:=10pt#™ and ˜cap#:=7pt#™ in line 2 mean that the
Io font has two parameters, called em and cap , whose mode-independent values
are 10 and 7 points, respectively. The statement ˜define_pixels(em,cap)™ on
line 5 converts these values into pixel units. For example, if we are working at
the comparatively low resolution of 3 pixels per pt, the values of em and cap
after the computer has performed the instructions on line 5 will be em = 30
and cap = 21. (We will see later that the widths of characters in this font are
expressed in terms of ems, and that cap is the height of the capital letters. A
change to line 2 will therefore a¬ect the widths and/or heights of all the letters.)
Similarly, the Io font has parameters called thin and thick , de¬ned on
line 3 and converted to pixel units in line 6. These are used to control the breadth
of a simulated pen when it draws the letter O. Experience has shown that -
produces better results on certain output devices if pixel-oriented pens are
made slightly broader than the true dimensions would imply, because black pixels
sometimes tend to “burn o¬” in the process of printing. The command on line 6,
˜define_blacker_pixels™, adds a correction based on the device for which the
font is being prepared. For example, if the resolution is 3 pixels per point, the
value of thin when converted from true units to pixels by de¬ne pixels would
be 1, but de¬ne blacker pixels might set thin to a value closer to 2.
34 Chapter 5: Running

The ˜o™ parameter on line 4 represents the amount by which curves will o
overshoot their boundaries. This is converted to pixels in yet another way on sidebar
line 7, so as to avoid yet another problem that arises in low-resolution printing. rounding
The author apologizes for letting such real-world considerations intrude into a TeX
textbook example; let™s not get bogged down in fussy details now, since these
re¬nements will be explained in Chapter 11 after we have mastered the basics.
For now, the important point is simply that a typeface design usually in-
volves parameters that represent physical lengths. The true, “sharped” forms of
these parameters need to be converted to “unsharped” pixel-oriented quantities,
and best results are obtained when such conversions are done carefully. After
has obeyed line 7 of the example, the pixel-oriented parameters em ,
cap , thin , thick , and o are ready to be used as we draw letters of the font.
Line 8 de¬nes a quantity called curve sidebar that will measure the
distance of the left and right edges of the ˜O™ from the bounding box. It is com-
puted by rounding 18 em to the nearest integer number of pixels. For example,
if em = 30 then 30 = 5 yields the rounded value curve sidebar = 2; there will
18 3
be two all-white columns of pixels at the left and right of the ˜O™, when we work
at this particular resolution.
Before we go any further, we ought to discuss the strange collection of
words and pseudo-words in the ¬le io.mf. Which of the terms ˜mode_setup™, ˜em™,
˜curve_sidebar™ and so forth are part of the language, and which of
them are made up speci¬cally for the Io example? Well, it turns out that almost
nothing in this example is written in the pure language that the
computer understands! is really a low-level language that has been
designed to allow easy adaptation to many di¬erent styles of programming, and
io.mf illustrates just one of countless ways to use it. Most of the terms in io.mf
are conventions of “plain ,” which is a collection of subroutines found
in Appendix B. ™s primitive capabilities are not meant to be used
directly, because that would force a particular style on all users. A “base ¬le” is
generally loaded into the computer at the beginning of a run, so that a standard
set of conventions is readily available. ™s welcoming message, quoted
at the beginning of this chapter, says ˜preloaded base=plain™; it means that
the primitive language has been extended to include the features
of the plain base ¬le. This book is not only about ; it also explains
how to use the conventions of ™s plain base. Similarly, The TEXbook
describes a standard extension of TEX called “plain TEX format”; the “plain”
extensions of TEX and are completely analogous to each other.
The notions of mode setup, de¬ne pixels, beginchar, penpos , and
many other things found in io.mf are aspects of plain but they are
not hardwired into itself. Appendix B de¬nes all of these things, as
well as the relations between “sharped” and “unsharped” variables. Even the
fact that z1 stands for (x1 , y1 ) is de¬ned in Appendix B; does not
have this built in. You are free to de¬ne even fancier bases as you gain more
experience, but the plain base is a suitable starting point for a novice.
Chapter 5: Running 35

If you have important applications that make use of a di¬erent base ¬le, it™s mf
possible to create a version of that has any desired base preloaded.
Computer Modern
Such a program is generally called by a special name, since the nickname ˜mf™ is reserved **
for the version that includes the standard plain base assumed in this book. For example, ampersand
the author has made a special version called ˜cmmf™ just for the Computer Modern bounding box
typefaces he has been developing, so that the Computer Modern base ¬le does not sharped
have to be loaded each time he makes a new experiment.
There™s a simple way to change the base ¬le from the one that has been rounded
preloaded: If the ¬rst character you type in response to ˜**™ is an ampersand
( ˜&™ ), will replace its memory with a speci¬ed base ¬le before proceeding.
If, for example, there is a base ¬le called ˜cm.base™ but not a special program called
˜cmmf™, you can substitute the Computer Modern base for the plain base in mf by
typing ˜&cm™ at the very beginning of a run. If you are working with a program that
doesn™t have the plain base preloaded, the ¬rst experiment in this chapter won™t work as
described, but you can do it by starting with ˜&plain \relax™ instead of just ˜\relax™.
These conventions are exactly the same as those of TEX.

Our Ionian example uses the following words that are not part of plain
: em , cap , thin , thick , o , curve sidebar , test I , code , trial stem ,
trial width , and stem . If you change these to some other words or symbols”for
example, if you replace ˜thin™ and ˜thick™ by ˜t™ and ˜T™ respectively, in lines
3, 6, 10, and 11”the results will be unchanged, unless your substitutions just
happen to clash with something that plain has already pre¨mpted.
In general, the best policy is to choose descriptive terms for the quantities in
your programs, since they are not likely to con¬‚ict with reserved pseudo-words
like penpos and endchar.
We have already noted that lines 9“16 of the ¬le represent a program
for the letter ˜O™. The main part of this program, in lines 10“15, uses the ideas
of Chapter 4, but we haven™t seen the stu¬ in lines 9 and 16 before. Plain
makes it convenient to de¬ne letters by starting each one with
beginchar ( code , width , height , depth );
here code is either a quoted single character like "O" or a number that rep-
resents the character™s position in the ¬nal font. The other three quantities
width , height , and depth say how big the bounding box is, so that typeset-
ting systems like TEX will be able to use the character. These three dimensions
must be given in device-independent units, i.e., in “sharped” form.
What are the height and width of the bounding box described in the beginchar
command on line 9 of io.mf, given the parameter values de¬ned on line 2? Give
your answer in terms of printer™s points.
Each beginchar operation assigns values to special variables called w,
h, and d, which represent the respective width, height, and depth of the current
character™s bounding box, rounded to the nearest integer number of pixels. Our
36 Chapter 5: Running

example ¬le uses w and h to help establish the locations of several pen positions endchar
(see lines 12, 13, and 21 of io.mf). def
Continuing the previous exercise, what will be the values of w and h if there are mf
¬le names
exactly 3.6 pixels per point?
There™s a quoted phrase "The letter O" at the end of line 9; this is
simply a title that will be used in printouts.
The ˜endchar™ on line 16 ¬nishes the character that was begun on line 9,
by writing it to an output ¬le and possibly displaying it on your screen. We will
want to see the positions of the control points z1 , z2 , z3 , and z4 that are used in its
design, together with the auxiliary points (z1l , z2l , z3l , z4l ) and (z1r , z2r , z3r , z4r )
that come with the penpos conventions; the statement ˜penlabels(1,2,3,4)™
takes care of labeling these points on the proofsheets.
So much for the letter O. Lines 17“23 are analogous to what we™ve seen
before, except that there™s a new wrinkle: They contain a little program enclosed
by ˜def...enddef™, which means that a subroutine is being de¬ned. In other
words, those lines set up a whole bunch of commands that we will
want to execute several times with minor variations. The subroutine is called
test I and it has three parameters called code , trial stem , and trial width (see
line 17). The idea is that we™ll want to draw several di¬erent versions of an
˜I™, having di¬erent stem widths and character widths; but we want to type the
program only once. Line 18 de¬nes stem # and stem , given a value of trial stem ;
and lines 19“23 complete the program for the letter I (copying it from Chapter 4).
Oops”we™ve been talking much too long about io.mf. It™s time to stop
rambling and to begin Experiment 2 in earnest, because it will be much more
fun to see what the computer actually does with that ¬le.
Are you brave enough to try Experiment 2? Sure. Get
going again, but this time when the machine says ˜**™ you should say ˜io™, since
that™s the name of the ¬le you have prepared so laboriously. (The ¬le could also
be speci¬ed by giving its full name ˜io.mf™, but automatically adds
˜.mf™ when no su¬x has been given explicitly.)
If all goes well, the computer should now ¬‚ash its lights a bit and”
presto”a big ˜ ™ should be drawn on your screen. But if your luck is as good
as the author™s, something will probably go wrong the ¬rst time, most likely
because of a typographic error in the ¬le. A program contains lots
of data with comparatively little redundancy, so a single error can make a drastic
change in the meaning. Check that you™ve typed everything perfectly: Be sure
to notice the di¬erence between the letter ˜l™ and the numeral ˜1™ (especially in
line 12, where it says ˜x1l™, not ˜x11 or ˜xll™); be sure to distinguish between
the letter ˜O™ and the numeral ˜0™ (especially in line 9); be sure to type the
“underline” characters in words like ˜mode_setup™. We™ll see later that -
can recover gracefully from most errors, but your job for now is to make
sure that you™ve got io.mf correct.
Chapter 5: Running 37

Once you have a working ¬le, the computer will draw you an ˜ ™ and it ASCII
will also say something like this: end
(io.mf penpos
The letter O [79]) labels
over¬‚ow labels
What does this mean? Well, ˜(io.mf™ means that it has started to read your
¬le, and ˜The letter O™ was printed when the title was found in line 9. Then
when got to the endchar on line 16, it said ˜[79]™ to tell you that it
had just output character number 79. (This is the ASCII code for the letter O;
Appendix C lists all of these codes, if you need to know them.) The ˜)™ after
˜[79]™ means that subsequently ¬nished reading the ¬le, and the ˜*™
means that it wants another instruction.
Hmmm. The ¬le contains programs for both I and O; why did we get
only an O? Answer: Because lines 17“23 simply de¬ne the subroutine test I ; they
don™t actually do anything with that subroutine. We need to activate test I if
we™re going to see what it does. So let™s type
this invokes the subroutine, with code = "I", trial stem = 5 , and trial width =
. The computer will now draw an I corresponding to these values,* and it will
prompt us for another command.
It™s time to type ˜end™ now, after which should tell us that it
has completed this run and made an output ¬le called ˜io.2602gf™. Running this
¬le through GFtoDVI as in Experiment 1 will produce two proofsheets, showing
the ˜ ™ and the ˜ ™ we have created. The output won™t be shown here, but you
can see the results by doing the experiment personally.
Look at those proofsheets now, because they provide instructive exam-
ples of the simulated broad-edge pen constructions introduced in Chapter 4.
Compare the ˜ ™ with the program that drew it: Notice that the penpos2 in
line 10 makes the curve slightly thicker at the bottom than at the top; that
the equation ˜x1l = w ’ x3l = curve sidebar ™ in line 12 makes the right edge
of the curve as far from the right of the bounding box as the left edge is from
the left; that line 13 places point 1 slightly lower than point 3. The proofsheet
for ˜ ™ should look very much like the corresponding illustration near the end of
Chapter 4, but it will be somewhat larger.
Your proof copy of the ˜ ™ should show twelve dots for key points; but only
ten of them will be labeled, because there isn™t room enough to put labels on
points 2 and 4. The missing labels usually appear in the upper right corner, where it
might say, e.g., ˜4 = 4l + (-1,-5.9)™; this means that point z4 is one pixel to the left
and 5.9 pixels down from point z4l , which is labeled. (Some implementations omit this
information, because there isn™t always room for it.)

* Unless, of course, there was a typing error in lines 17“23, where test I is de¬ned.
38 Chapter 5: Running

The proofsheets obtained in Experiment 2 show the key points and the **
bounding boxes, but this extra information can interfere with our perception of smoke
the character shape itself. There™s a simple way to get proofs that allow a viewer magni¬cation
to criticize the results from an aesthetic rather than a logical standpoint; the
creation of such proofs will be the goal of our next experiment.
Here™s how to do Experiment 3: Start as usual, then type
\mode=smoke; input io
in response to the ˜**™. This will input ¬le io.mf again, after establishing
“smoke” mode. (As in Experiment 1, the command line begins with ˜\™ so
that the computer knows you aren™t starting with the name of a ¬le.) Then
complete the run exactly as in Experiment 2, by typing ˜test_I("I",5/6,1/3);
end™; and apply GFtoDVI to the resulting ¬le io.2602gf.
This time the proofsheets will contain the same characters as before,
but they will be darker and without labeled points. The bounding boxes will be
indicated only by small markings at the corners; you can put these boxes next
to each other and tack the results up on the wall, then stand back to see how
the characters will look when set by a high-resolution typesetter. (This way of
working is called smoke mode because it™s analogous to the “smoke proofs” that
punch-cutters traditionally used to test their handiwork. They held the newly
cut type over a candle ¬‚ame so that it would be covered with carbon; then they
pressed it on paper to make a clean impression of the character, in order to see
whether changes were needed.)
Incidentally, many systems allow you to invoke by typing a one-
line command like ˜mf io™ in the case of Experiment 2; you don™t have to
wait for the ˜**™ before giving a ¬le name. Similarly, the one-liners ˜mf \relax™ and
˜mf \mode=smoke; input io™ can be used on many systems at the beginning of Experi-
ments 1 and 3. You might want to try this, to see if it works on your computer; or you
might ask somebody if there™s a similar shortcut.
Experiments 1, 2, and 3 have demonstrated how to make proof drawings
of test characters, but they don™t actually produce new fonts that can be used
in typesetting. For this, we move onward to Experiment 4, in which we put
ourselves in the position of a person who is just starting to design a new typeface.
Let™s imagine that we™re happy with the O of io.mf, and that we want a “sans
serif” I in the general style produced by test I , but we aren™t sure about how
thick the stem of the I should be in order to make it blend properly with the O.
Moreover, we aren™t sure how much white space to leave at the sides of the I.
So we want to do some typesetting experiments, using a sequence of di¬erent I™s.
The ideal way to do this would be to produce a high-resolution test font
and to view the output at its true size. But this may be too expensive, because
¬ne printing equipment is usually available only for large production runs. The
next-best alternative is to use a low-resolution printer but to magnify the output,
so that the resolution is e¬ectively increased. We shall adopt the latter strategy,
because it gives us a chance to learn about magni¬cation as well as fontmaking.
Chapter 5: Running 39

After starting again, you can begin Experiment 4 by typing plain base
\mode=localfont; mag=4; input io
in response to the ˜**™. The plain base at your installation is supposed to recog- endfor
nize localfont as the name of the mode that makes fonts for your “standard” ASCII
output device. The equation ˜mag=4™ means that this run will produce a font font metric ¬le
that is magni¬ed fourfold; i.e., the results will be 4 times bigger than usual. output of METAFONT
The computer will read io.mf as before, but this time it won™t display
an ˜O™; characters are normally not displayed in fontmaking modes, because we
usually want the computer to run as fast as possible when it™s generating a font
that has already been designed. All you™ll see is ˜(io.mf [79])™, followed by ˜*™.
Now the fun starts: You should type
for s=7 upto 10:
for w=5 upto 8:
test_I(incr code,s/10,w/20);
endfor endfor end.
(Here ˜upto™ must be typed as a single word.) We™ll learn about repeating things
with ˜for...endfor™ in Chapter 19. This little program produces 16 versions of
the letter I, with stem widths of 10 , 10 , 10 , and 10 pt, and with character widths
7 8 9
5 6 7 8
of 20 , 20 , 20 , and 20 em. The sixteen trial characters will appear in positions
101 through 116 of the font; it turns out that these are the ASCII codes for lower
case letters e through t inclusive. (Other codes would have been used if ˜code™
had been started at a value di¬erent from 100. The construction ˜incr code™
increases the value of code by 1 and produces the new value; thus, each use of
test_I has a di¬erent code number.)
This run of will not only produce a generic font io.nnngf,
it will also create a ¬le called io.tfm, the “font metric ¬le” that tells typesetting
systems like TEX how to make use of the new font. The remaining part of
Experiment 4 will be to put TEX to work: We shall make some test patterns
from the new font, in order to determine which ˜I™ is best.
You may need to ask a local system wizard for help at this point, because
it may be necessary to move the ¬le io.tfm to some special place where TEX
and the other typesetting software can ¬nd it. Furthermore, you™ll need to run
a program that converts io.nnngf to the font format used by your local output
device. But with luck, these will both be fairly simple operations, and a new
font called ˜io™ will e¬ectively be installed on your system. This font will contain
seventeen letters, namely an O and sixteen I™s, where the I™s happen to be in
the positions normally occupied by e, f, . . . , t. Furthermore, the font will be
magni¬ed fourfold.
The magni¬cation of the font will be re¬‚ected in its ¬le name. For example,
if localfont mode is for a device with 200 pixels per inch, the io font at 4—
magni¬cation will be called ˜io.800gf™.
40 Chapter 5: Running

You can use TEX to typeset from this font like any other, but for the testfont
purposes of Experiment 4 it™s best to use a special TEX package that has been backslash
speci¬cally designed for font testing. All you need to do is to run TEX”which background letter
is just like running , except that you call it ˜tex™ instead of ˜mf™; Isis
and you simply type ˜testfont™ in reply to TEX™s ˜**™. (The testfont routine
should be available on your system; if not, you or somebody else can type it in,
by copying the relevant material from Appendix H.) You will then be asked for
the name of the font you wish to test. Type
io scaled 4000
(which means the io font magni¬ed by 4, in TEX™s jargon), since this is what
just created. The machine will now ask you for a test command,
and you should reply
to get the “mixture” test. (Don™t forget the backslash.) You™ll be asked for a
background letter, a starting letter, and an ending letter; type ˜O™, ˜e™, and ˜t™,
respectively. This will produce sixteen lines of typeset output, in which the ¬rst
line contains a mixture of O with e, the second contains a mixture of O with f,
and so on. To complete Experiment 4, type ˜\end™ to TEX, and print the ¬le
testfont.dvi that TEX gives you.
If all goes well, you™ll have sixteen lines that say ˜OIOOI IOOOII IOI™,
but with a di¬erent I on each line. In order to choose the line that looks best,
without being in¬‚uenced by neighboring lines, it™s convenient to take two sheets
of blank paper and use them to mask out all of the lines except the one you™re
studying. Caution: These letters are four times larger than the size at which
the ¬nal font is meant to be viewed, so you should look at the samples from
afar. Xerographic reductions may introduce distortions that will give misleading
results. Sometimes when you stare at things like this too closely, they all look
wrong, or they all look right; ¬rst impressions are usually more signi¬cant than
the results of logical re¬‚ection. At any rate, you should be able to come up
with an informed judgment about what values to use for the stem width and the
character width of a decent ˜I™; these can then be incorporated into the program,
the ˜def™ and ˜enddef™ parts of io.mf can be removed, and you can go on to
design other characters that go with your I and O. Furthermore you can always
go back and make editorial changes after you see your letters in more contexts.
The goddess Io was known in Egypt as Isis. Design an ˜ ™ for her.

Well, this isn™t a book about type design; the example of io.mf is simply
intended to illustrate how a type designer might want to operate, and to provide a
run-through of the complete process from design of type to its use in a document.
We must go back now to the world of computerese, and study a few more practical
details about the use of .
Chapter 5: Running 41

This has been a long chapter, but take heart: There™s only one more ¿¿
experiment to do, and then you will know enough about to run it
fearlessly by yourself forever after. The only thing you are still missing is some
information about how to cope with error messages. Sometimes
stops and asks you what to do next. Indeed, this may have already happened,
and you may have panicked.
Error messages can be terrifying when you aren™t prepared for them;
but they can be fun when you have the right attitude. Just remember that
you really haven™t hurt the computer™s feelings, and that nobody will hold the
errors against you. Then you™ll ¬nd that running might actually be
a creative experience instead of something to dread.
The ¬rst step in Experiment 5 is to plant some intentional mistakes in
the input ¬le. Make a copy of io.mf and call it badio.mf; then change line 1 of
badio.mf to
mode setup; % an intentional error!
(thereby omitting the underline character in mode_setup). Also change the ¬rst
semicolon ( ˜;™ ) on line 2 to a colon ( ˜:™ ); change ˜thick,10™ to ˜thick,l0™ on
line 10 (i.e., replace the numeral ˜1™ by the letter ˜l™ ); and change ˜thin™ to
˜thinn™ on line 11. These four changes introduce typical typographic errors, and
it will be instructive to see if they lead to any disastrous consequences.
Now start up again; but instead of cooperating with the
computer, type ˜mumble™ in reply to the ˜**™. (As long as you™re going to make
intentional mistakes, you might as well make some dillies.) will say
that it can™t ¬nd any ¬le called mumble.mf, and it will ask you for another name.
Just hit return this time; you™ll see that you had better give the name of a real
¬le. So type ˜badio™ and wait for to ¬nd one of the faux pas in that
messed-up travesty.
Ah yes, the machine will soon stop, after typing something like this:
>> mode.setup
! Isolated expression.
<to be read again>
l.1 mode setup;
% an intentional error!
begins its error messages with ˜!™, and it sometimes precedes them
with one or two related mathematical expressions that are displayed on lines
starting with ˜>>™. Each error message is also followed by lines of context that
show what the computer was reading at the time of the error. Such context lines
occur in pairs; the top line of the pair (e.g., ˜mode setup;™ ) shows what -
has looked at so far, and where it came from (˜l.1™, i.e., line number 1);
the bottom line (here ˜% an intentional error!™ ) shows what has
42 Chapter 5: Running

yet to read. In this case there are two pairs of context lines; the top pair refers transcript
log ¬le
to a semicolon that has read once but will be reading again, because ?
it didn™t belong with the preceding material. inserting text online
online interaction, see interaction
You don™t have to take out pencil and paper in order to write down the interacting with MF
error messages that you get before they disappear from view, since tokens
deleting tokens
always writes a “transcript” or “log ¬le” that records what happened during
each session. For example, you should now have a ¬le called io.log containing
the transcript of Experiment 4, as well as a ¬le mfput.log that contains the
transcript of Experiment 1. (The old transcript of Experiment 2 was probably
overwritten when you did Experiment 3, and again when you did Experiment 4,
because all three transcripts were called io.log.) At the end of Experiment 5
you™ll have a ¬le badio.log that will serve as a helpful reminder of what errors
need to be ¬xed up.
The ˜?™ that appears after the context display means that
wants advice about what to do next. If you™ve never seen an error message
before, or if you™ve forgotten what sort of response is expected, you can type ˜?™
now (go ahead and try it!); will respond as follows:
Type <return> to proceed, S to scroll future error messages,
R to run without stopping, Q to run quietly,
I to insert something, E to edit your file,
1 or ... or 9 to ignore the next 1 to 9 tokens of input,
H for help, X to quit.
This is your menu of options. You may choose to continue in various ways:
1. Simply type return . will resume its processing, after at-
tempting to recover from the error as best it can.
2. Type ˜S™. will proceed without pausing for instructions if
further errors arise. Subsequent error messages will ¬‚ash by on your
terminal, possibly faster than you can read them, and they will appear
in your log ¬le where you can scrutinize them at your leisure. Thus,
˜S™ is sort of like typing return to every message.
3. Type ˜R™. This is like ˜S™ but even stronger, since it tells not
to stop for any reason, not even if a ¬le name can™t be found.
4. Type ˜Q™. This is like ˜R™ but even more so, since it tells not
only to proceed without stopping but also to suppress all further output
to your terminal. It is a fast, but somewhat reckless, way to proceed
(intended for running with no operator in attendance).
5. Type ˜I™, followed by some text that you want to insert.
will read this text before encountering what it would ordinarily see next.
6. Type a small number (less than 100). will delete this many
tokens from whatever it is about to read next, and it will pause again
to give you another chance to look things over. (A “token” is a name,
number, or symbol that reads as a unit; e.g., ˜mode™ and
Chapter 5: Running 43

˜setup™ and ˜;™ are the ¬rst three tokens of badio.mf, but ˜mode_setup™ help messages
is the ¬rst token of io.mf. Chapter 6 explains this concept precisely.) period
7. Type ˜H™. This is what you should do now and whenever you are faced comments
with an error message that you haven™t seen for a while.
has two messages built in for each perceived error: a formal one and
an informal one. The formal message is printed ¬rst (e.g., ˜! Isolated
expression.™ ); the informal one is printed if you request more help
by typing ˜H™, and it also appears in your log ¬le if you are scrolling
error messages. The informal message tries to complement the formal
one by explaining what thinks the trouble is, and often by
suggesting a strategy for recouping your losses.
8. Type ˜X™. This stands for “exit.” It causes to stop working
on your job, after putting the ¬nishing touches on your log ¬le and on
any characters that have already been output to your gf and/or tfm
¬les. The current (incomplete) character will not be output.
9. Type ˜E™. This is like ˜X™, but it also prepares the computer to edit the
¬le that is currently reading, at the current position, so that
you can conveniently make a change before trying again.
After you type ˜H™ (or ˜h™, which also works), you™ll get a message that tries to
explain the current problem: The mathematical quantity just read by -
(i.e., mode.setup) was not followed by ˜=™ or ˜:=™, so there was nothing for
the computer to do with it. Chapter 6 explains that a space between tokens (e.g.,
˜mode setup™ ) is equivalent to a period between tokens (e.g., ˜mode.setup™ ). The
correct spelling ˜mode_setup™ would be recognized as a preloaded subroutine of
plain , but plain doesn™t have any built-in meaning for
mode.setup. Hence mode.setup appears as a sort of orphan, and
realizes that something is amiss.
In this case, it™s OK to go ahead and type return , because we really
don™t need to do the operations of mode setup when no special mode has been
selected. will continue by forgetting the isolated expression, and it
will ignore the rest of line 1 because everything after a ˜%™ sign is always ignored.
(This is another thing that will be explained in Chapter 6; it™s a handy way to
put comments into your programs.) The changes that were made
to line 1 of badio.mf therefore have turned out to be relatively harmless. But
will almost immediately encounter the mutilated semicolon in line 2:
! Extra tokens will be flushed.
<to be read again>
l.2 em#:=10pt#:
What does this mean? Type ˜H™ to ¬nd out. has no idea what to do
44 Chapter 5: Running

with a ˜:™ at this place in the ¬le, so it plans to recover by “¬‚ushing” or getting ¬‚ushing
rid of everything it sees, until coming to a semicolon. It would be a bad idea to EXPR
type return now, since you™d lose the important assignment ˜cap#:=7pt#™, and SUFFIX
that would lead to worse errors. transformations
You might type ˜X™ or ˜E™ at this point, to exit from and to
¬x the errors in lines 1 and 2 before trying again. But it™s usually best to keep
going, trying to detect and correct as many mistakes as possible in each run,
since that increases your productivity while decreasing your computer bills. An
experienced user will quit after an error only if the error is un¬xable,
or if there™s almost no chance that additional errors are present.
The solution in this case is to proceed in two steps: First type ˜1™, which
tells to delete the next token (the unwanted ˜:™); then type ˜I;™,
which inserts a semicolon. This semicolon protects the rest of line 2 from being
¬‚ushed away, so all will go well until reaches another garbled line.
The next error message is more elaborate, because it is detected while
is trying to carry out a penpos command; penpos is not a primitive
operation (it is de¬ned in plain ), hence a lot more context is given:
>> l0
! Improper transformation argument.
<to be read again>
l.10 penpos1(thick,l0)
; penpos2(.1[thin,thick],90-10);
At ¬rst, such error messages will appear to be complete nonsense to you, because
much of what you see is low-level code that you never wrote. But you
can overcome this hangup by getting a feeling for the way operates.
The bottom line shows how much progress has made so far
in the badio ¬le: It has read ˜penpos1(thick,l0)™ but not yet the semicolon,
on line 10. The penpos routine expands into a long list of tokens; indeed, this
list is so long that it can™t all be shown on two lines, and the appearances of
˜...™ indicate that the de¬nition of penpos has been truncated here. Parameter
values are often inserted into the expansion of a high-level routine; in this case,
for example, ˜(EXPR3)™ and ˜(EXPR4)™ correspond to the respective parameters
˜thick™ and ˜l0™, and ˜(SUFFIX2)™ corresponds to ˜1™. detected an
error just after encountering the phrase ˜rotated(EXPR4)™; the value of (EXPR4)
was an unde¬ned quantity (namely ˜l0™, which treats as the sub-
scripted variable ˜l0 ™ ), and rotation is permitted only when a known numeric
value has been supplied. Rotations are particular instances of what
calls transformations; hence describes this particular error by saying
that an “improper transformation argument” was present.
Chapter 5: Running 45

When you get a multiline error message like this, the best clues about
the source of the trouble are usually on the bottom line (since that is what
you typed) and on the top line (since that is what triggered the error message).
Somewhere in there you can usually spot the problem.
If you type ˜H™ now, you™ll ¬nd that has simply decided to
continue without doing the requested rotation. Thus, if you respond by typing
return , will go on as if the program had said ˜penpos1(thick,0)™.
Comparatively little harm has been done; but there™s actually a way to ¬x the
error perfectly before proceeding: Insert the correct rotation by typing
I rotated 10
and will rotate by 10 degrees as if ˜l0™ had been ˜10™.
What happens next in Experiment 5? will hiccup on the
remaining bug that we planted in the ¬le. This time, however, the typo will
not be discovered until much later, because there™s nothing wrong with line 11
as it stands. (The variable thinn is not de¬ned, but unde¬ned quantities are
no problem unless you™re doing something complicated like rotation. Indeed,
programs typically consist of equations in which there are lots of
unknowns; variables get more and more de¬ned as time goes on. Hence spelling
errors cannot possibly be detected until the last minute.) Finally comes the
moment of truth, when badio tries to draw a path through an unknown point;
and you will get an error message that™s even scarier than the previous one:
>> 0.08682thinn+144
! Undefined x coordinate has been replaced by 0.
<to be read again>
<for(l)> ...FFIX0){up}..z4(SUFFIX0){
left}..cycle; ENDFOR
<to be read again>
l.15 ... ..z3e{up}..z4e{left}..cycle;

Wow; what™s this? The expansion of penstroke involves a “for loop,” and the
error was detected in the midst of it. The expression ˜0.08682thinn+144™ just
above the error message implies that the culprit in this case was a misspelled
˜thin™. If that hadn™t been enough information, you could have gleaned another
clue from the fact that ˜z4(SUFFIX0)™ has just been read; (SUFFIX0) is the
current loop value and ˜<for(l)>™ indicates that the value in question is ˜l™,
hence z4l is under suspicion. (Sure enough, the unde¬ned x coordinate that
provoked this error can be shown to be x4l = 0.08682thinn + 144.)
46 Chapter 5: Running

In any event the mistake on line 11 has propagated too far to be ¬xable, editing
so you™re justi¬ed in typing ˜X™ or ˜E™ at this point. But type ˜S™ instead, just
for fun: This tells to plunge ahead, correcting all remaining errors
as best it can. (There will be a few more problems, since several variables still
depend on ˜thinn™.) will draw a very strange letter O before it gets
to the end of the ¬le. Then you should type ˜end™ to terminate the run.
If you try to edit badio.mf again, you™ll notice that line 2 still contains
a colon instead of a semicolon. The fact that you told to delete the
colon and to insert additional material doesn™t mean that your ¬le has changed
in any way. However, the transcript ¬le badio.log has a record of all the errors,
so it™s a handy reference when you want to correct mistakes. (Why not look at
badio.log now, and io.log too, in order to get familiar with log ¬les?)
Suppose you were doing Experiment 3 with badio instead of io, so you be-
gan by saying ˜\mode=smoke; input badio™. Then you would want to recover from the
error on line 1 by inserting a correct mode setup command, instead of by simply
return ing, because mode setup is what really establishes smoke mode. Unfortu-
nately if you try typing ˜I mode_setup™ in response to the “isolated expression” error,
it doesn™t work. What should you type instead?
By doing the ¬ve experiments in this chapter you have learned at ¬rst
hand (1) how to produce proofsheets of various kinds, including “smoke proofs”;
(2) how to make a new font and test it; (3) how to keep calm when
issues stern warnings. Congratulations! You™re on the threshold of being able to
do lots more. As you read the following chapters, the best strategy will be for
you to continue making trial runs, using experiments of your own design.
However, this has been an extremely long chapter, so you should go outside now
and get some real exercise.
Chapter 5: Running 47


Let us learn how Io™s frenzy came”
She telling her disasters manifold.
” ÆSCHYLUS, Prometheus Bound (c. 470 B.C.)

To the student who wishes to use graphical methods as a tool,
it can not be emphasized too strongly that practice in the use of that tool
is as essential as a knowledge of how to use it.
The oft-repeated pedagogical phrase, “we learn by doing,” is applicable here.
” THEODORE RUNNING, Graphical Mathematics (1927)
(page 48)

Reads What You
Chapter 6: How Reads What You Type 49

So far in this book we™ve seen lots of things that can do, but we ASCII
haven™t discussed what can™t do. We have looked at many examples string tokens
of commands that can understand, but we haven™t dwelt on the numeric tokens
symbolic tokens
fact that the computer will ¬nd many phrases unintelligible. It™s time now to underline
adopt a more systematic approach and to study the exact rules of ™s grammatical rules
language. Then we™ll know what makes sense to the machine, and we™ll also Naur
know how to avoid ungrammatical utterances. angle brackets
syntax rules
A program consists of one or more lines of text, where each
line is made up of letters, numbers, punctuation marks, and other symbols that
appear on a standard computer keyboard. A total of 95 di¬erent characters
can be employed, namely a blank space plus the 94 visible symbols of stan-
dard ASCII. (Appendix C describes the American Standard Code for Informa-
tion Interchange, popularly known as “ASCII,” under which code numbers 33
through 126 have been assigned to 94 speci¬c symbols. This particular coding
scheme is not important to a programmer; the only relevant thing
is that 94 di¬erent nonblank symbols can be used.)
converts each line of text into a series of tokens, and a
programmer should understand exactly how this conversion takes place. Tokens
are the individual lexical units that govern the computer™s activities. They are
the basic building blocks from which meaningful sequences of instructions can
be constructed. We discussed tokens brie¬‚y at the end of the previous chapter;
now we shall consider them in detail. Line 9 of the ¬le io.mf in that chapter is
a typical example of what the machine might encounter:
beginchar("O",0.8em#,cap#,0); "The letter O";
When reads these ASCII characters it ¬nds sixteen tokens:
beginchar ( "O" , 0.8 em # ,
cap # , 0 ) ; "The letter O" ;
Two of these, "O" and "The letter O", are called string tokens because they
represent strings of characters. Two of them, ˜0.8™ and ˜0™, are called numeric
tokens because they represent numbers. The other twelve”˜beginchar™, ˜(™,
etc.”are called symbolic tokens; such tokens can change their meaning while a
program runs, but string tokens and numeric tokens always have a
predetermined signi¬cance. Notice that clusters of letters like ˜beginchar™ are
treated as a unit; the same holds with respect to letters mixed with underline
characters, as in ˜mode_setup™. Indeed, the rules we are about to study will
explain that clusters of other characters like ˜0.8™ and ˜:=™ are also considered
to be indecomposable tokens. has a de¬nite way of deciding where
one token stops and another one begins.
It™s often convenient to discuss grammatical rules by formulating them
in a special notation that was introduced about 1960 by John Backus and Peter
Naur. Parts of speech are represented by named quantities in angle brackets,
and syntax rules are used to express the ways in which those quantities can
50 Chapter 6: How Reads What You Type

be built up from simpler units. For example, here are three syntax rules that decimal digit
digit string
completely describe the possible forms of numeric tokens: numeric token
decimal digit ’’ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 semantics
digit string ’’ decimal digit | digit string decimal digit numeric tokens, rounded values
numeric tokens, maximum value
numeric token ’’ digit string | . digit string space
| digit string . digit string period
decimal point
percent sign
The ¬rst rule says that a decimal digit is either ˜0™ or ˜1™ or · · · or ˜9™; thus comments
it must be one of the ten numerals. The next rule says that a digit string is decimal digit
double-quote mark
either a decimal digit or a digit string followed by a decimal digit ; thus it
must be a sequence of one or more digits. Finally, a numeric token has one of
three forms, exempli¬ed respectively by ˜15™, ˜.05™, and ˜3.14159™.
Syntax rules explain only the surface structure of a language, not the
underlying meanings of things. For example, the rules above tell us that ˜15™
is a numeric token , but they don™t imply that ˜15™ has any connection with
the number ¬fteen. Therefore syntax rules are generally accompanied by rules
of semantics, which ascribe meanings to the strings of symbols that meet the
conditions of the syntax. In the case of numeric tokens, the principles of ordinary
decimal notation de¬ne the semantics, except that deals only with
numbers in a limited range: A numeric token must be less than 4096, and its
value is always rounded to the nearest multiple of 65536 . Thus, for example,
1 6554 1
˜.1™ does not mean 10 , it means 65536 (which is slightly greater than 10 ). It
turns out that the tokens ˜.099999™ and ˜0.10001™ both have exactly the same
meaning as ˜.1™, because all three tokens represent the value 65536 .
Are the following pairs of numeric tokens equivalent to each other, when they
appear in programs? (a) 0 and 0.00001; (b) 0.00001 and 0.00002;
(c) 0.00002 and 0.00003; (d) 04095.999999 and 10000?

converts each line of text into a sequence of tokens by re-
peating the following rules until no more characters remain on the line:
1) If the next character is a space, or if it™s a period ( ˜.™ ) that isn™t followed
by a decimal digit or a period, ignore it and move on.
2) If the next character is a percent sign ( ˜%™ ), ignore it and also ignore
everything else that remains on the current line. (Percent signs therefore
allow you to write comments that are unseen by .)
3) If the next character is a decimal digit or a period that™s followed by
a decimal digit, the next token is a numeric token, consisting of the
longest sequence of contiguous characters starting at the current place
that satis¬es the syntax for numeric token above.
4) If the next character is a double-quote mark ( ˜"™ ), the next token is a
string token, consisting of all characters from the current place to the
next double-quote, inclusive. (There must be at least one more double-
quote remaining on the line, otherwise will complain about
Chapter 6: How Reads What You Type 51

an “incomplete string.”) A string token represents the sequence of incomplete string
characters between the double-quotes. table of character classes
5) If the next character is a parenthesis ( ˜(™ or ˜)™ ), a comma ( ˜,™ ), or a HOLLAND
semicolon ( ˜;™ ), the next token is a symbolic token consisting of that COWPER
single character. Homer
6) Otherwise the next token is a symbolic token consisting of the next
character together with all immediately following characters that appear
in the same row of the following table:

(see rules 1, 3, 6)
(see rule 5; these characters are “loners”)
(see rule 4 for details about string tokens)
(see rule 3 for details about numeric tokens)
(see rule 2 for details about comments)
The best way to learn the six rules about tokens is to work the following exercise,
after which you™ll be able to read any input ¬le just as the computer does.
What tokens does ¬nd in the (ridiculous) line
xx3.1.6..[[a+-bc_d.e] ]"a %" <|>(($1. 5"+-""" % weird?
Criticize the following statement: ignores all spaces in the input.
True or false: If the syntax for numeric token were changed to include a
fourth alternative, ˜ digit string .™, the meaning of programs would not
change in any way.

Yet wee with all our seeking could see no tokens.
” PHILEMON HOLLAND, Camden™s Brittania (1610)

Unpropitious tokens interfered.
” WILLIAM COWPER, Homer™s Iliad (1791)
(page 52)

Chapter 7: Variables 53

One of ™s most important concepts is the notion of a variable” variable
data structure
something that can take on a variety of di¬erent values. Indeed, this is one of primitive
the most important concepts in all of mathematics, and variables play a promi- macro
nent rˆle in almost all computer languages. The basic idea is that a program
o tag
manipulates data, and the data values are stored in little compartments of a
computer™s memory. Each little compartment is a variable, and we refer to an
item of data by giving its compartment a name.
For example, the io.mf program for the letter in Chapter 5 contains
lots of variables. Some of these, like ˜x1l™ and ˜y1™, represent coordinates. Others,
like ˜up™, represent directions. The variables ˜em#™ and ˜thin#™ stand for physical,
machine-independent distances; the analogous variables ˜em™ and ˜thin™ stand for
the corresponding machine-dependent distances in units of pixels.
These examples indicate that di¬erent variables are often related to each
other. There™s an implicit connection between ˜em#™ and ˜em™, between ˜x1™ and
˜y1™; the ˜penpos ™ convention sets up relationships between ˜x1l™, ˜x1™, and ˜x1r™.
By choosing the names of variables carefully, programmers can make their pro-
grams much easier to understand, because the relationships between variables
can be made to correspond to the structure of their names.
In the previous chapter we discussed tokens, the atomic elements from
which all programs are made. We learned that there are three kinds
of tokens: numeric (representing numbers), string (representing text), and sym-
bolic (representing everything else). Symbolic tokens have no intrinsic meaning;
any symbolic token can stand for whatever a programmer wants it to represent.
Some symbolic tokens do, however, have prede¬ned primitive meanings,
when begins its operations. For example, ˜+™ stands initially for
“plus,” and ˜;™ stands for “¬nish the current statement and move on to the next
part of the program.” It is customary to let such tokens retain their primitive
meanings, but any symbolic token can actually be assigned a new meaning as a
program is performed. For example, the de¬nition of ˜test_I™ in io.mf makes
that token stand for a macro, i.e., a subroutine. We™ll see later that you can
instruct to ˜let plus=+™, after which ˜plus™ will act just like ˜+™ did.
divides symbolic tokens into two categories, depending on
their current meaning. If the symbolic token currently stands for one of -
™s primitive operations, or if it has been de¬ned to be a macro, it is called a
spark; otherwise it is called a tag. Almost all symbolic tokens are tags, because
only a few are de¬ned to be sparks; however, programs typically in-
volve lots of sparks, because sparks are what make things happen. The symbolic
tokens on the ¬rst ¬ve lines of io.mf include the following sparks:

mode_setup ; := / define_pixels ( , )

and the following tags:

em # pt cap thin thick o
54 Chapter 7: Variables

(some of which appear several times). Tags are used to designate variables, but Pascal
sparks cannot be used within a variable™s name. su¬x
Some variables, like ˜em#™, have names that are made from more than subscript
one token; in fact, the variable ˜x1l™ is named by three tokens, one of which is subscript
numeric. has been designed so that it is easy to make compound arrays
names that correspond to the relations between variables. Conventional pro- [
gramming languages like Pascal would refer to ˜x1l™ by the more cumbersome ]
notation ˜x[1].l™; it turns out that ˜x[1].l™ is an acceptable way to designate internal quantities
the variable x1l in a program, but the shorthand form ˜x1l™ is a fontmaking
great convenience because such variables are used frequently.
Here are the formal rules of syntax by which understands
the names of variables:
variable ’’ tag su¬x
su¬x ’’ empty | su¬x subscript | su¬x tag
subscript ’’ numeric token | [ numeric expression ]
First comes a tag, like ˜x™; then comes a su¬x to the tag, like ˜1l™. The su¬x
might be empty, or it might consist of one or more subscripts or tags that are
tacked on to the original tag. A subscript is a numeric index that permits you
to construct arrays of related variables. The subscript is either a single numeric
token, or it is a formula enclosed in square brackets; in the latter case the formula
should produce a numeric value. For example, ˜x[1]™ and ˜x[k]™ and ˜x[3-2k]™
all mean the same thing as ˜x1™, if k is a variable whose value is 1. But ˜x.k™ is
not the same; it is the tag ˜x™ su¬xed by the tag ˜k™, not the tag ˜x™ subscripted
by the value of variable k.
The variables ˜x1™ and ˜x01™ and ˜x1.00™ are identical. Since any numeric token
can be used as a subscript, fractional indices are possible; for example, ˜x1.5™
is the same as ˜x[3/2]™. Notice, however, that ˜B007™ and ˜B.007™ are not the same
variable, because the latter has a fractional subscript.
makes each su¬x as long as possible. In other words, a su¬x
is always extended if it is followed by a subscript or a tag .
Explain how to type a reference to the doubly subscripted variable ˜a[1][5]™
without using square brackets.
Is it possible to refer to any variable without using square brackets?
Jonathan H. Quick (a student) used ˜a.plus1™ as the name of a variable at
the beginning of his program; later he said ˜let plus=+™. How could he refer to the
variable ˜a.plus1™ after that?
has several special variables called internal quantities that are
intimately wired-in to the computer™s behavior. For example, there™s an in-
ternal quantity called ˜fontmaking™ that controls whether or not a tfm ¬le is produced;
Chapter 7: Variables 55

another one called ˜tracingtitles™ governs whether or not titles like "The letter O" tracingtitles
appear on your terminal; still another one called ˜smoothing™ a¬ects the digitization of
curves. (A complete list of ™s internal quantities appears in Chapter 25.) tag
The name of an internal quantity acts like a tag, but internal quantities cannot be italic type
su¬xed. Thus, the syntax rule for variable should actually be replaced by a slightly types
more complicated pair of rules: boolean
variable ’’ external tag su¬x | internal quantity false
tag ’’ external tag | internal quantity string
True or false: Every variable is a legal su¬x . pair
The ˜[™ and ˜]™ that appear in the syntax for subscript stand for any sym-
bolic tokens whose current meanings are the same as ™s primitive
meanings of left and right bracket, respectively; those tokens don™t necessarily have to
be brackets. Conversely, if the meanings of the tokens ˜[™ and ˜]™ have been changed,
brackets cannot be used to delimit subscripts. Similar remarks apply to all of the sym-
bolic tokens in all of the syntax rules from now on. doesn™t look at the
form of a token; it considers only a token™s current meaning.

The examples of programs in this book have used two di¬er-
ent typographic conventions. Sometimes we refer to variables by using italic type
and/or genuine subscripts, e.g., ˜em ™ and ˜x2r ™; but sometimes we refer to those
same variables by using a typewriter-like style of type, e.g., ˜em™ and ˜x2r™. In
general, the typewriter style is used when we are mainly concerned with the way
a programmer is supposed to type something that will appear on the terminal
or in a ¬le; but fancier typography is used when we are focusing on the meaning
of a program rather than its ASCII representation. It should be clear how to
convert the fancier form into tokens that can actually understand.
In general, we shall use italic type only for tags (e.g., em , x , r ), while boldface
and roman type will be used for sparks (e.g., draw, ¬ll, cycle, rotated, sqrt).
Tags that consist of special characters instead of letters will sometimes get special
treatment; for example, em# and z2™ might be rendered em # and z2 , respectively.

The variables we™ve discussed so far have almost always had numbers as
their values, but in fact ™s variables are allowed to assume values of
eight di¬erent types. A variable can be of type
boolean, representing the values ˜true™ or ˜false™;
string, representing sequences of ASCII characters;
path, representing a (possibly curved) line;
pen, representing the shape of a pen nib;
picture, representing an entire pattern of pixels;
transform, representing the operations of scaling, rotating, shifting, re-
¬‚ecting, and/or slanting;
pair, representing two numbers (e.g., a point or a vector);
numeric, representing a single number.
56 Chapter 7: Variables

If you want a variable to represent something besides a number, you must ¬rst type declaration
give a type declaration that states what the type will be. But if you refer to a []
variable whose type has not been declared, won™t complain, unless collective subscripts
value, disappearance of
you try to use it in a way that demands a value that isn™t numeric. declaration
Type declarations are easy. You simply name one of the eight types, type
then you list the variables that you wish to declare for that type. For example, string
the declaration path
pair right , left , a.p
says that right and left and a.p will be variables of type pair, so that equations numeric
right = ’left = 2a.p = (1, 0)
can be given later. These equations, incidentally, de¬ne the values right = (1, 0),
left = (’1, 0), and a.p = (.5, 0). (Plain has the stated values of
right and left already built in.)
The rules for declarations are slightly trickier when subscripts are in-
volved, because insists that all variables whose names are identical
except for subscript values must have the same type. It™s possible to set things
up so that, for example, a is numeric, a.p is a pair, a.q is a pen, a.r is a path,
and a1 is a string; but if a1 is a string, then all other variables a2 , a3 , etc.,
must also be strings. In order to enforce this restriction, allows only
“collective” subscripts, represented by empty brackets ˜[]™, to appear in type
declarations. For example,
path r, r[], x[]arc, f[][]
declares r and all variables of the forms r[i], x[i]arc , and f [i][j] to be path
variables. This declaration doesn™t a¬ect the types or values of other variables
like r[ ]arc ; it a¬ects only the variables that are speci¬cally mentioned.
Declarations destroy all previous values of the variables being de¬ned.
For example, the path declaration above makes r and r[i] and x[i]arc and f [i][j]
unde¬ned, even if those variables previously had paths as their values. The idea
is that all such variables will start out with a clean slate so that they can receive
appropriate new values based on subsequent equations.
Numeric variables don™t need to be declared. Therefore is there ever any reason
for saying ˜numeric x™ ?
The formal syntax rules for type declarations explain these grammatical con-
ventions precisely. If the symbolic token that begins a declared variable was
previously a spark, it loses its former meaning and immediately becomes a tag.
declaration ’’ type declaration list
type ’’ boolean | string | path | pen
| picture | transform | pair | numeric
Chapter 7: Variables 57

declaration list ’’ declared variable declaration list
| declaration list , declared variable ,
declared variable
declared variable ’’ symbolic token declared su¬x declared su¬x
declared su¬x ’’ empty | declared su¬x tag DARWIN
| declared su¬x [ ] LOCKYER

Find three errors in the supposed declaration ˜transform t42,24t,,t,path™.

Beings low in the scale of nature are
more variable than those which are higher.
” CHARLES DARWIN, On the Origin of Species (1859)

Among the variables, Beta (¬) Persei, or Algol,
is perhaps the most interesting, as its period is short.
” J. NORMAN LOCKYER, Elements of Astronomy (1870)
(page 58)

Chapter 8: Algebraic Expressions 59

programmers express themselves algebraically by writing algebraic expressions


. 2
( 13)