§1  GFtoPXL  INTRODUCTION 1

1. Introduction. The utility program reads binary generic-font (“ ”) files that are produced by font compilers such as , and converts them into PXL Matrix Format (“ ”) files. While it is usually possible to write driver programs for dot matrix outpot devices that accept input files, there are situations where one may want to use an old program to load recently created information. can be used to generate the required files. This program, in its handling of the input to produce an image array , follows the example set by .

The banner string defined here should be changed whenever gets modified. define banner ≡ ´ ␣ ␣ ␣ ␣ ´ { printed when the program starts } define resolution ≡ 200.0 { pixelx per inch, standard for pxl files }

2. Some of the code below is intended to be used only when debugging this program. Such code will not normally be compiled; it is delimited by the codewords ‘debug … gubed’, with apologies to people who wish to preserve the purity of English. For even more drastic and voluminous output, we use eebug .

define debug ≡ define gubed ≡ define eebug ≡ { change this to ‘eebug ≡ ’ when really debugging } define gubee ≡ { change this to ‘gubee ≡ ’ when really debugging } format debug ≡ begin format gubed ≡ end format eebug ≡ begin format gubee ≡ end

3. This program is written in standard Pascal, except where it is necessary to use extensions; for example, one extension is to use a default case as in , , etc. All places where nonstandard constructions are used have been listed in the index under “system dependencies.”

define othercases ≡ others : { default for cases not listed explicitly } define endcases ≡ end { follows the default case in an extended case statement } format othercases ≡ else format endcases ≡ end

4. The binary input comes from gf file, and the output font is written on pxl file. Status reporting and error messages appear on Pascal’s standard output file. The term print is used instead of write when this program writes on output , so that all such output could easily be redirected if desired.

define print (#) ≡ write(#) define print ln(#) ≡ write ln(#) define print nl ≡ write ln

program GF to PXL(gf file, pxl file, output ); label ⟨ Labels in the outer block 5 ⟩ const ⟨ Constants in the outer block 6 ⟩ type ⟨ Types in the outer block 12 ⟩ var ⟨ Globals in the outer block 10 ⟩ procedure initialize; { this procedure gets things started properly }

var i: integer ; { loop index for initializations } begin print ln(banner ); ⟨ Set initial values 15 ⟩ end;

2  INTRODUCTION  GFtoPXL §5

5. If the program has to stop prematurely, it goes to the ‘final end ’.

define final end = 9999 { label for the end of it all } ⟨ Labels in the outer block 5 ⟩ ≡

final end ;

This code is used in section 4.

6. The following parameters can be changed at compile time to extend or reduce GF to PXL’s capacity. ⟨ Constants in the outer block 6 ⟩ ≡

line length = 79; { bracketed lines of output will be at most this long } terminal line length = 150;

{ maximum number of characters input in a single line of input from the terminal } max glyph no = 127; { maximum glyph number in font, later change to 255 } top pixel = 700; { boundary of pixel image of glyph } bot pixel = −250; left pixel = −250; right pixel = 750;

This code is used in section 4.

7. Here are some macros for common programming idioms.

define incr (#) ≡ # ← # + 1 { increase a variable by unity } define decr (#) ≡ # ← # − 1 { decrease a variable by unity } define negate(#) ≡ # ← −# { change the sign of a variable } define do nothing ≡ { empty statement }

8. If the file is badly malformed, the whole process must be aborted; will give up, after issuing an error message about the symptoms that were noticed.

Such errors might be discovered inside of subroutines inside of subroutines, so a procedure called jump out has been introduced. This procedure, which simply transfers control to the label final end at the end of the program, contains the only non-local goto statement in .

define abort (#) ≡ begin print (´ ␣´ , #); jump out ; end

define bad gf (#) ≡ abort (´ ␣ ␣ ␣´ , #, ´ ´ ) procedure jump out ;

begin goto final end ; end;

9. We steal the following routine from .

define unity ≡ ´ 200000 { 2^{16}, represents 1.00000 } procedure print scaled (s : integer ); { prints scaled real, rounded to five digits }

var delta: integer ; { amount of allowable inaccuracy } begin if s < 0 then

begin print (´ ´ ); negate(s); { print the sign, if negative }

end; print (s div unity : 1); { print the integer part } s ← 10 ∗ (s mod unity ) + 5; if s ≠ 5 then

begin delta ← 10; print (´ ´ );

repeat if delta > unity then s ← s + ´ 100000 − (delta div 2); { round the final digit }

print (chr (ord (´ ´ ) + (s div unity ))); s ← 10 ∗ (s mod unity ); delta ← delta ∗ 10; until s ≤ delta; end;

end;

§10  GFtoPXL  OPTIONAL MODES OF OUTPUT 3

10. Optional modes of output. The following is left in the program to simplify the addition of some input and output routines should these be needed later.

The input ln routine waits for the user to type a line at his or her terminal; then it puts ASCII-code equivalents for the characters on that line into the buffer array. The term in file is used for terminal input, and term out for terminal output. ⟨ Globals in the outer block 10 ⟩ ≡ buffer : array [0 . . terminal line length] of ASCII code; term in: text file; { the terminal, considered as an input file } term out : text file; { the terminal, considered as an output file }

See also sections 14, 25, 28, 34, 36, 39, 52, 54, 59, and 68. This code is used in section 4.

11. Humdrum. function lower casify (c : ASCII code): ASCII code;

begin if (c ≥ ) ∧ (c ≤ ) then lower casify ← c + −

else lower casify ← c;

end;

4  THE CHARACTER SET  GFtoPXL §12
12. The character set. Like all programs written with the  system,  can be used with any

character set. But it uses ASCII code internally, because the programming for portable input-output is easier when a fixed internal code is used.

The next few sections of have therefore been copied from the analogous ones in the system routines. They have been considerably simplified, since need not deal with the controversial ASCII codes less than ´ 40 . If such codes appear in the file, they will be printed as question marks. ⟨ Types in the outer block 12 ⟩ ≡

ASCII code = ␣ . . ; { a subrange of the integers }

See also sections 13, 24, 33, and 35. This code is used in section 4.

13. The original Pascal compiler was designed in the late 60s, when six-bit character sets were common, so it did not make provision for lower case letters. Nowadays, of course, we need to deal with both upper and lower case alphabets in a convenient way, especially in a program like . So we shall assume that the Pascal system being used for has a character set containing at least the standard visible characters of ASCII code ( through ).

Some Pascal compilers use the original name char for the data type associated with the characters in text files, while other Pascals consider char to be a 64-element subrange of a larger data type that has some other name. In order to accommodate this difference, we shall use the name text char to stand for the data type of the characters in the output file. We shall also assume that text char consists of the elements chr (first text char ) through chr (last text char ), inclusive. The following definitions should be adjusted if necessary.

define text char ≡ char { the data type of characters in text files }

define first text char = 0 { ordinal number of the smallest element of text char }

define last text char = 127 { ordinal number of the largest element of text char } ⟨ Types in the outer block 12 ⟩ +≡

text file = packed file of text char ;

14. The processor converts between ASCII code and the user’s external character set by means of arrays xord and xchr that are analogous to Pascal’s ord and chr functions. ⟨ Globals in the outer block 10 ⟩ +≡ xord : array [text char ] of ASCII code; { specifies conversion of input characters } xchr : array [0 . . 255] of text char ; { specifies conversion of output characters }

§15  GFtoPXL  THE CHARACTER SET 5

15. Under our assumption that the visible characters of standard ASCII are all present, the following assignment statements initialize the xchr array properly, without needing any system-dependent changes. ⟨ Set initial values 15 ⟩ ≡

for i ← 0 to ´ 37 do xchr [i] ← ´ ´ ; xchr [´ 40 ] ← ´ ␣´ ; xchr [´ 41 ] ← ´ ´ ; xchr [´ 42 ] ← ´ ´ ; xchr [´ 43 ] ← ´ #´ ; xchr [´ 44 ] ← ´ $´ ; xchr [´ 45 ] ← ´ %´ ; xchr [´ 46 ] ← ´ ´ ; xchr [´ 47 ] ← ´ ´ ´ ´ ; xchr [´ 50 ] ← ´ ´ ; xchr [´ 51 ] ← ´ ´ ; xchr [´ 52 ] ← ´ ´ ; xchr [´ 53 ] ← ´ ´ ; xchr [´ 54 ] ← ´ ´ ; xchr [´ 55 ] ← ´ ´ ; xchr [´ 56 ] ← ´ ´ ; xchr [´ 57 ] ← ´ ´ ; xchr [´ 60 ] ← ´ ´ ; xchr [´ 61 ] ← ´ ´ ; xchr [´ 62 ] ← ´ ´ ; xchr [´ 63 ] ← ´ ´ ; xchr [´ 64 ] ← ´ ´ ; xchr [´ 65 ] ← ´ ´ ; xchr [´ 66 ] ← ´ ´ ; xchr [´ 67 ] ← ´ ´ ; xchr [´ 70 ] ← ´ ´ ; xchr [´ 71 ] ← ´ ´ ; xchr [´ 72 ] ← ´ ´ ; xchr [´ 73 ] ← ´ ´ ; xchr [´ 74 ] ← ´ ´ ; xchr [´ 75 ] ← ´ ´ ; xchr [´ 76 ] ← ´ ´ ; xchr [´ 77 ] ← ´ ´ ; xchr [´ 100 ] ← ´ ´ ; xchr [´ 101 ] ← ´ ´ ; xchr [´ 102 ] ← ´ ´ ; xchr [´ 103 ] ← ´ ´ ; xchr [´ 104 ] ← ´ ´ ; xchr [´ 105 ] ← ´ ´ ; xchr [´ 106 ] ← ´ ´ ; xchr [´ 107 ] ← ´ ´ ; xchr [´ 110 ] ← ´ ´ ; xchr [´ 111 ] ← ´ ´ ; xchr [´ 112 ] ← ´ ´ ; xchr [´ 113 ] ← ´ ´ ; xchr [´ 114 ] ← ´ ´ ; xchr [´ 115 ] ← ´ ´ ; xchr [´ 116 ] ← ´ ´ ; xchr [´ 117 ] ← ´ ´ ; xchr [´ 120 ] ← ´ ´ ; xchr [´ 121 ] ← ´ ´ ; xchr [´ 122 ] ← ´ ´ ; xchr [´ 123 ] ← ´ ´ ; xchr [´ 124 ] ← ´ ´ ; xchr [´ 125 ] ← ´ ´ ; xchr [´ 126 ] ← ´ ´ ; xchr [´ 127 ] ← ´ ´ ; xchr [´ 130 ] ← ´ ´ ; xchr [´ 131 ] ← ´ ´ ; xchr [´ 132 ] ← ´ ´ ; xchr [´ 133 ] ← ´ ´ ; xchr [´ 134 ] ← ´ ´ ; xchr [´ 135 ] ← ´ ´ ; xchr [´ 136 ] ← ´ ´ ; xchr [´ 137 ] ← ´ ´ ; xchr [´ 140 ] ← ´ ` ´ ; xchr [´ 141 ] ← ´ ´ ; xchr [´ 142 ] ← ´ ´ ; xchr [´ 143 ] ← ´ ´ ; xchr [´ 144 ] ← ´ ´ ; xchr [´ 145 ] ← ´ ´ ; xchr [´ 146 ] ← ´ ´ ; xchr [´ 147 ] ← ´ ´ ; xchr [´ 150 ] ← ´ ´ ; xchr [´ 151 ] ← ´ ´ ; xchr [´ 152 ] ← ´ ´ ; xchr [´ 153 ] ← ´ ´ ; xchr [´ 154 ] ← ´ ´ ; xchr [´ 155 ] ← ´ ´ ; xchr [´ 156 ] ← ´ ´ ; xchr [´ 157 ] ← ´ ´ ; xchr [´ 160 ] ← ´ ´ ; xchr [´ 161 ] ← ´ ´ ; xchr [´ 162 ] ← ´ ´ ; xchr [´ 163 ] ← ´ ´ ; xchr [´ 164 ] ← ´ ´ ; xchr [´ 165 ] ← ´ ´ ; xchr [´ 166 ] ← ´ ´ ; xchr [´ 167 ] ← ´ ´ ; xchr [´ 170 ] ← ´ ´ ; xchr [´ 171 ] ← ´ ´ ; xchr [´ 172 ] ← ´ ´ ; xchr [´ 173 ] ← ´ ´ ; xchr [´ 174 ] ← ´ ´ ; xchr [´ 175 ] ← ´ ´ ; xchr [´ 176 ] ← ´ ´ ; for i ← ´ 177 to 255 do xchr [i] ← ´ ´ ;

See also sections 16, 40, and 60. This code is used in section 4.

16. The following system-independent code makes the xord array contain a suitable inverse to the information in xchr . ⟨ Set initial values 15 ⟩ +≡

6  GENERIC FONT FILE FORMAT  GFtoPXL §17

for i ← first text char to last text char do xord [chr (i)] ← ´ 40 ; for i ← ␣ to do xord [xchr [i]] ← i; 17. Generic font file format. The most important output produced by a typical run of is the “generic font” ( ) file that specifies the bit patterns of the characters that have been drawn. The term generic indicates that this file format doesn’t match the conventions of any name-brand manufacturer; but it is easy to convert files to the special format required by almost all digital phototypesetting equipment. There’s a strong analogy between the files written by TEX and the files written by ; and, in fact, the file formats have a lot in common.

A file is a stream of 8-bit bytes that may be regarded as a series of commands in a machine-like language. The first byte of each command is the operation code, and this code is followed by zero or more bytes that provide parameters to the command. The parameters themselves may consist of several consecutive bytes; for example, the ‘boc’ (beginning of character) command has six parameters, each of which is four bytes long. Parameters are usually regarded as nonnegative integers; but four-byte-long parameters can be either positive or negative, hence they range in value from −2^{31} to 2^{31} − 1. As in files, numbers that occupy more than one byte position appear in BigEndian order, and negative numbers appear in two’s complement notation.

A file consists of a “preamble,” followed by a sequence of one or more “characters,” followed by a “postamble.” The preamble is simply a pre command, with its parameters that introduce the file; this must come first. Each “character” consists of a boc command, followed by any number of other commands that specify “black” pixels, followed by an eoc command. The characters appear in the order that generated them. If we ignore no-op commands (which are allowed between any two commands in the file), each eoc command is immediately followed by a boc command, or by a post command; in the latter case, there are no more characters in the file, and the remaining bytes form the postamble. Further details about the postamble will be explained later.

Some parameters in commands are “pointers.” These are four-byte quantities that give the location number of some other byte in the file; the first file byte is number 0, then comes number 1, and so on.

18. The format is intended to be both compact and easily interpreted by a machine. Compactness is achieved by making most of the information relative instead of absolute. When a -reading program reads the commands for a character, it keeps track of two quantities: (a) the current column number, m; and (b) the current row number, n. These are 32-bit signed integers, although most actual font formats produced from files will need to curtail this vast range because of practical limitations. ( output will never allow |m| or |n| to get extremely large, but the format tries to be more general.)

How do ’s row and column numbers correspond to the conventions of TEX and ? Well, the “reference point” of a character, in TEX’s view, is considered to be at the lower left corner of the pixel in row 0 and column 0. This point is the intersection of the baseline with the left edge of the type; it corresponds to location (0, 0) in programs. Thus the pixel in row 0 and column 0 is ’s unit square, comprising the region of the plane whose coordinates both lie between 0 and 1. The pixel in row n and column m consists of the points whose coordinates (x, y) satisfy m ≤ x ≤ m + 1 and n ≤ y ≤ n + 1. Negative values of m and x correspond to columns of pixels left of the reference point; negative values of n and y correspond to rows of pixels below the baseline.

Besides m and n, there’s also a third aspect of the current state, namely the paint switch, which is always either black or white. Each paint command advances m by a specified amount d, and blackens the intervening pixels if paint switch = black ; then the paint switch changes to the opposite state. ’s commands are designed so that m will never decrease within a row, and n will never increase within a character; hence there is no way to whiten a pixel that has been blackened.

§19  GFtoPXL  GENERIC FONT FILE FORMAT 7

19. Here is a list of all the commands that may appear in a file. Each command is specified by its symbolic name (e.g., boc), its opcode byte (e.g., 67), and its parameters (if any). The parameters are followed by a bracketed number telling how many bytes they occupy; for example, ‘d[2]’ means that parameter d is two bytes long. paint 0 0. This is a paint command with d = 0; it does nothing but change the paint switch from black to

white or vice versa. paint 1 through paint 63 (opcodes 1 to 63). These are paint commands with d = 1 to 63, defined as follows:

If paint switch = black , blacken d pixels of the current row n, in columns m through m + d − 1 inclusive. Then, in any case, complement the paint switch and advance m by d.

paint1 64 d[1]. This is a paint command with a specified value of d; uses it to paint when

64 ≤ d < 256. paint2 65 d[2]. Same as paint1 , but d can be as high as 65535. paint3 66 d[3]. Same as paint1 , but d can be as high as 2^{24} − 1. never needs this command,

and it is hard to imagine anybody making practical use of it; surely a more compact encoding will be desirable when characters can be this large. But the command is there, anyway, just in case.

boc 67 c[4] p[4] min m[4] max m[4] min n[4] max n[4]. Beginning of a character: Here c is the character code, and p points to the previous character beginning (if any) for characters having this code number modulo 256. (The pointer p is −1 if there was no prior character with an equivalent code.) The values of registers m and n defined by the instructions that follow for this character must satisfy min m ≤ m ≤ max m and min n ≤ n ≤ max n. (The values of max m and min n need not be the tightest bounds possible.) When a -reading program sees a boc, it can use min m, max m, min n, and max n to initialize the bounds of an array. Then it sets m ← min m, n ← max n, and paint switch ← white.

boc1 68 c[1] del m[1] max m[1] del n[1] max n[1]. Same as boc, but p is assumed to be −1; also del m = max m − min m and del n = max n − min n are given instead of min m and min n. The one-byte parameters must be between 0 and 255, inclusive. (This abbreviated boc saves 19 bytes per character, in common cases.)

eoc 69. End of character: All pixels blackened so far constitute the pattern for this character. In particular,

a completely blank character might have eoc immediately following boc. skip0 70. Decrease n by 1 and set m ← min m, paint switch ← white. (This finishes one row and begins

another, ready to whiten the leftmost pixel in the new row.) skip1 71 d[1]. Decrease n by d + 1, set m ← min m, and set paint switch ← white. This is a way to produce

d all-white rows. skip2 72 d[2]. Same as skip1 , but d can be as large as 65535. skip3 73 d[3]. Same as skip1 , but d can be as large as 2^{24} − 1. obviously never needs this

command. new row 0 74. Decrease n by 1 and set m ← min m, paint switch ← black . (This finishes one row and

begins another, ready to blacken the leftmost pixel in the new row.) new row 1 through new row 164 (opcodes 75 to 238). Same as new row 0 , but with m ← min m + 1

through min m + 164, respectively. xxx1 239 k[1] x[k]. This command is undefined in general; it functions as a (k + 2)-byte no op unless

special -reading programs are being used. generates xxx commands when encountering a special string; this occurs in the file only between characters, after the preamble, and before the postamble. However, xxx commands might appear anywhere in files generated by other processors. It is recommended that x be a string having the form of a keyword followed by possible parameters relevant to that keyword.

xxx2 240 k[2] x[k]. Like xxx1 , but 0 ≤ k < 65536. xxx3 241 k[3] x[k]. Like xxx1 , but 0 ≤ k < 2^{24}. uses this when sending a special string whose

length exceeds 255. xxx4 242 k[4] x[k]. Like xxx1 , but k can be ridiculously large; k mustn’t be negative. yyy 243 y[4]. This command is undefined in general; it functions as a 5-byte no op unless special -reading

programs are being used. puts scaled numbers into yyy ’s, as a result of numspecial commands; the intent is to provide numeric parameters to xxx commands that immediately precede.

no op 244. No operation, do nothing. Any number of no op’s may occur between commands, but a

no op cannot be inserted between a command and its parameters or between two parameters. char loc 245 c[1] dx [4] dy [4] w[4] p[4]. This command will appear only in the postamble, which will be

explained shortly. char loc0 246 c[1] dm[1] w[4] p[4]. Same as char loc, except that dy is assumed to be zero, and the value

of dx is taken to be 65536 ∗ dm, where 0 ≤ dm < 256. pre 247 i[1] k[1] x[k]. Beginning of the preamble; this must come at the very beginning of the file. Parameter i

is an identifying number for format, currently 131. The other information is merely commentary; it is not given special interpretation like xxx commands are. (Note that xxx commands may immediately follow the preamble, before the first boc.)

post 248. Beginning of the postamble, see below. post post 249. Ending of the postamble, see below. Commands 250–255 are undefined at the present time.

define gf id byte = 131 { identifies the kind of files described here }

20. Here are the opcodes that actually refers to.

define paint 0 = 0 { beginning of the paint commands } define paint1 = 64 { move right a given number of columns, then black ↔ white } define boc = 67 { beginning of a character } define boc1 = 68 { abbreviated boc } define eoc = 69 { end of a character } define skip0 = 70 { skip no blank rows } define skip1 = 71 { skip over blank rows } define new row 0 = 74 { move down one row and then right } define max new row = 238 { move down one row and then right } define xxx1 = 239 { for special strings } define yyy = 243 { for numspecial numbers } define nop = 244 { no operation } define char loc = 245 { character locators in the postamble } define char loc0 = 246 { character locators in the postamble } define pre = 247 { preamble } define post = 248 { postamble beginning } define post post = 249 { postamble ending } define undefined commands ≡ 250, 251, 252, 253, 254, 255 21. The last character in a file is followed by ‘post ’; this command introduces the postamble, which summarizes important facts that has accumulated. The postamble has the form

post p[4] ds [4] cs [4] hppp[4] vppp[4] min m[4] max m[4] min n[4] max n[4] ⟨ character locators ⟩ post post q[4] i[1] 223’s[≥4]

Here p is a pointer to the byte following the final eoc in the file (or to the byte following the preamble, if there are no characters); it can be used to locate the beginning of xxx commands that might have preceded the postamble. The ds and cs parameters give the design size and check sum, respectively, which are exactly the values put into the header of any file that shares information with this file. Parameters hppp and vppp are the ratios of pixels per point, horizontally and vertically, expressed as scaled integers (i.e., multiplied by 2^{16}); they can be used to correlate the font with specific device resolutions, magnifications, and “at sizes.” Then come min m, max m, min n, and max n, which bound the values that registers m and n assume in all characters in this file. (These bounds need not be the best possible; max m and min n may, on the other hand, be tighter than the similar bounds in boc commands. For example, some character may have min n = −100 in its boc, but it might turn out that n never gets lower than −50 in any character; then min n can have any value ≤ −50. If there are no characters in the file, it’s possible to have min m > max m and/or min n > max n.)

22. Character locators are introduced by char loc commands, which specify a character residue c, character escapements (dx , dy ), a character width w, and a pointer p to the beginning of that character. (If two or more characters have the same code c modulo 256, only the last will be indicated; the others can be located by following backpointers. Characters whose codes differ by a multiple of 256 are assumed to share the same font metric information, hence the file contains only residues of character codes modulo 256. This convention is intended for oriental languages, when there are many character shapes but few distinct widths.)

The character escapements (dx , dy ) are the values of ’s chardx and chardy parameters; they are in units of scaled pixels; i.e., dx is in horizontal pixel units times 2^{16}, and dy is in vertical pixel units times 2^{16}. This is the intended amount of displacement after typesetting the character; for files, dy should be zero, but other document file formats allow nonzero vertical escapement.

The character width w duplicates the information in the file; it is 2^{24} times the ratio of the true width to the font’s design size.

The backpointer p points to the character’s boc, or to the first of a sequence of consecutive xxx or yyy or no op commands that immediately precede the boc, if such commands exist; such “special” commands essentially belong to the characters, while the special commands after the final character belong to the postamble (i.e., to the font as a whole). This convention about p applies also to the backpointers in boc commands, even though it wasn’t explained in the description of boc.

Pointer p might be −1 if the character exists in the file but not in the file. This unusual situation can arise in output if the user had proofing < 0 when the character was being shipped out, but then made proofing ≥ 0 in order to get a file.

23. The last part of the postamble, following the post post byte that signifies the end of the character locators, contains q, a pointer to the post command that started the postamble. An identification byte, i, comes next; this currently equals 131, as in the preamble.

The i byte is followed by four or more bytes that are all equal to the decimal number 223 (i.e., ´ 337 in octal). puts out four to seven of these trailing bytes, until the total length of the file is a multiple of four bytes, since this works out best on machines that pack four bytes per word; but any number of 223’s is allowed, as long as there are at least four of them. In effect, 223 is a sort of signature that is added at the very end.

This curious way to finish off a file makes it feasible for -reading programs to find the postamble first, on most computers, even though wants to write the postamble last. Most operating systems permit random access to individual words or bytes of a file, so the reader can start at the end and skip backwards over the 223’s until finding the identification byte. Then it can back up four bytes, read q, and move to byte q of the file. This byte should, of course, contain the value 248 (post ); now the postamble can be read, so the reader can discover all the information needed for individual characters.

Unfortunately, however, standard Pascal does not include the ability to access a random position in a file, or even to determine the length of a file. Almost all systems nowadays provide the necessary capabilities, so format has been designed to work most efficiently with modern operating systems. Indeed, insists on being able to read the postamble first, because it needs the device width information found there in order to encode characters.

§24  GFtoPXL  INPUT AND OUTPUT FOR BINARY FILES 11

24. Input and Output for binary files. We have seen that a file is a sequence of 8-bit bytes. The bytes appear physically in what is called a ‘packed file of 0 . . 255’ in Pascal lingo.

Packing is system dependent, and many Pascal systems fail to implement such files in a sensible way (at least, from the viewpoint of producing good production software). For example, some systems treat all byte-oriented files as text, looking for end-of-line marks and such things. Therefore some system-dependent code is often needed to deal with binary files, even though most of the program in this section of is written in standard Pascal.

We shall stick to simple Pascal in this program, for reasons of clarity, even if such simplicity is sometimes unrealistic. ⟨ Types in the outer block 12 ⟩ +≡

eight bits = 0 . . 255; { unsigned one-byte quantity }

byte file = packed file of eight bits ; { files that contain binary data }

25. The program deals with two binary file variables: gf file is the input file that we are translating into format, to be written on pxl file. ⟨ Globals in the outer block 10 ⟩ +≡ gf file: byte file; { the stuff we are ing } pxl file: byte file; { the stuff we have ed }

26. To prepare the gf file for input, we reset it. procedure open gf file; { prepares to read packed bytes in gf file }

begin reset (gf file); cur loc ← 0;

end;

27. To prepare the pxl file for output, we rewrite it. procedure open pxl file; { prepares to write packed bytes in pxl file }

begin rewrite(pxl file);

end;

28. If you looked carefully at the preceding code, you probably asked, “What is cur loc?” Good question. It’s a global variable that holds the number of the byte about to be read next from gf file. Likewise, pxl byte holds the number of the byte about to be written next into pxl file. ⟨ Globals in the outer block 10 ⟩ +≡ cur loc: integer ; { where we are about to look, in gf file } pxl byte no: integer ; { where we are about to write, in pxl file }

12  INPUT AND OUTPUT FOR BINARY FILES  GFtoPXL §29

29. We shall use a set of simple functions to read the next byte or bytes from gf file. There are seven possibilities, each of which is treated as a separate function in order to minimize the overhead for subroutine calls. function get byte: integer ; { returns the next byte, unsigned }

var b: eight bits ; begin if eof (gf file) then get byte ← 0 else begin read (gf file, b); incr (cur loc); get byte ← b;

end; end;

function signed byte: integer ; { returns the next byte, signed } var b: eight bits ; begin read (gf file, b); incr (cur loc); if b < 128 then signed byte ← b else signed byte ← b − 256; end;

function get two bytes : integer ; { returns the next two bytes, unsigned } var a, b: eight bits ; begin read (gf file, a); read (gf file, b); cur loc ← cur loc + 2; get two bytes ← a ∗ 256 + b; end;

function signed pair : integer ; { returns the next two bytes, signed } var a, b: eight bits ; begin read (gf file, a); read (gf file, b); cur loc ← cur loc + 2; if a < 128 then signed pair ← a ∗ 256 + b else signed pair ← (a − 256) ∗ 256 + b; end;

function get three bytes : integer ; { returns the next three bytes, unsigned } var a, b, c: eight bits ; begin read (gf file, a); read (gf file, b); read (gf file, c); cur loc ← cur loc + 3; get three bytes ← (a ∗ 256 + b) ∗ 256 + c; end;

function signed trio: integer ; { returns the next three bytes, signed } var a, b, c: eight bits ; begin read (gf file, a); read (gf file, b); read (gf file, c); cur loc ← cur loc + 3; if a < 128 then signed trio ← (a ∗ 256 + b) ∗ 256 + c else signed trio ← ((a − 256) ∗ 256 + b) ∗ 256 + c; end;

function signed quad : integer ; { returns the next four bytes, signed } var a, b, c, d: eight bits ; begin read (gf file, a); read (gf file, b); read (gf file, c); read (gf file, d); cur loc ← cur loc + 4; if a < 128 then signed quad ← ((a ∗ 256 + b) ∗ 256 + c) ∗ 256 + d else signed quad ← (((a − 256) ∗ 256 + b) ∗ 256 + c) ∗ 256 + d; end; 30. Most info in the pxl file comes in words, but we have to write it as bytes and halfwords occasionally.

define pxl byte(#) ≡ begin write(pxl file, #); incr (pxl byte no); end

procedure pxl halfword (w : integer ); begin if w < 0 then w ← w + ˝ 10000; pxl byte(w div ˝ 100); pxl byte(w mod ˝ 100); end;

procedure pxl word (w : integer ); begin if w > 0 then pxl byte(w div ˝ 1000000) else begin w ← w + ˝ 40000000; w ← w + ˝ 40000000; pxl byte((w div ˝ 1000000) + 128);

end; pxl byte((w div ˝ 10000) mod ˝ 100); pxl byte((w div ˝ 100) mod ˝ 100); pxl byte(w mod ˝ 100); end;

31. Finally we come to the routines that are used for random access of the gf file. The driver program below needs two such routines: gf length should compute the total number of bytes in gf file, possibly also causing eof (gf file) to be true; and move to byte(n) should position gf file so that the next get byte will read byte n, starting with n = 0 for the first byte in the file.

Such routines are, of course, highly system dependent. They are implemented here in terms of two assumed system routines called set pos and cur pos . The call set pos (f, n) moves to item n in file f, unless n is negative or larger than the total number of items in f; in the latter case, set pos (f, n) moves to the end of file f. The call cur pos (f) gives the total number of items in f, if eof (f) is true; we use cur pos only in such a situation. function gf length: integer ;

begin set pos (gf file, −1); gf length ← cur pos (gf file);

end; procedure move to byte(n : integer );

begin set pos (gf file, n); cur loc ← n;

14  TRANSLATION TO RASTER FORM  GFtoPXL §32

end; 32. Translation to raster form. The main work of is accomplished by the do char procedure, which produces the output for an entire character, assuming that the boc command for that character has already been processed. This procedure works in two parts, the first of which is essentially an interpretive routine that reads and acts on the commands by writing into an array of pixels, and the second is a routine which encapsules this information into the form needed for the Raster Information portion of the file.

33. The definition of files refers to two registers, (m, n), which hold integer row and column numbers. We also need to remember paint switch, who’s value is either black or white. ⟨ Types in the outer block 12 ⟩ +≡

x coord = left pixel . . right pixel ; y coord = bot pixel . . top pixel ; { BUG FIXME ??? off by one }

34. ⟨ Globals in the outer block 10 ⟩ +≡ m: x coord ; n: y coord ; { current state values } paint switch: pixel ;

35. We’ll need a big array of pixels to hold the character image. Each pixel should be represented as a single bit in order to save space. Different systems may prefer the following definitions, while others may do better using the boolean type and constants.

define white = 0 { could also be false }

define black = 1 { could also be true }

define complement (#) ≡

if # = black then # ← white else # ← black { could also be paint switch ← ¬paint switch }

⟨ Types in the outer block 12 ⟩ +≡ pixel = white . . black ; { could also be boolean }

36. In order to allow different systems to change the image array from row-major to column-major (or vice versa) easily, or to transpose it top and bottom or left and right, we declare and access it as follows.

define image ≡ image array [n, m] ⟨ Globals in the outer block 10 ⟩ +≡ image array : packed array [y coord , x coord ] of pixel ;

37. Maybe there’s a faster way to do this on your system. Note that the only part of the image array that we clear is the part that the current character may use. Thus, the rest of this program may not look outside the area delimited by [y, x] = [min n . . max n, min m . . max m] and expect to see anything but junk ⟨ Clear the image 37 ⟩ ≡

begin n ← min n;

while n ≤ max n do begin m ← min m; while m ≤ max m do

begin image ← white; incr (m); end; incr (n); end;

end

This code is used in section 72.

§38  GFtoPXL  TRANSLATION TO RASTER FORM 15

38. ⟨ Print the image 38 ⟩ ≡ begin n ← max n; while (n ≥ min n) ∧ (n ≥ max n − 80) do

begin m ← min m;

while (m ≤ max m) ∧ (m ≤ min m + 78) do begin if image = white then print (´ ␣´ ) else print (´ ´ ); incr (m); end;

print ln(´ ␣´ ); decr (n);

end; end

This code is used in section 64.

39. Let’s keep track of how many characters are in the font. ⟨ Globals in the outer block 10 ⟩ +≡ char code: integer ; { current character number } total chars : integer ; { the total number of characters seen so far }

40. ⟨ Set initial values 15 ⟩ +≡ total chars ← 0;

41. Before we get into the details of do char , it is convenient to consider a simpler routine that computes the first parameter of each opcode.

define three cases (#) ≡ #, # + 1, # + 2 define four cases (#) ≡ #, # + 1, # + 2, # + 3 define eight cases (#) ≡ four cases (#), four cases (# + 4) define nine cases (#) ≡ eight cases (#), # + 8 define sixteen cases (#) ≡ eight cases (#), eight cases (# + 8) define eighteen cases (#) ≡ nine cases (#), nine cases (# + 9) define thirty two cases (#) ≡ sixteen cases (#), sixteen cases (# + 16) define sixty four cases (#) ≡ thirty two cases (#), thirty two cases (# + 32) define eighty two cases (#) ≡ sixty four cases (#), eighteen cases (# + 64) define one hundred sixty five cases (#) ≡ #, eighty two cases (# + 1), eighty two cases (# + 83)

function first par (o : eight bits ): integer ;

begin case o of

sixty four cases (paint 0 ): first par ← o − paint 0 ; paint1 , skip1 , char loc, char loc0 , xxx1 : first par ← get byte; paint1 + 1, skip1 + 1, xxx1 + 1: first par ← get two bytes ; paint1 + 2, skip1 + 2, xxx1 + 2: first par ← get three bytes ; xxx1 + 3, yyy : first par ← signed quad ; skip0 , nop, boc, boc1 , eoc, pre, post , post post , undefined commands : first par ← 0; one hundred sixty five cases (new row 0 ): first par ← o − new row 0 ; end; end; 42. Strictly speaking, the do char procedure is really a function with side effects, not a ‘procedure’; it returns the value false if should be aborted because of some unusual happening. The subroutine is organized as a typical interpreter, with a multiway branch on the command code. function do char : boolean;

label 1, 2, 3, 4, 9997, 9998, 9999; var o: eight bits ; { operation code of the current command }

p, q: integer ; { parameters of the current command } i, j: integer ; { used to index in select byte type } b: eight bits ; { holding byte for pxl bits }

begin { we’ve already scanned the boc } do char ← true; while true do ⟨ Translate the next command in the file; goto 9999 if it was eoc; goto 9998 if

premature termination is needed 43 ⟩;

9998: print ln(´ ´ ); do char ← false; goto 9997; 9999: ⟨ Remove white rows and columns 51 ⟩;

⟨ Save directory info. 61 ⟩⟨ Encode the glyph 64 ⟩; 9997: end;

43. This is the main command loop.

define error (#) ≡ begin print (a : 1, ´ ␣ ␣´ , #); print nl ; end

⟨ Translate the next command in the file; goto 9999 if it was eoc; goto 9998 if premature termination is

needed 43 ⟩ ≡ begin a ← cur loc; o ← get byte; p ← first par (o); if eof (gf file) then bad gf (´ ␣ ␣ ␣ ´ ); ⟨ Translate command o 44 ⟩; end

This code is used in section 42.

44. The multiway switch in first par , above, was organized by the length of each command; the one in do char is organized by the semantics. ⟨ Translate command o 44 ⟩ ≡

if o ≤ paint1 + 2 then ⟨ Translate a paint command 48 ⟩ else if (new row 0 ≤ o) ∧ (o ≤ max new row ) then ⟨ Translate a new row command 49 ⟩

else case o of

four cases (skip0 ): ⟨ Translate a skip command 50 ⟩;

⟨ Cases for commands nop, pre, post , post post , boc, and eoc 45 ⟩ four cases (xxx1 ): ⟨ Translate an xxx command 46 ⟩; yyy : ⟨ Translate a yyy command 47 ⟩; othercases error (´ ␣ ␣´ , o : 1, ´ ´ ) endcases

This code is used in section 43.

45. ⟨ Cases for commands nop, pre, post , post post , boc, and eoc 45 ⟩ ≡ nop: do nothing ; pre: begin error (´ ␣ ␣ ␣ ␣ ´ ); goto 9998;

end; post , post post : begin error (´ ␣ ␣ ␣ ␣ ´ ); goto 9998;

end; boc, boc1 : begin error (´ ␣ ␣ ␣ ´ ); goto 9998;

end; eoc: goto 9999;

This code is used in section 44.

46. ⟨ Translate an xxx command 46 ⟩ ≡ begin bad char ← false; while p > 0 do

begin q ← get byte;

if (q < ␣ ) ∨ (q > ) then bad char ← true;

decr (p);

end; if bad char then error (´ ␣ ␣ ␣ ␣ ´ ); end

This code is used in sections 44 and 71.

47. ⟨ Translate a yyy command 47 ⟩ ≡ do nothing

This code is used in sections 44 and 71.

48. ⟨ Translate a paint command 48 ⟩ ≡

begin if m + p > right pixel then

begin if m ≤ right pixel then { give error message only once }

    error (´ ␣       ␣   ␣   ␣  ␣   ␣     ␣   ␣ ´ );

m ← m + p;

end else while p > 0 do

begin image ← paint switch; incr (m); decr (p);

end; complement (paint switch); end

This code is used in section 44.

49. ⟨ Translate a new row command 49 ⟩ ≡ begin decr (n); m ← min m + p; paint switch ← black ; end

This code is used in section 44.

50. ⟨ Translate a skip command 50 ⟩ ≡ begin n ← n − (p + 1); m ← min m; paint switch ← white; end

This code is used in section 44.

51. Note that format does not guarantee that max m and max n are as small as they might be (they’re sure to be big enough, though). Likewise, min m and min n might be smaller than they might be. Here we set the bounds as tightly as possible.

define no black ≡ (min n > max n) ⟨ Remove white rows and columns 51 ⟩ ≡

debug print nl ; print ln(´ ␣ ´ , min m : 1, ´ ␣ ´ , max m : 1, ´ ␣ ´ , min n : 1, ´ ␣ ´ , max n : 1); gubed n ← min n; while n ≤ max n do

begin m ← min m; while m ≤ max m do

begin if image = black then goto 1;

incr (m);

end; incr (n); min n ← n; { blank row at bottom now gone } end;

1: if no black then begin min m ← max m + 1; goto 4; { why bother? } end;

n ← max n; while n > min n do

begin m ← min m; while m ≤ max m do

begin if image = black then goto 2;

incr (m);

end; decr (n); max n ← n; { blank row at top now gone } end;

2: m ← min m;

while m < max m do begin n ← min n; while n ≤ max n do

begin if image = black then goto 3;

incr (n);

end; incr (m); min m ← m; { blank column at left now gone } end;

3: m ← max m;

while m > min m do begin n ← min n; while n ≤ max n do

begin if image = black then goto 4;

incr (n);

end; decr (m); max m ← m; { blank column at right now gone } end;

4: cols ← max m − min m + 1; rows ← max n − min n + 1; num bytes ← 4 ∗ ((cols + 31) div 32);

debug print ln(´ ␣ ␣  ´ , min m : 1, ´ ␣  ´ , max m : 1, ´ ␣  ´ , min n : 1, ´ ␣  ´ ,
max n : 1); print ln(´  ´ , cols : 1, ´ ␣  ´ , rows : 1);

gubed

This code is used in section 42.

52. While we were at it, we also snuck in a computation of how many rows and columns are in the bounding box and the number of bytes needed to report each row of pixels. ⟨ Globals in the outer block 10 ⟩ +≡ cols , rows : integer ; { columns and rows of pixels } num bytes : integer ; { needed bytes per row }

20  READING THE POSTAMBLE  GFtoPXL §53

53. Reading the postamble. Now imagine that we are reading the file and positioned just after the post command. That, in fact, is the situation, when the following part of is called upon to read, translate, and check the rest of the postamble. procedure read postamble;

var k: integer ; { loop index }

p, q, m, c: integer ; { general purpose registers } begin post loc ← cur loc − 1; print ln(´ ␣ ␣ ␣ ␣´ , post loc : 1, ´ ´ ); p ← signed quad ; design size ← signed quad ; check sum ← signed quad ; print (´ ␣ ␣ ␣´ , design size : 1, ´ ␣ ´ ); print scaled (design size div 16); print ln(´ ´ ); print ln(´ ␣ ␣ ␣´ , check sum : 1); hppp ← signed quad ; vppp ← signed quad ; print (´ ␣ ␣´ , hppp : 1, ´ ␣ ´ ); print scaled (hppp); print ln(´ ´ ); print (´ ␣ ␣´ , vppp : 1, ´ ␣ ´ ); print scaled (vppp); print ln(´ ´ ); magnification ← hppp/(65536.0 ∗ resolution/72.27); pxl mag ← round (1000 ∗ magnification); print ln(´ ␣ ␣´ , pxl mag : 1); min m ← signed quad ; max m ← signed quad ; min n ← signed quad ; max n ← signed quad ; print ln(´ ␣ ␣ ␣´ , min m : 1, ´ ␣ ␣ ␣ ␣´ , max m : 1); print ln(´ ␣ ␣ ␣´ , min n : 1, ´ ␣ ␣ ␣ ␣´ , max n : 1); ⟨ Process the character locations in the postamble 56 ⟩; ⟨ Make sure that the end of the file is well-formed 55 ⟩; end;

54. Here is the main information we glean from the postamble. ⟨ Globals in the outer block 10 ⟩ +≡ design size: integer ; min m, max m, min n, max n: integer ; hppp, vppp: integer ; check sum: integer ; post loc: integer ; magnification: real ; tfm width: array [0 . . max glyph no] of integer ; device width: array [0 . . max glyph no] of integer ;

55. When we get to the present code, the post post command has just been read. ⟨ Make sure that the end of the file is well-formed 55 ⟩ ≡

if k ≠ post post then error (´ ␣ ␣ ´ ); q ← signed quad ; if q ≠ post loc then error (´ ␣ ␣ ␣ ␣´ , post loc : 1, ´ ␣ ␣´ , q : 1); m ← get byte; if m ≠ gf id byte then error (´ ␣ ␣ ␣ ␣´ , gf id byte : 1); k ← cur loc; m ← 223; while (m = 223) ∧ ¬eof (gf file) do m ← get byte; if ¬eof (gf file) then bad gf (´ ␣ ␣ ␣´ , cur loc − 1 : 1, ´ ␣ ␣ ␣ ´ ) else if cur loc < k + 4 then error (´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ );

This code is used in section 53.

§56  GFtoPXL  READING THE POSTAMBLE 21

56. ⟨ Process the character locations in the postamble 56 ⟩ ≡

repeat k ← get byte;

if (k = char loc) ∨ (k = char loc0 ) then begin c ← first par (k); if c > max glyph no then abort (´ ␣ ␣ ␣ ´ ); if k = char loc0 then device width[c] ← get byte else begin device width[c] ← round (signed quad /unity ); m ← signed quad ;

end; tfm width[c] ← signed quad ; p ← signed quad ; k ← nop; end;

until k ≠ nop;

This code is used in section 53.

57. This routines is brought into play in order to read the postamble first. procedure find postamble;

var q, k: integer ; begin post loc ← gf length − 4; repeat if post loc = 0 then bad gf (´ ␣ ´ );

22  PXL MATRIX FORMAT  GFtoPXL §58

move to byte(post loc); k ← get byte; decr (post loc); until k ≠ 223; if k ≠ gf id byte then bad gf (´ ␣ ␣ ␣´ , k : 1); move to byte(post loc − 3); q ← signed quad ; if (q < 0) ∨ (q > post loc − 3) then bad gf (´ ␣ ␣´ , q : 1, ´ ␣ ␣ ␣´ , post loc − 3 : 1); move to byte(q); k ← get byte; if k ≠ post then bad gf (´ ␣´ , q : 1, ´ ␣ ␣ ␣ ´ ); end; 58. PXL Matrix Format. A file is an expanded raster description of a single font at a particular resolution and contains essentially the same information as that contained in a file. files are used by many existing device-driver programs for dot matrix devices. By convention, files are for 200 pixels per inch. will report the magnification over the design point size that will occur if the file is used on a 200 pixel per inch output device.

All words in of files are in 32-bit format, with the four lower bits zero on 36-bit machines. The raster information is contained in a sequence of binary words which record white pixels as zeros and black pixels as ones.

The first word of the file and the last word contain the which is currently equal to 1001(decimal).

This first word is followed by a sequence of raster information words where each line of pixels in the glyphs is represented by one or more words of binary information. The number of words used to represent each row of pixels for any particular glyph is fixed and it is set by the value of max m − min m + 1 for that particular glyph. Each white pixel is represented by a zero and each black pixel is represented by a one in the corresponding bit positions (the first 32 only of each word on 36-bit machines). The unused bit positions toward the end of each set of words for each row of pixels are filled with zeros. It sould be noted that this representation is more wasteful of space than it needs to be, but it may possibly simplify the subsequent use of the information by a device-driver program.

The Font Directory follows, occupying a fixed position with respect to the end of the file (in words 517 through 6 from this end), and assigns 4 words for each of the potential 128 different glyphs that could be contained in this particular font in the order of their assending ascii values (not in the order that the glyphs appear in the raster section, which may be entirely arbitrary). This means that the first four words are for the ascii zero glyph. All four words reserved for any missing glyphs are set to zero.

The first word of each glyph’s directory information contains the Pixel Width in the left half-word (the leftmost 16 bits) and the Pixel Height in the right half-word (the next 16 bits). These dimensions are those of the smallest bounding-box, measured in pixels, and they have nothing necessarily to do with the width and height figures that appear in the file. The width, measured in , where 1 is 1/(2^{20} times the design size, is listed in the fourth word of the glyph’s directory information.

The second word of the glyph’s directory information contains the offset of the glyph’s reference point from its upper-left-hand corner of the bounding box, measured in pixels, with the X-Offset in the left half-word and the Y-Offset in the right half-word. These numbers may be negative, and two’s complement representation is used. Remember that the positive x direction means ‘rightward’ and positive y is ‘downward’ on the page.

The third word of a glyph’s directory information contains the number of the word in this file where the Raster Description for this particular glyph begins, measured from the first word which is numbered zero.

As mentioned earlier, the fourth word of directory information for each glyph contains the width. The final five words in the file contain information relation to the entire file. The first of these five words is a checksum which should match the checksum contained in the file that

TEX used in reference to this font, although, if this checksum is zero, no validity checking will be done.

The second of these five words is an integer that is 1000 times the magnification factor at which this font was produced.

The third word contains the design sige of the font measured in (2^{−20} unmagnified points).

The fourth word contains a pointer to the first word of the font directory.

The fifth and last word of the entire file contains a duplicate of the ID as contained in the first word of the file.

define pxl id = 1001 { current version of format }

§59  GFtoPXL  PXL MATRIX FORMAT 23

59. ⟨ Globals in the outer block 10 ⟩ +≡ glyph ptr : array [0 . . max glyph no] of integer ; glyph cols : array [0 . . max glyph no] of integer ; glyph rows : array [0 . . max glyph no] of integer ; cols offset : array [0 . . max glyph no] of integer ; rows offset : array [0 . . max glyph no] of integer ; bc, ec: integer ; pxl dir ptr : integer ; pxl mag : integer ;

60. ⟨ Set initial values 15 ⟩ +≡ char code ← 0; while char code ≤ max glyph no do

begin glyph cols [char code] ← 0; glyph rows [char code] ← 0; cols offset [char code] ← 0; rows offset [char code] ← 0; glyph ptr [char code] ← 0; { marks nonexistent character } incr (char code); end;

bc ← max glyph no + 1; ec ← −1;

61. The glyph ptr is saved in Encode the glyph. ⟨ Save directory info. 61 ⟩ ≡

glyph cols [char code] ← cols ; glyph rows [char code] ← rows ; cols offset [char code] ← −min m; rows offset [char code] ← max n;

This code is used in section 42.

62. ⟨ Start up the pxl file 62 ⟩ ≡ pxl byte no ← 0; pxl word (pxl id ); debug print ln(´ ␣ ␣ ␣ ´ ); gubed

This code is used in section 67.

63. When we get to this section we have all of the esential information needed to write the 4∗max glyph no words of the font directory and the last five words of the pxl file. ⟨ Finish off the pxl file 63 ⟩ ≡

if (pxl byte no mod 4) ≠ 0 then abort (´ ␣ ´ ´ ␣ ␣ ´ );

pxl dir ptr ← pxl byte no div 4;

for char code ← 0 to max glyph no do begin pxl halfword (glyph cols [char code]); pxl halfword (glyph rows [char code]); pxl halfword (cols offset [char code]); pxl halfword (rows offset [char code]); pxl word (glyph ptr [char code]); { ptr to glyph raster info } pxl word (tfm width[char code]); end;

pxl word (check sum); pxl word (pxl mag ); pxl word (design size); pxl word (pxl dir ptr ); pxl word (pxl id ); debug print ln(´ ␣ ␣ ␣ ´ ); gubed

This code is used in section 67.

64. The following procedure writes out the pxl raster, and updates pxl byte no. ⟨ Encode the glyph 64 ⟩ ≡

if glyph ptr [char code] ≠ 0 then error (´ ␣ ´ ); glyph ptr [char code] ← pxl byte no div 4; eebug print nl ; ⟨ Print the image 38 ⟩; gubee n ← max n; while (n ≥ min n) do

begin m ← min m;

for j ← 1 to num bytes do begin if m < (max m − 7) then ⟨ Get full byte 65 ⟩ else if (m > max m) then pxl byte(0)

else ⟨ Get mixed byte 66 ⟩; end;

if (pxl byte no mod 4) ≠ 0 then error (´ ␣ ␣ ␣ ␣ ´ ); decr (n) end;

This code is used in section 42.

65. ⟨ Get full byte 65 ⟩ ≡ begin b ← image; incr (m); for i ← 2 to 8 do

begin b ← b ∗ 2 + image; incr (m);

end; pxl byte(b); end

This code is used in section 64.

66. ⟨ Get mixed byte 66 ⟩ ≡ begin b ← image; incr (m); i ← 2; while m ≤ max m do

begin b ← b ∗ 2 + image; incr (m); incr (i);

end; for i ← i to 8 do b ← b ∗ 2; pxl byte(b); end

This code is used in section 64.

§67  GFtoPXL  THE MAIN PROGRAM 25

67. The main program. Now we are ready to put it all together. This is where starts, and where it ends.

begin initialize; { get all variables initialized } open gf file; find postamble; read postamble; open gf file; ⟨ Process the preamble 69 ⟩; open pxl file; ⟨ Start up the pxl file 62 ⟩⟨ Translate all the characters 70 ⟩; print nl ; ⟨ Finish off the pxl file 63 ⟩print (´ ␣ ␣´ , total chars : 1, ´ ␣ ´ ); if total chars ≠ 1 then print (´ ´ ); print (´ ␣ ´ );

final end : end.

68. The main program needs a few global variables in order to do its work. ⟨ Globals in the outer block 10 ⟩ +≡ a: integer ; { byte number of the current command } o, p, q: integer ; { general purpose registers } bad char : boolean; { has a non-ASCII character code appeared in this xxx ? }

69. looks at the preamble in order to do error checking, and to display the introductory comment. ⟨ Process the preamble 69 ⟩ ≡

o ← get byte; { fetch the first byte } if o ≠ pre then bad gf (´ ␣ ␣ ´ ´ ␣ ␣ ␣ ´ ); o ← get byte; { fetch the identification byte } if o ≠ gf id byte then error (´ ␣ ␣ ␣ ␣´ , gf id byte : 1, ´ ␣ ␣´ , o : 1, ´ ´ ); o ← get byte; { fetch the length of the introductory comment } print (´ ´ ´ ´ ); while o > 0 do

begin decr (o); print (xchr [get byte]); end;

print ln(´ ´ ´ ´ );

This code is used in section 67.

70. ⟨ Translate all the characters 70 ⟩ ≡

repeat ⟨ Pass nop, xxx and yyy commands 71 ⟩;

if o ≠ post then begin if (o ≠ boc) ∧ (o ≠ boc1 ) then bad gf (´ ␣´ , cur loc − 1 : 1, ´ ␣ ␣ ␣ ␣ ´ , o : 1, ´ ´ ); ⟨ Pass a boc command 72 ⟩; if ¬do char then bad gf (´ ␣ ␣ ´ ); print (´ ´ ); incr (total chars ); if (total chars mod 10) = 0 then print nl ; end

until o = post ;

This code is used in section 67.

26  THE MAIN PROGRAM  GFtoPXL §71

71. ⟨ Pass nop, xxx and yyy commands 71 ⟩ ≡

repeat a ← cur loc; o ← get byte; p ← first par (o); if eof (gf file) then bad gf (´ ␣ ␣ ␣ ´ ); if o = yyy then

begin ⟨ Translate a yyy command 47 ⟩; o ← nop; end

else if (o ≥ xxx1 ) ∧ (o ≤ xxx1 + 3) then begin ⟨ Translate an xxx command 46 ⟩; o ← nop; end;

until o ≠ nop;

This code is used in section 70.

72. ⟨ Pass a boc command 72 ⟩ ≡ a ← cur loc; if o = boc1 then

begin char code ← get byte; q ← get byte; max m ← get byte; min m ← max m − q; q ← get byte; max n ← get byte; min n ← max n − q; end

else begin char code ← get two bytes ; char code ← get two bytes ; p ← signed quad ;

{ ignore backpointer } min m ← signed quad ; max m ← signed quad ; min n ← signed quad ; max n ← signed quad ; end;

print (´ ´ , char code : 1); if char code > max glyph no then abort (´ ␣ ␣ ␣ ´ ); if char code > ec then ec ← char code; if char code < bc then bc ← char code; if min m < left pixel then abort (´ ␣ ␣ ␣ ´ ); if max m > right pixel then abort (´ ␣ ␣ ␣ ´ ); if min n < bot pixel then abort (´ ␣ ␣ ␣ ´ ); if max n > top pixel then abort (´ ␣ ␣ ␣ ´ ); ⟨ Clear the image 37 ⟩; n ← max n; m ← min m; paint switch ← white;

This code is used in section 70.

§73  GFtoPXL  SYSTEM-DEPENDENT CHANGES 27

73. System-dependent changes. This section should be replaced, if necessary, by changes to the program that are necessary to make work at a particular installation. It is usually best to design your change file so that all changes to previous sections preserve the section numbering; then everybody’s version will be consistent with the printed program. More extensive changes, which introduce new sections, can be inserted here; then only the index itself will get a new section number.

28  INDEX  GFtoPXL §74

74. Index. Pointers to error messages appear here together with the section numbers where each identifier is used.

a: \underline{29}, \underline{68}. abort : \underline{8}, 56, 63, 72. : 57. ASCII code: 10, 11, \underline{12}, 14. b: \underline{29}. backpointers: 22. : 8. bad char : 46, \underline{68}. bad gf : \underline{8}, 43, 55, 57, 69, 70, 71. banner : \underline{1}, 4. bc: \underline{59}, 60, 72. begin: 2. black : 18, 19, 33, \underline{35}, 49, 51. boc: 17, 19, \underline{20}, 21, 22, 32, 41, 42, 45, 70. : 45. boc1 : 19, \underline{20}, 41, 45, 70, 72. boolean: 35, 42, 68. bot pixel : \underline{6}, 33, 72. buffer : \underline{10}. byte: 42. : 70. : 57. byte file: \underline{24}, 25. c: \underline{11}, \underline{29}, \underline{53}. char : 13. : 70. char code: \underline{39}, 60, 61, 63, 64, 72. char loc: 19, \underline{20}, 22, 41, 56. char loc0 : \underline{19}, \underline{20}, 41, 56. : 48. check sum: 21. check sum: 53, \underline{54}, 63. Chinese characters: 22. chr : 9, 13, 14, 16. cols : 51, \underline{52}, 61. cols offset : \underline{59}, 60, 61, 63. complement : \underline{35}, 48. cs : \underline{21}. cur loc: 26, \underline{28}, 29, 31, 43, 53, 55, 70, 71, 72. cur pos : 31. d: \underline{29}. debug: \underline{2}, \underline{51}, \underline{62}, \underline{63}. debugging: 2. decr : \underline{7}, 38, 46, 48, 49, 51, 57, 64, 69. del m: \underline{19}. del n: \underline{19}. delta: \underline{9}. design size: 21. design size: 53, \underline{54}, 63. device width: \underline{54}, 56. dm: \underline{19}. do char : 32, 41, \underline{42}, 44, 70. do nothing : \underline{7}, 45, 47. ds : \underline{21}. dx : 19, 22. dy : 19, 22. ec: \underline{59}, 60, 72. eebug: \underline{2}, \underline{64}. eight bits : \underline{24}, 29, 41, 42. eight cases : \underline{41}. eighteen cases : \underline{41}. eighty two cases : \underline{41}. else: 3. end: 2, 3. endcases: \underline{3}. eoc: 17, 19, \underline{20}, 21, 41, 45. eof : 29, 31, 43, 55, 71. error : \underline{43}, 44, 45, 46, 48, 55, 64, 69. false: 35, 42, 46. final end : \underline{5}, 8, 67. find postamble: \underline{57}, 67. : 69. first par : \underline{41}, 43, 44, 56, 71. first text char : \underline{13}, 16. four cases : \underline{41}, 44. Fuchs, David Raymond: 23. get byte: \underline{29}, 31, 41, 43, 46, 55, 56, 57, 69, 71, 72. get three bytes : \underline{29}, 41. get two bytes : \underline{29}, 41, 72. gf file: \underline{4}, \underline{25}, 26, 28, 29, 31, 43, 55, 71. gf id byte: \underline{19}, 55, 57, 69. gf length: \underline{31}, 57. GF to PXL: \underline{4}, 6. glyph cols : \underline{59}, 60, 61, 63. glyph ptr : \underline{59}, 60, 61, 63, 64. glyph rows : \underline{59}, 60, 61, 63. gubed: \underline{2}. gubee: \underline{2}. hppp: \underline{21}, 53, \underline{54}. i: \underline{4}. : 57. : 55, 69. image: \underline{36}, 37, 38, 48, 51, 65, 66. image array : 1, \underline{36}, 37. incr : \underline{7}, 29, 30, 37, 38, 48, 51, 60, 65, 66, 70. initialize: \underline{4}, 67. input ln: 10. integer : 4, 9, 28, 29, 30, 31, 39, 41, 42, 52,

53, 54, 57, 59, 68. Japanese characters: 22.

§74  GFtoPXL  INDEX 29

jump out : \underline{8}. k: \underline{53}, \underline{57}. last text char : \underline{13}, 16. left pixel : \underline{6}, 33, 72. line length: \underline{6}. lower casify : \underline{11}. m: \underline{34}, \underline{53}. magnification: 53, \underline{54}. max glyph no: \underline{6}, 54, 56, 59, 60, 63, 72. max m: 19, \underline{21}, 37, 38, 51, 53, \underline{54}, 58, 64, 66, 72. max n: 19, \underline{21}, 37, 38, 51, 53, \underline{54}, 61, 64, 72. max new row : \underline{20}, 44. min m: 19, \underline{21}, 37, 38, 49, 50, 51, 53, \underline{54}, 58,

61, 64, 72. min n: 19, \underline{21}, 37, 38, 51, 53, \underline{54}, 64, 72. move to byte: \underline{31}, 57. n: \underline{34}. negate: \underline{7}, 9. new row 0 : 19, \underline{20}, 41, 44. new row 1 : \underline{19}. new row 164 : \underline{19}. nine cases : \underline{41}. no black : \underline{51}. no op: 19, 22. : 46. nop: \underline{20}, 41, 45, 56, 71. : 55. num bytes : 51, \underline{52}, 64. o: \underline{42}, \underline{68}. one hundred sixty five cases : \underline{41}. open gf file: \underline{26}, 67. open pxl file: \underline{27}, 67. ord : 9, 14. oriental characters: 22. othercases: \underline{3}. others : 3. output : \underline{4}. p: \underline{42}, \underline{53}, \underline{68}. paint switch: \underline{18}, 19, 33, \underline{34}, 35, 48, 49, 50, 72. paint 0 : 19, \underline{20}, 41. paint1 : 19, \underline{20}, 41, 44. paint2 : \underline{19}. paint3 : \underline{19}. pixel : 34, \underline{35}, 36. : 72. post : 17, 19, \underline{20}, 21, 23, 41, 45, 53, 57, 70. : 57. post loc: 53, \underline{54}, 55, 57. post post : 19, \underline{20}, 21, 23, 41, 45, 55. : 45. : 55. pre: 17, 19, \underline{20}, 41, 45, 69. : 45. print : \underline{4}, 8, 9, 38, 43, 53, 67, 69, 70, 72. print ln: \underline{4}, 38, 42, 51, 53, 62, 63, 69. print nl : \underline{4}, 43, 51, 64, 67, 70. print scaled : \underline{9}, 53. proofing : 22. pxl : 64. pxl byte: 28, \underline{30}, 64, 65, 66. pxl byte no: \underline{28}, 30, 62, 63, 64. pxl dir ptr : \underline{59}, 63. pxl file: \underline{4}, \underline{25}, 27, 28, 30, 63. pxl halfword : \underline{30}, 63. pxl id : \underline{58}, 62, 63. pxl mag : 53, \underline{59}, 63. pxl word : \underline{30}, 62, 63. q: \underline{42}, \underline{53}, \underline{57}, \underline{68}. read : 29. read postamble: \underline{53}, 67. real : 54. reset : 26. resolution: \underline{1}, 53. rewrite: 27. right pixel : \underline{6}, 33, 48, 72. round : 53, 56. rows : 51, \underline{52}, 61. rows offset : \underline{59}, 60, 61, 63. s: \underline{9}. scaled : 19, 21, 22. select : 42. set pos : 31. : 55. : 55. signed byte: \underline{29}. signed pair : \underline{29}. signed quad : \underline{29}, 41, 53, 55, 56, 57, 72. signed trio: \underline{29}. sixteen cases : \underline{41}. sixty four cases : \underline{41}. skip0 : 19, \underline{20}, 41, 44. skip1 : 19, \underline{20}, 41. skip2 : \underline{19}. skip3 : \underline{19}. system dependencies: \underline{3}, 8, 10, 13, 23, 24, 29,

31, 35, 36, 37, 73. term in: \underline{10}. term out : \underline{10}. terminal line length: \underline{6}, 10. text char : \underline{13}, 14. text file: 10, \underline{13}. tfm width: \underline{54}, 56, 63. : 43, 71. thirty two cases : \underline{41}. three cases : \underline{41}. top pixel : \underline{6}, 33, 72. total chars : \underline{39}, 40, 67, 70. true: 35, 42, 46. : 44. undefined commands : \underline{20}, 41. unity : \underline{9}, 56. vppp: \underline{21}, 53, \underline{54}. w: \underline{30}. white: 19, 33, \underline{35}, 37, 38, 50, 72. write: 4, 30. write ln: 4. x coord : \underline{33}, 34, 36. xchr : \underline{14}, 15, 16, 69. xord : \underline{14}, 16. xxx1 : 19, \underline{20}, 41, 44, 71. xxx2 : \underline{19}. xxx3 : 19. xxx4 : \underline{19}. y coord : \underline{33}, 34, 36. yyy : 19, \underline{20}, 22, 41, 44, 71.

§74  GFtoPXL  NAMES OF THE SECTIONS 31

⟨ Cases for commands nop, pre, post , post post , boc, and eoc 45 ⟩ Used in section 44.

⟨ Clear the image 37 ⟩ Used in section 72.

⟨ Constants in the outer block 6 ⟩ Used in section 4.

⟨ Encode the glyph 64 ⟩ Used in section 42. ⟨ Finish off the pxl file 63 ⟩ Used in section 67. ⟨ Get full byte 65 ⟩ Used in section 64. ⟨ Get mixed byte 66 ⟩ Used in section 64. ⟨ Globals in the outer block 10, 14, 25, 28, 34, 36, 39, 52, 54, 59, 68 ⟩ Used in section 4.

⟨ Labels in the outer block 5 ⟩ Used in section 4. ⟨ Make sure that the end of the file is well-formed 55 ⟩ Used in section 53.

⟨ Pass a boc command 72 ⟩ Used in section 70.

⟨ Pass nop, xxx and yyy commands 71 ⟩ Used in section 70.

⟨ Print the image 38 ⟩ Used in section 64.

⟨ Process the character locations in the postamble 56 ⟩ Used in section 53. ⟨ Process the preamble 69 ⟩ Used in section 67. ⟨ Remove white rows and columns 51 ⟩ Used in section 42. ⟨ Save directory info. 61 ⟩ Used in section 42.

⟨ Set initial values 15, 16, 40, 60 ⟩ Used in section 4. ⟨ Start up the pxl file 62 ⟩ Used in section 67.

⟨ Translate a new row command 49 ⟩ Used in section 44. ⟨ Translate a paint command 48 ⟩ Used in section 44. ⟨ Translate a skip command 50 ⟩ Used in section 44.

⟨ Translate a yyy command 47 ⟩ Used in sections 44 and 71.

⟨ Translate all the characters 70 ⟩ Used in section 67.

⟨ Translate an xxx command 46 ⟩ Used in sections 44 and 71.

⟨ Translate command o 44 ⟩ Used in section 43. ⟨ Translate the next command in the file; goto 9999 if it was eoc; goto 9998 if premature termination is

needed 43 ⟩ Used in section 42. ⟨ Types in the outer block 12, 13, 24, 33, 35 ⟩ Used in section 4.

The GFtoPXL processor

(Version 2.1, January 22, 1996)

Section Page

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 Optional modes of output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3 The character set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 4 Generic font file format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 6 Input and Output for binary files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 11 Translation to raster form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 14 Reading the postamble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 20 PXL Matrix Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 22 The main program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 25 System-dependent changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 27 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 28

The preparation of this report was supported in part by the National Science Foundation under grants IST-8201926 and MCS-8300984, and by the System Development Foundation. ‘TEX’ is a trademark of the American Mathematical Society.