<< . .

. 34
( : 45)

. . >>

xmin_ := min(xlist); xmax_ := max(xlist);
ymin_ := min(ylist); ymax_ := max(ylist); chardp
for x=xlist: proofrule((x,ymin_), (x,ymax_)); endfor
for y=ylist: proofrule((xmin_,y), (xmax_,y)); endfor d
italic correction
Finally we have a few macros that allow further communication with the
hardcopy proof-drawing routine of Appendix H. You can change the fonts, the thickness
of proof rules, and the position of the image on its page.

vardef titlefont suffix $ = special "titlefont "&str$ enddef;
vardef labelfont suffix $ = special "labelfont "&str$ enddef;
vardef grayfont suffix $ = special "grayfont "&str$ enddef;
vardef slantfont suffix $ = special "slantfont "&str$ enddef;
def proofoffset primary z = % shift proof output by z
special "offset"; numspecial xpart z; numspecial ypart z enddef;
vardef proofrulethickness expr x =
special "rulethickness"; numspecial x enddef;

7. Character and font administration. After this elaborate preparation, we™re ¬nally
ready to consider the beginchar . . . endchar framework for the individual characters of
a font. Each beginchar begins a group, which should end at the next endchar. Then
beginchar stores the given character code and device-independent box dimensions
™s internal variables charcode , charwd , charht , and chardp . Then it
computes the device-dependent box dimensions w , h , and d . Finally it clears the z
variables, the current picture, and the current pen.

def beginchar(expr c,w_sharp,h_sharp,d_sharp) =
charcode:=if known c: byte c else: 0 fi;
charwd:=w_sharp; charht:=h_sharp; chardp:=d_sharp;
w:=hround(charwd*hppp); h:=vround(charht*hppp); d:=vround(chardp*hppp);
charic:=0; clearxy; clearit; clearpen; scantokens extra_beginchar;

The italic correction is normally zero, unless the user gives an ˜italcorr™ command;
even then, the correction stays zero unless the given value is positive:

def italcorr expr x_sharp = if x_sharp>0: charic:=x_sharp fi enddef;
276 Appendix B: Basic Operations

When we want to change the pixel width w from even to odd or vice versa, the change width
change width macro does the right thing.
extra beginchar
extra endchar
def change_width = bounding box
w:=w if w>charwd*hppp:- else:+ fi 1 enddef; makebox
italic correction
(The user might also decide to change w in some other way.) The current value of w maketicks
font size etc
at the time of endchar will be the “o¬cial” pixel width of the character, chardx , that
is shipped to the gf output ¬le.
def endchar =
scantokens extra_endchar;
if proofing>0: makebox(proofrule); fi
chardx:=w; % desired width of the character in pixels
if displaying>0: makebox(screenrule); showit; fi
endgroup enddef;
Extensions to these routines can be provided by putting commands in the string vari-
ables extra beginchar and extra endchar .
string extra_beginchar, extra_endchar;
A “bounding box” that surrounds the character according to the speci¬cations
given in beginchar is produced by makebox, which takes into account the possibility
that pixels might not be square. An extra line is drawn to mark the width of the
character with its italic correction included, if this correction is nonzero.
def makebox(text r) =
for y=0,h.o_,-d.o_: r((0,y),(w,y)); endfor % horizontals
for x=0,w: r((x,-d.o_),(x,h.o_)); endfor % verticals
if charic<>0: r((w+charic*hppp,h.o_),(w+charic*hppp,.5h.o_)); fi
The maketicks routine is an alternative to makebox that draws less con-
spicuous lines. This makes it easier to visualize a character™s appearance near the edges
of its bounding box.
def maketicks(text r) =
for y=0,h.o_,-d.o_: r((0,y),(10,y)); r((w-10,y),(w,y)); endfor
for x=0,w: r((x,10-d.o_),(x,-d.o_)); r((x,h.o_-10),(x,h.o_)); endfor
if charic<>0: r((w+charic*hppp,h.o_-10),(w+charic*hppp,h.o_)); fi
Overall information about the font as a whole is generally supplied by the
following commands, which are explained in Appendix F.
def font_size expr x = designsize:=x enddef;
def font_slant expr x = fontdimen 1: x enddef;
def font_normal_space expr x = fontdimen 2: x enddef;
def font_normal_stretch expr x = fontdimen 3: x enddef;
def font_normal_shrink expr x = fontdimen 4: x enddef;
Appendix B: Basic Operations 277

def font_x_height expr x = fontdimen 5: x enddef; z
screen rows
def font_quad expr x = fontdimen 6: x enddef;
screen cols
def font_extra_space expr x = fontdimen 7: x enddef; openit
def font_identifier expr x = font_identifier_:=x enddef; clearxy
def font_coding_scheme expr x = font_coding_scheme_:=x enddef; clearit
string font_identifier_, font_coding_scheme_;
font_identifier_=font_coding_scheme_="UNSPECIFIED"; command line
8. The endgame. What have we left out? A few miscellaneous things still need to be
handled. First, we almost forgot to de¬ne the z convention for points:
vardef z@#=(x@#,y@#) enddef;
Then we need to do something rudimentary about ™s “windows.”
newinternal screen_rows, screen_cols, currentwindow;
screen_rows:=400; % these values should be corrected,
screen_cols:=500; % by reading in a separate file after plain.mf
def openit = openwindow currentwindow
from origin to (screen_rows,screen_cols) at (-50,300) enddef;
def showit = openit; let showit=showit_; showit enddef; % first time only
def showit_ = display currentpicture inwindow currentwindow enddef;
Plain has several other terse commands like ˜openit™ and ˜showit™:
def clearxy = save x,y enddef;
def clearit = currentpicture:=nullpicture enddef;
def shipit = shipout currentpicture enddef;
def cullit = cull currentpicture dropping (-infinity,0) enddef;

The next several macros are handy things to put on your command line when
you are starting a job (i.e., just before ˜input font ¬le name ™):
screenchars. Say this when you™re making a font but want the characters to
be displayed just before they are shipped out.
screenstrokes. Say this when you™re in proof mode and want to see each
stroke as it™s added to the current picture.
imagerules. Say this when you want to include the bounding box in the
current character, before you begin to draw it.
gfcorners. Say this when you expect to make proofsheets with large pixels,
from a low-resolution font.
nodisplays. Say this to save computer time when you don™t want proof mode
to display each character automatically.
notransforms. Say this to save computer time when you know that the current
transform is the identity.
def screenchars = % endchar should ˜showit™
extra_endchar:=extra_endchar&"showit;" enddef;
def screenstrokes = % every stroke should ˜showit™
def addto_currentpicture text t=
addto currentpicture t; showit enddef; enddef;
278 Appendix B: Basic Operations

def imagerules = % a box should be part of the character image imagerules
extra_beginchar:=extra_beginchar & "makebox(screenrule);" enddef;
def gfcorners = % ˜maketicks™ should send rules to the gf file
extra_setup:=extra_setup & "let makebox=maketicks;proofing:=1;" enddef; end
clear pen memory
def nodisplays = % endchar shouldn™t ˜showit™
mode setup
extra_setup:=extra_setup & "displaying:=0;" enddef; mode
def notransforms = % currenttransform should not be used
let t_ = \ enddef; screen rows
screen cols
We make ˜bye™ synonymous with ˜end™, just in case TEX users expect - ¬llin
programs to end like TEX documents do.
let bye = end; outer end,bye;
And ¬nally, we provide the default environment that a user gets when simple
experiments like those at the beginning of Chapter 5 are desired.
clear_pen_memory; % initialize the ˜savepen™ mechanism
mode_setup; % establish proof mode as the default
numeric mode,mag; % but leave mode and mag undefined
Whew! That™s the end of the plain.mf ¬le.
9. Adapting to local conditions. In order to make plain programs inter-
changeable between di¬erent computers, everybody should use the same plain.mf base.
But there are some things that clearly should be customized at each installation:
Additional modes should be de¬ned, so that fonts can be made for whatever
output devices are of interest.
The proper localfont mode should be established.
The correct numbers should be assigned to screen rows and screen cols .
Here™s an example of a supplementary ¬le ˜local.mf™ that would be appropriate for
a computer center with the hypothetical cheapo and luxo printers described in Chap-
ter 11. We assume that cheapo mode is to be identical to lowres mode, except that
the cheapo fonts should be generated with a negative value of ¬llin (because cheapo
tends to make diagonal lines lighter than normal, not heavier). The terminal screens
are assumed to be 768 pixels wide and 512 pixels high.
% A file to be loaded after "plain.mf".
screen_rows:=512; screen_cols:=768;
mode_def cheapo = % cheapo mode: to generate fonts for cheapo
lowres_; % do as in lowres mode, except:
fillin:=-.1; % compensate for lighter diagonals
mode_def luxo = % luxo mode: to generate fonts for luxo
proofing:=0; % no, we™re not making proofs
fontmaking:=1; % yes, we are making a font
tracingtitles:=1; % yes, show titles online
pixels_per_inch:=2000; % almost 30 pixels per pt
Appendix B: Basic Operations 279

blacker:=.2; % make pens a teeny bit blacker bye
fillin:=.1; % but compensate for heavy diagonals
o_correction:=1; % and keep the full overshoot Computer Modern
localfont:=cheapo; DRAYTON
The macro ˜bye™ might also be rede¬ned, as suggested at the close of Appendix F.
To prepare a preloaded base ¬le at this installation, a suitably privileged
person should run INIMF in the following way:
This is METAFONT, Version 2.0 (INIMF) 8 NOV 1989 10:09
Preloading the plain base, version 2.0)
*input local
Beginning to dump on file plain.base
(The stu¬ after ˜**™ or ˜*™ is typed by the user; everything else is typed by the system.
A few more messages actually come out.)
Notice that local.mf does not include any new macros or features that a
programmer could use in a special way. Therefore it doesn™t make plain
incompatible with implementations at other computing centers.
Changes and/or extensions to the plain.mf macros should never be made,
unless the resulting base ¬le is clearly distinguished from the standard plain base. But
new, di¬erently named bases are welcome. For example, the author prepared a special
base for the Computer Modern fonts, so that they could be generated without ¬rst
reading the same 700 lines of macro de¬nitions each time. To load this base at high
speed, he can type ˜&cm™ after ™s initial ˜**™. (Or, on some machines, he has
a special version called ˜cmmf™ in which the new base is already present.)

None but the Base, in baseness doth delight.
” MICHAEL DRAYTON, Robert, Duke of Normandy (1605)

So far all was plain sailing, as the saying is;
but Mr. Till knew that his main di¬culties were yet to come.
” FRANCIS E. PAGET, Milford Malvoisin (1842)
(page 280)

Appendix C: Character Codes 281

Di¬erent computers tend to have di¬erent ways of representing the characters in codes
¬les of text, but gives the same results on all machines, because it oct
converts everything to a standard internal code when it reads a ¬le. hex
also converts back from its internal representation to the appropriate external
code, when it writes a ¬le of text; therefore most users need not be aware of the
fact that the codes have actually switched back and forth inside the machine.
The purpose of this appendix is to de¬ne ™s internal code,
which has the same characteristics on all implementations of . The
existence of such a code is important, because it makes programs
portable. ™s scheme is based on the American Standard Code for
Information Interchange, known popularly as “ASCII.” There are 128 codes,
numbered 0 to 127; we conventionally express the numbers in octal notation, from
oct"000" to oct"177", or in hexadecimal notation, from hex"00" to hex"7F".
Thus, the value of ASCII"b" is normally called oct"142" or hex"62", not 98.
In the ASCII scheme, codes oct"000" through oct"037" and code oct"177"
are assigned to special functions; for example, code oct"007" is called BEL, and
it means “Ring the bell.” The other 95 codes are assigned to visible symbols and
to the blank space character. Here is a chart that shows ASCII codes in such a
way that octal and hexadecimal equivalents can easily be read o¬:
´0 ´1 ´2 ´3 ´4 ´5 ´6 ´7
´04x ! " # $ % & ™
´05x ( ) * + , - . /
´06x 0 1 2 3 4 5 6 7
´07x 8 9 : ; < = > ?
´10x @ A B C D E F G
´11x H I J K L M N O
´12x P Q R S T U V W
´13x X Y Z [ \ ] ^ _
´14x ˜ a b c d e f g
´15x h i j k l m n o
´16x p q r s t u v w
´17x x y z { | } ˜ DEL
˝8 ˝9 ˝A ˝B ˝C ˝D ˝E ˝F
Ever since ASCII was established in the early 1960s, people have had
di¬erent ideas about what to do with positions oct"000" thru oct"037" and
oct"177", because most of the functions assigned to those codes are appropriate
282 Appendix C: Character Codes

only for special purposes like ¬le transmission, not for applications to printing Knuth
or to interactive computing. Manufacturers soon started producing line printers ¡=
that were capable of generating 128 characters, 33 of which were tailored to ¿=
the special needs of particular customers; part of the advantage of a standard
code was therefore lost. An extended ASCII code intended for text editing and
interactive computing was developed at several universities about 1965, and for
many years there have been terminals in use at Stanford, MIT, Carnegie-Mellon,
and elsewhere that have 120 or 121 symbols, not just 95. For example, the author
developed on a keyboard that includes the symbols ˜≠™, ˜¤™, ˜≥™, and
˜←™, which are easier to use than the character pairs ˜<>™, ˜<=™, ˜>=™, and ˜:=™. The
full character set looks like this:

´0 ´1 ´2 ´3 ´4 ´5 ´6 ´7
´00x … “ ± β § ¬ ∈ π
´01x » γ δ ‘ ± • ∞ ‚
´02x ‚ ⊃ © ∪ ∀ ∃ — ”
´03x ← ’ ≠ — ¤ ≥ ≡ ∨
´04x ! " # $ % & ™
´05x ( ) * + , ’ . /
´06x 0 1 2 3 4 5 6 7
´07x 8 9 : ; < = > ?
´10x @ A B C D E F G
´11x H I J K L M N O
´12x P Q R S T U V W
´13x X Y Z [ \ ] ^ _
´14x ˜ a b c d e f g
´15x h i j k l m n o
´16x p q r s t u v w
´17x x y z { | } ˜ «
˝8 ˝9 ˝A ˝B ˝C ˝D ˝E ˝F

can also be con¬gured to accept any or all of the character codes
128“255. However, programs that make use of anything in addition
to the 95 standard ASCII characters cannot be expected to run on other systems,
so the use of extended character sets is discouraged.
A possible middle ground has been suggested, based on the fact that it™s
easy to write a program that converts extended-character ¬les into standard ¬les
by substituting ˜<>™ for ˜≠™, etc. In the author™s implementation at Stanford, the
symbols ˜≠™, ˜¤™, ˜≥™, and ˜←™ are considered to be in the same class as ˜<™, ˜=™, ˜:™,
and ˜>™ when tokens are formed (see Chapter 6). Tokens like ˜≠=™ and ˜<≥™ are
therefore distinct, although they both become ˜<>=™ after conversion. As long as
Appendix C: Character Codes 283

such tokens are avoided, the author™s programs can easily be expurgated into a WILKINS
portable form for general distribution. (Another feasible approach would have
been to convert nonstandard codes to character pairs during ™s input
process; that would have been slightly less e¬cient.)
Computers with non-ASCII character sets should specify a correspon-
dence between 95 distinct characters and the standard ASCII codes oct"040"
thru oct"176". programs written on any such machines will be
completely interchangeable with each other.

If any shall suggest, that some of the Enquiries here insisted upon
(as particularly those about the Letters of the Alphabet)
do seem too minute and trivial, for any prudent Man
to bestow his serious thoughts and time about.
Such Persons may know, that the discovery
of the true nature and Cause of any the most minute thing,
doth promote real Knowledge,
and therefore cannot be un¬t for any Mans endeauours,
who is willing to contribute to the advancement of Learning.
” JOHN WILKINS, Towards a Real Character (1668)

Clearly even the simple A.B.C. is a thing of mystery.
Like all codes, it should not be tri¬‚ed with,
but it is to be feared that in modern times
it has not always been respected.
” STANLEY MORISON, On Type Faces (1923)
(page 284)

Dirty Tricks
Appendix D: Dirty Tricks 285

Any powerful computer language can be used in ways that go considerably be- Hobby
yond what the language designer originally had in mind, especially when macro mouth
expansion is possible. Sometimes the unexpected constructions are just amus- stomach

<< . .

. 34
( : 45)

. . >>