home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / unixtex-6.1b-src.tgz / tar.out / contrib / unixtex / web2c / fontutil / gftodvi.web (.txt) < prev    next >
Texinfo Document  |  1996-09-28  |  187KB  |  3,721 lines

  1. % This program by D. E. Knuth is not copyrighted and can be used freely.
  2. % Version 0 was completed on April 23, 1984.
  3. % Version 0.1 added char_code output (May 4).
  4. % Version 0.2 included rules and dots in the boundary calculations (May 25).
  5. % Version 0.3 added label type "/" (May 27).
  6. % Version 0.4 (by Arthur Samuel) improved the dot labeling routine (July 23).
  7. % Version 0.5 added the slant font for rules (September 2).
  8. % Version 0.6 changed label types and allowed invisible dots (September 28).
  9. % Version 1.0 switched to new GF format (December 8).
  10. % Version 1.1 switched to newer GF format (February 2, 1985).
  11. % Version 1.2 added the offset operations of MF version 0.8 (April 1, 1985).
  12. % Version 1.3 allowed online entry of gray font, etc. (April 22, 1985).
  13. % Version 1.4 allowed "almost" horizontal or vertical rules (May 20, 1985).
  14. % Version 1.5 corrected a bug in the diagonal slant routine (June 18, 1985).
  15. % Version 1.6 corrected a bug if labels exist but no dots (September 13, 1985).
  16. % Version 1.7 changed from am to cm fonts; fam became ext (October 5, 1985).
  17. % Version 2.0 was tuned up for the METAFONTware report (April, 1989).
  18. % Version 3.0 uses 8-bit codes and extended ligatures (October, 1989).
  19. % Here is TeX material that gets inserted after \input webmac
  20. \def\hang{\hangindent 3em\indent\ignorespaces}
  21. \font\ninerm=cmr9
  22. \let\mc=\ninerm % medium caps for names like SAIL
  23. \def\PASCAL{Pascal}
  24. \font\logo=manfnt % font used for the METAFONT logo
  25. \def\MF{{\logo META}\-{\logo FONT}}
  26. \let\swap=\leftrightarrow
  27. \def\(#1){} % this is used to make section names sort themselves better
  28. \def\9#1{} % this is used for sort keys in the index
  29. \def\title{GF$\,$\lowercase{to}$\,$DVI}
  30. \def\contentspagenumber{301}
  31. \def\topofcontents{\null
  32.   \def\titlepage{F} % include headline on the contents page
  33.   \def\rheader{\mainfont\hfil \contentspagenumber}
  34.   \vfill
  35.   \centerline{\titlefont The {\ttitlefont GFtoDVI} processor}
  36.   \vskip 15pt
  37.   \centerline{(Version 3.0, October 1989)}
  38.   \vfill}
  39. \def\botofcontents{\vfill
  40.   \centerline{\hsize 5in\baselineskip9pt
  41.     \vbox{\ninerm\noindent
  42.     The preparation of this report
  43.     was supported in part by the National Science
  44.     Foundation under grants IST-8201926, MCS-8300984, and
  45.     CCR-8610181,
  46.     and by the System Development Foundation. `\TeX' is a
  47.     trademark of the American Mathematical Society.
  48.     `{\logo hijklmnj}\kern1pt' is a trademark of Addison-Wesley
  49.     Publishing Company.}}}
  50. \pageno=\contentspagenumber \advance\pageno by 1
  51. @* Introduction.
  52. The \.{GFtoDVI} utility program reads binary generic font (``\.{GF}'')
  53. files that are produced by font compilers such as \MF, and converts them
  54. into device-independent (``\.{DVI}'') files that can be printed to give
  55. annotated hardcopy proofs of the character shapes. The annotations are
  56. specified by the comparatively simple conventions of plain \MF; i.e.,
  57. there are mechanisms for labeling chosen points and for superimposing
  58. horizontal or vertical rules on the enlarged character shapes.
  59. The purpose of \.{GFtoDVI} is simply to make proof copies; it does not
  60. exhaustively test the validity of a \.{GF} file, nor do its algorithms
  61. much resemble the algorithms that are typically used to prepare font
  62. descriptions for commercial typesetting equipment. Another program,
  63. \.{GFtype}, is available for validity checking; \.{GFtype} also serves
  64. as a model of programs that convert fonts from \.{GF} format to some
  65. other coding scheme.
  66. The |banner| string defined here should be changed whenever \.{GFtoDVI}
  67. gets modified.
  68. @d banner=='This is GFtoDVI, Version 3.0' {printed when the program starts}
  69. @ This program is written in standard \PASCAL, except where it is necessary
  70. to use extensions; for example, \.{GFtoDVI} must read files whose names
  71. are dynamically specified, and such a task would be impossible in pure \PASCAL.
  72. All places where nonstandard constructions are used have been listed in
  73. the index under ``system dependencies.''
  74. @!@^system dependencies@>
  75. Another exception to standard \PASCAL\ occurs in the
  76. use of default branches in |case| statements; the conventions
  77. of \.{TANGLE}, \.{WEAVE}, etc., have been followed.
  78. @d othercases == others: {default for cases not listed explicitly}
  79. @d endcases == @+end {follows the default case in an extended |case| statement}
  80. @f othercases == else
  81. @f endcases == end
  82. @ The main input and output files are not mentioned in the program header,
  83. because their external names
  84. will be determined at run time (e.g., by interpreting the
  85. command line that invokes this program). Error messages and other remarks
  86. are written on the |output| file, which the user may
  87. choose to assign to the terminal if the system permits it.
  88. @^system dependencies@>
  89. The term |print| is used instead of |write| when this program writes on
  90. the |output| file, so that all such output can be easily deflected.
  91. @d print(#)==write(#)
  92. @d print_ln(#)==write_ln(#)
  93. @d print_nl(#)==@+begin write_ln; write(#);@+end
  94. @p program GF_to_DVI(@!output);
  95. label @<Labels in the outer block@>@/
  96. const @<Constants in the outer block@>@/
  97. type @<Types in the outer block@>@/
  98. var @<Globals in the outer block@>@/
  99. procedure initialize; {this procedure gets things started properly}
  100.   var @!i,@!j,@!m,@!n:integer; {loop indices for initializations}
  101.   begin print_ln(banner);@/
  102.   @<Set initial values@>@/
  103.   end;
  104. @ If the program has to stop prematurely, it goes to the
  105. `|final_end|'.
  106. @d final_end=9999 {label for the end of it all}
  107. @<Labels...@>=final_end;
  108. @ The following parameters can be changed at compile time to extend or
  109. reduce \.{GFtoDVI}'s capacity.
  110. @<Constants...@>=
  111. @!max_labels=2000; {maximum number of labels and dots and rules per character}
  112. @!pool_size=10000; {maximum total length of labels and other strings}
  113. @!max_strings=1100; {maximum number of labels and other strings}
  114. @!terminal_line_length=150; {maximum number of characters input in a single
  115.   line of input from the terminal}
  116. @!file_name_size=50; {a file name shouldn't be longer than this}
  117. @!font_mem_size=2000; {space for font metric data}
  118. @!dvi_buf_size=800; {size of the output buffer; must be a multiple of 8}
  119. @!widest_row=8192; {maximum number of pixels per row}
  120. @!lig_lookahead=20; {size of stack used when inserting ligature characters}
  121. @ Labels are given symbolic names by the following definitions, so that
  122. occasional |goto| statements will be meaningful. We insert the label
  123. `|exit|:' just before the `\ignorespaces|end|\unskip' of a procedure in
  124. which we have used the `|return|' statement defined below; the label
  125. `|reswitch|' is occasionally used just prior to a |case|
  126. statement in which some cases change the conditions and we wish to branch
  127. to the newly applicable case.  Loops that are set up with the |loop|
  128. construction defined below are commonly exited by going to `|done|' or to
  129. `|found|' or to `|not_found|', and they are sometimes repeated by going to
  130. `|continue|'.
  131. Incidentally, this program never declares a label that isn't actually used,
  132. because some fussy \PASCAL\ compilers will complain about redundant labels.
  133. @d exit=10 {go here to leave a procedure}
  134. @d reswitch=21 {go here to start a case statement again}
  135. @d continue=22 {go here to resume a loop}
  136. @d done=30 {go here to exit a loop}
  137. @d done1=31 {like |done|, when there is more than one loop}
  138. @d found=40 {go here when you've found it}
  139. @d not_found=45 {go here when you've found nothing}
  140. @ Here are some macros for common programming idioms.
  141. @d incr(#) == #:=#+1 {increase a variable by unity}
  142. @d decr(#) == #:=#-1 {decrease a variable by unity}
  143. @d loop == @+ while true do@+ {repeat over and over until a |goto| happens}
  144. @f loop == xclause
  145.   {\.{WEB}'s |xclause| acts like `\ignorespaces|while true do|\unskip'}
  146. @d do_nothing == {empty statement}
  147. @d return == goto exit {terminate a procedure call}
  148. @f return == nil {\.{WEB} will henceforth say |return| instead of \\{return}}
  149. @ If the \.{GF} file is badly malformed, the whole process must be aborted;
  150. \.{GFtoDVI} will give up, after issuing an error message about the symptoms
  151. that were noticed.
  152. Such errors might be discovered inside of subroutines inside of subroutines,
  153. so a procedure called |jump_out| has been introduced. This procedure, which
  154. simply transfers control to the label |final_end| at the end of the program,
  155. contains the only non-local |goto| statement in \.{GFtoDVI}.
  156. @^system dependencies@>
  157. @d abort(#)==@+begin print(' ',#); jump_out;@+end
  158. @d bad_gf(#)==abort('Bad GF file: ',#,'! (at byte ',cur_loc-1:1,')')
  159. @.Bad GF file@>
  160. @p procedure jump_out;
  161. begin goto final_end;
  162. @ As in \TeX\ and \MF, this program deals with numeric quantities that
  163. are integer multiples of~$2^{16}$, and calls them |scaled|.
  164. @d unity==@'200000 {|scaled| representation of 1.0}
  165. @<Types ...@>=
  166. @!scaled=integer; {fixed-point numbers}
  167. @* The character set.
  168. Like all programs written with the  \.{WEB} system, \.{GFtoDVI} can be
  169. used with any character set. But it uses ASCII code internally, because
  170. the programming for portable input-output is easier when a fixed internal
  171. code is used. Furthermore, both \.{GF} and \.{DVI} files use ASCII code
  172. for file names and certain other strings.
  173. The next few sections of \.{GFtoDVI} have therefore been copied from the
  174. analogous ones in the \.{WEB} system routines.
  175. @<Types ...@>=
  176. @!ASCII_code=0..255; {eight-bit numbers, a subrange of the integers}
  177. @ The original \PASCAL\ compiler was designed in the late 60s, when
  178. six-bit character sets were common, so it did not make provision for lowercase
  179. letters. Nowadays, of course, we need to deal with both capital and
  180. small letters in a convenient way.  So we shall assume that the
  181. \PASCAL\ system being used for \.{GFtoDVI} has a character set containing
  182. at least the standard visible ASCII characters (|"!"| through |"~"|). If
  183. additional characters are present, \.{GFtoDVI} can be configured to
  184. work with them too.
  185. Some \PASCAL\ compilers use the original name |char| for the data type
  186. associated with the characters in text files, while other \PASCAL s
  187. consider |char| to be a 64-element subrange of a larger data type that has
  188. some other name.  In order to accommodate this difference, we shall use
  189. the name |text_char| to stand for the data type of the characters in the
  190. output file.  We shall also assume that |text_char| consists of
  191. the elements |chr(first_text_char)| through |chr(last_text_char)|,
  192. inclusive. The following definitions should be adjusted if necessary.
  193. @^system dependencies@>
  194. @d text_char == char {the data type of characters in text files}
  195. @d first_text_char=0 {ordinal number of the smallest element of |text_char|}
  196. @d last_text_char=255 {ordinal number of the largest element of |text_char|}
  197. @<Types ...@>=
  198. @!text_file=packed file of text_char;
  199. @ The \.{GFtoDVI} processor converts between ASCII code and
  200. the user's external character set by means of arrays |xord| and |xchr|
  201. that are analogous to \PASCAL's |ord| and |chr| functions.
  202. @<Globals...@>=
  203. @!xord: array [text_char] of ASCII_code;
  204.   {specifies conversion of input characters}
  205. @!xchr: array [ASCII_code] of text_char;
  206.   {specifies conversion of output characters}
  207. @ Under our assumption that the visible characters of standard ASCII are
  208. all present, the following assignment statements initialize the
  209. |xchr| array properly, without needing any system-dependent changes.
  210. @<Set init...@>=
  211. xchr[@'40]:=' ';
  212. xchr[@'41]:='!';
  213. xchr[@'42]:='"';
  214. xchr[@'43]:='#';
  215. xchr[@'44]:='$';
  216. xchr[@'45]:='%';
  217. xchr[@'46]:='&';
  218. xchr[@'47]:='''';@/
  219. xchr[@'50]:='(';
  220. xchr[@'51]:=')';
  221. xchr[@'52]:='*';
  222. xchr[@'53]:='+';
  223. xchr[@'54]:=',';
  224. xchr[@'55]:='-';
  225. xchr[@'56]:='.';
  226. xchr[@'57]:='/';@/
  227. xchr[@'60]:='0';
  228. xchr[@'61]:='1';
  229. xchr[@'62]:='2';
  230. xchr[@'63]:='3';
  231. xchr[@'64]:='4';
  232. xchr[@'65]:='5';
  233. xchr[@'66]:='6';
  234. xchr[@'67]:='7';@/
  235. xchr[@'70]:='8';
  236. xchr[@'71]:='9';
  237. xchr[@'72]:=':';
  238. xchr[@'73]:=';';
  239. xchr[@'74]:='<';
  240. xchr[@'75]:='=';
  241. xchr[@'76]:='>';
  242. xchr[@'77]:='?';@/
  243. xchr[@'100]:='@@';
  244. xchr[@'101]:='A';
  245. xchr[@'102]:='B';
  246. xchr[@'103]:='C';
  247. xchr[@'104]:='D';
  248. xchr[@'105]:='E';
  249. xchr[@'106]:='F';
  250. xchr[@'107]:='G';@/
  251. xchr[@'110]:='H';
  252. xchr[@'111]:='I';
  253. xchr[@'112]:='J';
  254. xchr[@'113]:='K';
  255. xchr[@'114]:='L';
  256. xchr[@'115]:='M';
  257. xchr[@'116]:='N';
  258. xchr[@'117]:='O';@/
  259. xchr[@'120]:='P';
  260. xchr[@'121]:='Q';
  261. xchr[@'122]:='R';
  262. xchr[@'123]:='S';
  263. xchr[@'124]:='T';
  264. xchr[@'125]:='U';
  265. xchr[@'126]:='V';
  266. xchr[@'127]:='W';@/
  267. xchr[@'130]:='X';
  268. xchr[@'131]:='Y';
  269. xchr[@'132]:='Z';
  270. xchr[@'133]:='[';
  271. xchr[@'134]:='\';
  272. xchr[@'135]:=']';
  273. xchr[@'136]:='^';
  274. xchr[@'137]:='_';@/
  275. xchr[@'140]:='`';
  276. xchr[@'141]:='a';
  277. xchr[@'142]:='b';
  278. xchr[@'143]:='c';
  279. xchr[@'144]:='d';
  280. xchr[@'145]:='e';
  281. xchr[@'146]:='f';
  282. xchr[@'147]:='g';@/
  283. xchr[@'150]:='h';
  284. xchr[@'151]:='i';
  285. xchr[@'152]:='j';
  286. xchr[@'153]:='k';
  287. xchr[@'154]:='l';
  288. xchr[@'155]:='m';
  289. xchr[@'156]:='n';
  290. xchr[@'157]:='o';@/
  291. xchr[@'160]:='p';
  292. xchr[@'161]:='q';
  293. xchr[@'162]:='r';
  294. xchr[@'163]:='s';
  295. xchr[@'164]:='t';
  296. xchr[@'165]:='u';
  297. xchr[@'166]:='v';
  298. xchr[@'167]:='w';@/
  299. xchr[@'170]:='x';
  300. xchr[@'171]:='y';
  301. xchr[@'172]:='z';
  302. xchr[@'173]:='{';
  303. xchr[@'174]:='|';
  304. xchr[@'175]:='}';
  305. xchr[@'176]:='~';
  306. @ Here now is the system-dependent part of the character set.
  307. If \.{GFtoDVI} is being implemented on a garden-variety \PASCAL\ for which
  308. only standard ASCII codes will appear in the input and output files, you
  309. don't need to make any changes here. But if you have, for example, an extended
  310. character set like the one in Appendix~C of {\sl The \TeX book}, the first
  311. line of code in this module should be changed to
  312. $$\hbox{|for i:=0 to @'37 do xchr[i]:=chr(i);|}$$
  313. \.{WEB}'s character set is essentially identical to \TeX's.
  314. @^system dependencies@>
  315. @<Set init...@>=
  316. for i:=0 to @'37 do xchr[i]:='?';
  317. for i:=@'177 to @'377 do xchr[i]:='?';
  318. @ The following system-independent code makes the |xord| array contain a
  319. suitable inverse to the information in |xchr|.
  320. @<Set init...@>=
  321. for i:=first_text_char to last_text_char do xord[chr(i)]:=" ";
  322. for i:=1 to @'377 do xord[xchr[i]]:=i;
  323. xord['?']:="?";
  324. @ The |input_ln| routine waits for the user to type a line at his or her
  325. terminal; then it puts ASCII-code equivalents for the characters on that line
  326. into the |buffer| array. The |term_in| file is used for terminal input.
  327. @^system dependencies@>
  328. Since the terminal is being used for both input and output, some systems
  329. need a special routine to make sure that the user can see a prompt message
  330. before waiting for input based on that message. (Otherwise the message
  331. may just be sitting in a hidden buffer somewhere, and the user will have
  332. no idea what the program is waiting for.) We shall call a system-dependent
  333. subroutine |update_terminal| in order to avoid this problem.
  334. @d update_terminal == break(output) {empty the terminal output buffer}
  335. @<Glob...@>=
  336. @!buffer:array[0..terminal_line_length] of 0..255;
  337. @!term_in:text_file; {the terminal, considered as an input file}
  338. @ A global variable |line_length| records the first buffer position after
  339. the line just read.
  340. @^system dependencies@>
  341. @p procedure input_ln; {inputs a line from the terminal}
  342. begin update_terminal; reset(term_in);
  343. if eoln(term_in) then read_ln(term_in);
  344. line_length:=0;
  345. while (line_length<terminal_line_length)and not eoln(term_in) do
  346.   begin buffer[line_length]:=xord[term_in^]; incr(line_length); get(term_in);
  347.   end;
  348. @ The global variable |buf_ptr| is used while scanning each line of input;
  349. it points to the first unread character in |buffer|.
  350. @<Glob...@>=
  351. @!buf_ptr:0..terminal_line_length; {the number of characters read}
  352. @!line_length:0..terminal_line_length; {end of line read by |input_ln|}
  353. @* Device-independent file format.
  354. Before we get into the details of \.{GFtoDVI}, we need to know exactly
  355. what \.{DVI} files are. The form of such files was designed by David R.
  356. @^Fuchs, David Raymond@>
  357. Fuchs in 1979. Almost any reasonable typesetting device can be driven by
  358. a program that takes \.{DVI} files as input, and dozens of such
  359. \.{DVI}-to-whatever programs have been written. Thus, it is possible to
  360. print the output of document compilers like \TeX\ on many different kinds
  361. of equipment. (The following material has been copied almost verbatim from the
  362. program for \TeX.)
  363. A \.{DVI} file is a stream of 8-bit bytes, which may be regarded as a
  364. series of commands in a machine-like language. The first byte of each command
  365. is the operation code, and this code is followed by zero or more bytes
  366. that provide parameters to the command. The parameters themselves may consist
  367. of several consecutive bytes; for example, the `|set_rule|' command has two
  368. parameters, each of which is four bytes long. Parameters are usually
  369. regarded as nonnegative integers; but four-byte-long parameters,
  370. and shorter parameters that denote distances, can be
  371. either positive or negative. Such parameters are given in two's complement
  372. notation. For example, a two-byte-long distance parameter has a value between
  373. $-2^{15}$ and $2^{15}-1$.
  374. @.DVI {\rm files}@>
  375. Incidentally, when two or more 8-bit bytes are combined to form an integer of
  376. 16 or more bits, the most significant bytes appear first in the file.
  377. This is called BigEndian order.
  378. @^BigEndian order@>
  379. A \.{DVI} file consists of a ``preamble,'' followed by a sequence of one
  380. or more ``pages,'' followed by a ``postamble.'' The preamble is simply a
  381. |pre| command, with its parameters that define the dimensions used in the
  382. file; this must come first.  Each ``page'' consists of a |bop| command,
  383. followed by any number of other commands that tell where characters are to
  384. be placed on a physical page, followed by an |eop| command. The pages
  385. appear in the order that they were generated, not in any particular
  386. numerical order. If we ignore |nop| commands and \\{fnt\_def} commands
  387. (which are allowed between any two commands in the file), each |eop|
  388. command is immediately followed by a |bop| command, or by a |post|
  389. command; in the latter case, there are no more pages in the file, and the
  390. remaining bytes form the postamble.  Further details about the postamble
  391. will be explained later.
  392. Some parameters in \.{DVI} commands are ``pointers.'' These are four-byte
  393. quantities that give the location number of some other byte in the file;
  394. the first byte is number~0, then comes number~1, and so on. For example,
  395. one of the parameters of a |bop| command points to the previous |bop|;
  396. this makes it feasible to read the pages in backwards order, in case the
  397. results are being directed to a device that stacks its output face up.
  398. Suppose the preamble of a \.{DVI} file occupies bytes 0 to 99. Now if the
  399. first page occupies bytes 100 to 999, say, and if the second
  400. page occupies bytes 1000 to 1999, then the |bop| that starts in byte 1000
  401. points to 100 and the |bop| that starts in byte 2000 points to 1000. (The
  402. very first |bop|, i.e., the one that starts in byte 100, has a pointer of $-1$.)
  403. @ The \.{DVI} format is intended to be both compact and easily interpreted
  404. by a machine. Compactness is achieved by making most of the information
  405. implicit instead of explicit. When a \.{DVI}-reading program reads the
  406. commands for a page, it keeps track of several quantities: (a)~The current
  407. font |f| is an integer; this value is changed only
  408. by \\{fnt} and \\{fnt\_num} commands. (b)~The current position on the page
  409. is given by two numbers called the horizontal and vertical coordinates,
  410. |h| and |v|. Both coordinates are zero at the upper left corner of the page;
  411. moving to the right corresponds to increasing the horizontal coordinate, and
  412. moving down corresponds to increasing the vertical coordinate. Thus, the
  413. coordinates are essentially Cartesian, except that vertical directions are
  414. flipped; the Cartesian version of |(h,v)| would be |(h,-v)|.  (c)~The
  415. current spacing amounts are given by four numbers |w|, |x|, |y|, and |z|,
  416. where |w| and~|x| are used for horizontal spacing and where |y| and~|z|
  417. are used for vertical spacing. (d)~There is a stack containing
  418. |(h,v,w,x,y,z)| values; the \.{DVI} commands |push| and |pop| are used to
  419. change the current level of operation. Note that the current font~|f| is
  420. not pushed and popped; the stack contains only information about
  421. positioning.
  422. The values of |h|, |v|, |w|, |x|, |y|, and |z| are signed integers having up
  423. to 32 bits, including the sign. Since they represent physical distances,
  424. there is a small unit of measurement such that increasing |h| by~1 means
  425. moving a certain tiny distance to the right. The actual unit of
  426. measurement is variable, as explained below.
  427. @ Here is a list of all the commands that may appear in a \.{DVI} file. Each
  428. command is specified by its symbolic name (e.g., |bop|), its opcode byte
  429. (e.g., 139), and its parameters (if any). The parameters are followed
  430. by a bracketed number telling how many bytes they occupy; for example,
  431. `|p[4]|' means that parameter |p| is four bytes long.
  432. \yskip\hang|set_char_0| 0. Typeset character number~0 from font~|f|
  433. such that the reference point of the character is at |(h,v)|. Then
  434. increase |h| by the width of that character. Note that a character may
  435. have zero or negative width, so one cannot be sure that |h| will advance
  436. after this command; but |h| usually does increase.
  437. \yskip\hang|set_char_1| through |set_char_127| (opcodes 1 to 127).
  438. Do the operations of |set_char_0|; but use the character whose number
  439. matches the opcode, instead of character~0.
  440. \yskip\hang|set1| 128 |c[1]|. Same as |set_char_0|, except that character
  441. number~|c| is typeset. \TeX82 uses this command for characters in the
  442. range |128<=c<256|.
  443. \yskip\hang|set2| 129 |c[2]|. Same as |set1|, except that |c|~is two
  444. bytes long, so it is in the range |0<=c<65536|.
  445. \yskip\hang|set3| 130 |c[3]|. Same as |set1|, except that |c|~is three
  446. bytes long, so it can be as large as $2^{24}-1$. Not even the Chinese
  447. language has this many characters, but this command might prove useful
  448. in some yet unforeseen way.
  449. \yskip\hang|set4| 131 |c[4]|. Same as |set1|, except that |c|~is four
  450. bytes long, possibly even negative. Imagine that.
  451. \yskip\hang|set_rule| 132 |a[4]| |b[4]|. Typeset a solid black rectangle
  452. of height |a| and width |b|, with its bottom left corner at |(h,v)|. Then
  453. set |h:=h+b|. If either |a<=0| or |b<=0|, nothing should be typeset. Note
  454. that if |b<0|, the value of |h| will decrease even though nothing else happens.
  455. \yskip\hang|put1| 133 |c[1]|. Typeset character number~|c| from font~|f|
  456. such that the reference point of the character is at |(h,v)|. (The `put'
  457. commands are exactly like the `set' commands, except that they simply put out a
  458. character or a rule without moving the reference point afterwards.)
  459. \yskip\hang|put2| 134 |c[2]|. Same as |set2|, except that |h| is not changed.
  460. \yskip\hang|put3| 135 |c[3]|. Same as |set3|, except that |h| is not changed.
  461. \yskip\hang|put4| 136 |c[4]|. Same as |set4|, except that |h| is not changed.
  462. \yskip\hang|put_rule| 137 |a[4]| |b[4]|. Same as |set_rule|, except that
  463. |h| is not changed.
  464. \yskip\hang|nop| 138. No operation, do nothing. Any number of |nop|'s
  465. may occur between \.{DVI} commands, but a |nop| cannot be inserted between
  466. a command and its parameters or between two parameters.
  467. \yskip\hang|bop| 139 $c_0[4]$ $c_1[4]$ $\ldots$ $c_9[4]$ $p[4]$. Beginning
  468. of a page: Set |(h,v,w,x,y,z):=(0,0,0,0,0,0)| and set the stack empty. Set
  469. the current font |f| to an undefined value.  The ten $c_i$ parameters can
  470. be used to identify pages, if a user wants to print only part of a \.{DVI}
  471. file; \TeX82 gives them the values of \.{\\count0} $\ldots$ \.{\\count9}
  472. at the time \.{\\shipout} was invoked for this page.  The parameter |p|
  473. points to the previous |bop| command in the file, where the first |bop|
  474. has $p=-1$.
  475. \yskip\hang|eop| 140.  End of page: Print what you have read since the
  476. previous |bop|. At this point the stack should be empty. (The \.{DVI}-reading
  477. programs that drive most output devices will have kept a buffer of the
  478. material that appears on the page that has just ended. This material is
  479. largely, but not entirely, in order by |v| coordinate and (for fixed |v|) by
  480. |h|~coordinate; so it usually needs to be sorted into some order that is
  481. appropriate for the device in question. \.{GFtoDVI} does not do such sorting.)
  482. \yskip\hang|push| 141. Push the current values of |(h,v,w,x,y,z)| onto the
  483. top of the stack; do not change any of these values. Note that |f| is
  484. not pushed.
  485. \yskip\hang|pop| 142. Pop the top six values off of the stack and assign
  486. them to |(h,v,w,x,y,z)|. The number of pops should never exceed the number
  487. of pushes, since it would be highly embarrassing if the stack were empty
  488. at the time of a |pop| command.
  489. \yskip\hang|right1| 143 |b[1]|. Set |h:=h+b|, i.e., move right |b| units.
  490. The parameter is a signed number in two's complement notation, |-128<=b<128|;
  491. if |b<0|, the reference point actually moves left.
  492. \yskip\hang|right2| 144 |b[2]|. Same as |right1|, except that |b| is a
  493. two-byte quantity in the range |-32768<=b<32768|.
  494. \yskip\hang|right3| 145 |b[3]|. Same as |right1|, except that |b| is a
  495. three-byte quantity in the range |@t$-2^{23}$@><=b<@t$2^{23}$@>|.
  496. \yskip\hang|right4| 146 |b[4]|. Same as |right1|, except that |b| is a
  497. four-byte quantity in the range |@t$-2^{31}$@><=b<@t$2^{31}$@>|.
  498. \yskip\hang|w0| 147. Set |h:=h+w|; i.e., move right |w| units. With luck,
  499. this parameterless command will usually suffice, because the same kind of motion
  500. will occur several times in succession; the following commands explain how
  501. |w| gets particular values.
  502. \yskip\hang|w1| 148 |b[1]|. Set |w:=b| and |h:=h+b|. The value of |b| is a
  503. signed quantity in two's complement notation, |-128<=b<128|. This command
  504. changes the current |w|~spacing and moves right by |b|.
  505. \yskip\hang|w2| 149 |b[2]|. Same as |w1|, but |b| is a two-byte-long
  506. parameter, |-32768<=b<32768|.
  507. \yskip\hang|w3| 150 |b[3]|. Same as |w1|, but |b| is a three-byte-long
  508. parameter, |@t$-2^{23}$@><=b<@t$2^{23}$@>|.
  509. \yskip\hang|w4| 151 |b[4]|. Same as |w1|, but |b| is a four-byte-long
  510. parameter, |@t$-2^{31}$@><=b<@t$2^{31}$@>|.
  511. \yskip\hang|x0| 152. Set |h:=h+x|; i.e., move right |x| units. The `|x|'
  512. commands are like the `|w|' commands except that they involve |x| instead
  513. of |w|.
  514. \yskip\hang|x1| 153 |b[1]|. Set |x:=b| and |h:=h+b|. The value of |b| is a
  515. signed quantity in two's complement notation, |-128<=b<128|. This command
  516. changes the current |x|~spacing and moves right by |b|.
  517. \yskip\hang|x2| 154 |b[2]|. Same as |x1|, but |b| is a two-byte-long
  518. parameter, |-32768<=b<32768|.
  519. \yskip\hang|x3| 155 |b[3]|. Same as |x1|, but |b| is a three-byte-long
  520. parameter, |@t$-2^{23}$@><=b<@t$2^{23}$@>|.
  521. \yskip\hang|x4| 156 |b[4]|. Same as |x1|, but |b| is a four-byte-long
  522. parameter, |@t$-2^{31}$@><=b<@t$2^{31}$@>|.
  523. \yskip\hang|down1| 157 |a[1]|. Set |v:=v+a|, i.e., move down |a| units.
  524. The parameter is a signed number in two's complement notation, |-128<=a<128|;
  525. if |a<0|, the reference point actually moves up.
  526. \yskip\hang|down2| 158 |a[2]|. Same as |down1|, except that |a| is a
  527. two-byte quantity in the range |-32768<=a<32768|.
  528. \yskip\hang|down3| 159 |a[3]|. Same as |down1|, except that |a| is a
  529. three-byte quantity in the range |@t$-2^{23}$@><=a<@t$2^{23}$@>|.
  530. \yskip\hang|down4| 160 |a[4]|. Same as |down1|, except that |a| is a
  531. four-byte quantity in the range |@t$-2^{31}$@><=a<@t$2^{31}$@>|.
  532. \yskip\hang|y0| 161. Set |v:=v+y|; i.e., move down |y| units. With luck,
  533. this parameterless command will usually suffice, because the same kind of motion
  534. will occur several times in succession; the following commands explain how
  535. |y| gets particular values.
  536. \yskip\hang|y1| 162 |a[1]|. Set |y:=a| and |v:=v+a|. The value of |a| is a
  537. signed quantity in two's complement notation, |-128<=a<128|. This command
  538. changes the current |y|~spacing and moves down by |a|.
  539. \yskip\hang|y2| 163 |a[2]|. Same as |y1|, but |a| is a two-byte-long
  540. parameter, |-32768<=a<32768|.
  541. \yskip\hang|y3| 164 |a[3]|. Same as |y1|, but |a| is a three-byte-long
  542. parameter, |@t$-2^{23}$@><=a<@t$2^{23}$@>|.
  543. \yskip\hang|y4| 165 |a[4]|. Same as |y1|, but |a| is a four-byte-long
  544. parameter, |@t$-2^{31}$@><=a<@t$2^{31}$@>|.
  545. \yskip\hang|z0| 166. Set |v:=v+z|; i.e., move down |z| units. The `|z|' commands
  546. are like the `|y|' commands except that they involve |z| instead of |y|.
  547. \yskip\hang|z1| 167 |a[1]|. Set |z:=a| and |v:=v+a|. The value of |a| is a
  548. signed quantity in two's complement notation, |-128<=a<128|. This command
  549. changes the current |z|~spacing and moves down by |a|.
  550. \yskip\hang|z2| 168 |a[2]|. Same as |z1|, but |a| is a two-byte-long
  551. parameter, |-32768<=a<32768|.
  552. \yskip\hang|z3| 169 |a[3]|. Same as |z1|, but |a| is a three-byte-long
  553. parameter, |@t$-2^{23}$@><=a<@t$2^{23}$@>|.
  554. \yskip\hang|z4| 170 |a[4]|. Same as |z1|, but |a| is a four-byte-long
  555. parameter, |@t$-2^{31}$@><=a<@t$2^{31}$@>|.
  556. \yskip\hang|fnt_num_0| 171. Set |f:=0|. Font 0 must previously have been
  557. defined by a \\{fnt\_def} instruction, as explained below.
  558. \yskip\hang|fnt_num_1| through |fnt_num_63| (opcodes 172 to 234). Set
  559. |f:=1|, \dots, |f:=63|, respectively.
  560. \yskip\hang|fnt1| 235 |k[1]|. Set |f:=k|. \TeX82 uses this command for font
  561. numbers in the range |64<=k<256|.
  562. \yskip\hang|fnt2| 236 |k[2]|. Same as |fnt1|, except that |k|~is two
  563. bytes long, so it is in the range |0<=k<65536|. \TeX82 never generates this
  564. command, but large font numbers may prove useful for specifications of
  565. color or texture, or they may be used for special fonts that have fixed
  566. numbers in some external coding scheme.
  567. \yskip\hang|fnt3| 237 |k[3]|. Same as |fnt1|, except that |k|~is three
  568. bytes long, so it can be as large as $2^{24}-1$.
  569. \yskip\hang|fnt4| 238 |k[4]|. Same as |fnt1|, except that |k|~is four
  570. bytes long; this is for the really big font numbers (and for the negative ones).
  571. \yskip\hang|xxx1| 239 |k[1]| |x[k]|. This command is undefined in
  572. general; it functions as a $(k+2)$-byte |nop| unless special \.{DVI}-reading
  573. programs are being used. \TeX82 generates |xxx1| when a short enough
  574. \.{\\special} appears, setting |k| to the number of bytes being sent. It
  575. is recommended that |x| be a string having the form of a keyword followed
  576. by possible parameters relevant to that keyword.
  577. \yskip\hang|xxx2| 240 |k[2]| |x[k]|. Like |xxx1|, but |0<=k<65536|.
  578. \yskip\hang|xxx3| 241 |k[3]| |x[k]|. Like |xxx1|, but |0<=k<@t$2^{24}$@>|.
  579. \yskip\hang|xxx4| 242 |k[4]| |x[k]|. Like |xxx1|, but |k| can be ridiculously
  580. large. \TeX82 uses |xxx4| when |xxx1| would be incorrect.
  581. \yskip\hang|fnt_def1| 243 |k[1]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
  582. Define font |k|, where |0<=k<256|; font definitions will be explained shortly.
  583. \yskip\hang|fnt_def2| 244 |k[2]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
  584. Define font |k|, where |0<=k<65536|.
  585. \yskip\hang|fnt_def3| 245 |k[3]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
  586. Define font |k|, where |0<=k<@t$2^{24}$@>|.
  587. \yskip\hang|fnt_def4| 246 |k[4]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
  588. Define font |k|, where |@t$-2^{31}$@><=k<@t$2^{31}$@>|.
  589. \yskip\hang|pre| 247 |i[1]| |num[4]| |den[4]| |mag[4]| |k[1]| |x[k]|.
  590. Beginning of the preamble; this must come at the very beginning of the
  591. file. Parameters |i|, |num|, |den|, |mag|, |k|, and |x| are explained below.
  592. \yskip\hang|post| 248. Beginning of the postamble, see below.
  593. \yskip\hang|post_post| 249. Ending of the postamble, see below.
  594. \yskip\noindent Commands 250--255 are undefined at the present time.
  595. @ Only a few of the operation codes above are actually needed by \.{GFtoDVI}.
  596. @d set1=128 {typeset a character and move right}
  597. @d put_rule=137 {typeset a rule}
  598. @d bop=139 {beginning of page}
  599. @d eop=140 {ending of page}
  600. @d push=141 {save the current positions}
  601. @d pop=142 {restore previous positions}
  602. @d right4=146 {move right}
  603. @d down4=160 {move down}
  604. @d z0=166 {move down |z|}
  605. @d z4=170 {move down and set |z|}
  606. @d fnt_num_0=171 {set current font to 0}
  607. @d fnt_def1=243 {define the meaning of a font number}
  608. @d pre=247 {preamble}
  609. @d post=248 {postamble beginning}
  610. @d post_post=249 {postamble ending}
  611. @ The preamble contains basic information about the file as a whole. As
  612. stated above, there are six parameters:
  613. $$\hbox{|@!i[1]| |@!num[4]| |@!den[4]| |@!mag[4]| |@!k[1]| |@!x[k]|.}$$
  614. The |i| byte identifies \.{DVI} format; currently this byte is always set
  615. to~2. (The value |i=3| is currently used for an extended format that
  616. allows a mixture of right-to-left and left-to-right typesetting.
  617. Some day we will set |i=4|, when \.{DVI} format makes another
  618. incompatible change---perhaps in the year 2048.)
  619. The next two parameters, |num| and |den|, are positive integers that define
  620. the units of measurement; they are the numerator and denominator of a
  621. fraction by which all dimensions in the \.{DVI} file could be multiplied
  622. in order to get lengths in units of $10^{-7}$ meters. (For example, there are
  623. exactly 7227 \TeX\ points in 254 centimeters, and \TeX82 works with scaled
  624. points where there are $2^{16}$ sp in a point, so \TeX82 sets |num=25400000|
  625. and $|den|=7227\cdot2^{16}=473628672$.)
  626. @^sp@>
  627. The |mag| parameter is what \TeX82 calls \.{\\mag}, i.e., 1000 times the
  628. desired magnification. The actual fraction by which dimensions are
  629. multiplied is therefore $|mag|\cdot|num|/1000|den|$. Note that if a \TeX\
  630. source document does not call for any `\.{true}' dimensions, and if you
  631. change it only by specifying a different \.{\\mag} setting, the \.{DVI}
  632. file that \TeX\ creates will be completely unchanged except for the value
  633. of |mag| in the preamble and postamble. (Fancy \.{DVI}-reading programs allow
  634. users to override the |mag|~setting when a \.{DVI} file is being printed.)
  635. Finally, |k| and |x| allow the \.{DVI} writer to include a comment, which is not
  636. interpreted further. The length of comment |x| is |k|, where |0<=k<256|.
  637. @d dvi_id_byte=2 {identifies the kind of \.{DVI} files described here}
  638. @ Font definitions for a given font number |k| contain further parameters
  639. $$\hbox{|c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.}$$
  640. The four-byte value |c| is the check sum that \TeX\ (or whatever program
  641. generated the \.{DVI} file) found in the \.{TFM} file for this font;
  642. |c| should match the check sum of the font found by programs that read
  643. this \.{DVI} file.
  644. @^check sum@>
  645. Parameter |s| contains a fixed-point scale factor that is applied to the
  646. character widths in font |k|; font dimensions in \.{TFM} files and other
  647. font files are relative to this quantity, which is always positive and
  648. less than $2^{27}$. It is given in the same units as the other dimensions
  649. of the \.{DVI} file.  Parameter |d| is similar to |s|; it is the ``design
  650. size,'' and (like~|s|) it is given in \.{DVI} units. Thus, font |k| is to be
  651. used at $|mag|\cdot s/1000d$ times its normal size.
  652. The remaining part of a font definition gives the external name of the font,
  653. which is an ASCII string of length |a+l|. The number |a| is the length
  654. of the ``area'' or directory, and |l| is the length of the font name itself;
  655. the standard local system font area is supposed to be used when |a=0|.
  656. The |n| field contains the area in its first |a| bytes.
  657. Font definitions must appear before the first use of a particular font number.
  658. Once font |k| is defined, it must not be defined again; however, we
  659. shall see below that font definitions appear in the postamble as well as
  660. in the pages, so in this sense each font number is defined exactly twice,
  661. if at all. Like |nop| commands, font definitions can
  662. appear before the first |bop|, or between an |eop| and a |bop|.
  663. @ The last page in a \.{DVI} file is followed by `|post|'; this command
  664. introduces the postamble, which summarizes important facts that \TeX\ has
  665. accumulated about the file, making it possible to print subsets of the data
  666. with reasonable efficiency. The postamble has the form
  667. $$\vbox{\halign{\hbox{#\hfil}\cr
  668.   |post| |p[4]| |num[4]| |den[4]| |mag[4]| |l[4]| |u[4]| |s[2]| |t[2]|\cr
  669.   $\langle\,$font definitions$\,\rangle$\cr
  670.   |post_post| |q[4]| |i[1]| 223's$[{\G}4]$\cr}}$$
  671. Here |p| is a pointer to the final |bop| in the file. The next three
  672. parameters, |num|, |den|, and |mag|, are duplicates of the quantities that
  673. appeared in the preamble.
  674. Parameters |l| and |u| give respectively the height-plus-depth of the tallest
  675. page and the width of the widest page, in the same units as other dimensions
  676. of the file. These numbers might be used by a \.{DVI}-reading program to
  677. position individual ``pages'' on large sheets of film or paper; however,
  678. the standard convention for output on normal size paper is to position each
  679. page so that the upper left-hand corner is exactly one inch from the left
  680. and the top. Experience has shown that it is unwise to design \.{DVI}-to-printer
  681. software that attempts cleverly to center the output; a fixed position of
  682. the upper left corner is easiest for users to understand and to work with.
  683. Therefore |l| and~|u| are often ignored.
  684. Parameter |s| is the maximum stack depth (i.e., the largest excess of
  685. |push| commands over |pop| commands) needed to process this file. Then
  686. comes |t|, the total number of pages (|bop| commands) present.
  687. The postamble continues with font definitions, which are any number of
  688. \\{fnt\_def} commands as described above, possibly interspersed with |nop|
  689. commands. Each font number that is used in the \.{DVI} file must be defined
  690. exactly twice: Once before it is first selected by a \\{fnt} command, and once
  691. in the postamble.
  692. @ The last part of the postamble, following the |post_post| byte that
  693. signifies the end of the font definitions, contains |q|, a pointer to the
  694. |post| command that started the postamble.  An identification byte, |i|,
  695. comes next; this currently equals~2, as in the preamble.
  696. The |i| byte is followed by four or more bytes that are all equal to
  697. the decimal number 223 (i.e., @'337 in octal). \TeX\ puts out four to seven of
  698. these trailing bytes, until the total length of the file is a multiple of
  699. four bytes, since this works out best on machines that pack four bytes per
  700. word; but any number of 223's is allowed, as long as there are at least four
  701. of them. In effect, 223 is a sort of signature that is added at the very end.
  702. @^Fuchs, David Raymond@>
  703. This curious way to finish off a \.{DVI} file makes it feasible for
  704. \.{DVI}-reading programs to find the postamble first, on most computers,
  705. even though \TeX\ wants to write the postamble last. Most operating
  706. systems permit random access to individual words or bytes of a file, so
  707. the \.{DVI} reader can start at the end and skip backwards over the 223's
  708. until finding the identification byte. Then it can back up four bytes, read
  709. |q|, and move to byte |q| of the file. This byte should, of course,
  710. contain the value 248 (|post|); now the postamble can be read, so the
  711. \.{DVI} reader can discover all the information needed for typesetting the
  712. pages. Note that it is also possible to skip through the \.{DVI} file at
  713. reasonably high speed to locate a particular page, if that proves
  714. desirable. This saves a lot of time, since \.{DVI} files used in production
  715. jobs tend to be large.
  716. Unfortunately, however, standard \PASCAL\ does not include the ability to
  717. @^system dependencies@>
  718. access a random position in a file, or even to determine the length of a file.
  719. Almost all systems nowadays provide the necessary capabilities, so \.{DVI}
  720. format has been designed to work most efficiently with modern operating systems.
  721. @* Generic font file format.
  722. The ``generic font'' (\.{GF}) input files that \.{GFtoDVI} must deal with
  723. have a structure that was inspired by \.{DVI} format, although the
  724. operation codes are quite different in most cases.  The term {\sl
  725. generic\/} indicates that this file format doesn't match the conventions
  726. of any name-brand manufacturer; but it is easy to convert \.{GF} files to
  727. the special format required by almost all digital phototypesetting
  728. equipment. There's a strong analogy between the \.{DVI} files written by
  729. \TeX\ and the \.{GF} files written by \MF; and, in fact, the reader will
  730. notice that many of the paragraphs below are identical to their
  731. counterparts in the description of \.{DVI} already given. The following
  732. description has been lifted almost verbatim from the program for \MF.
  733. A \.{GF} file is a stream of 8-bit bytes that may be
  734. regarded as a series of commands in a machine-like language. The first
  735. byte of each command is the operation code, and this code is followed by
  736. zero or more bytes that provide parameters to the command. The parameters
  737. themselves may consist of several consecutive bytes; for example, the
  738. `|boc|' (beginning of character) command has six parameters, each of
  739. which is four bytes long. Parameters are usually regarded as nonnegative
  740. integers; but four-byte-long parameters can be either positive or
  741. negative, hence they range in value from $-2^{31}$ to $2^{31}-1$.
  742. As in \.{DVI} files, numbers that occupy
  743. more than one byte position appear in BigEndian order,
  744. and negative numbers appear in two's complement notation.
  745. A \.{GF} file consists of a ``preamble,'' followed by a sequence of one or
  746. more ``characters,'' followed by a ``postamble.'' The preamble is simply a
  747. |pre| command, with its parameters that introduce the file; this must come
  748. first.  Each ``character'' consists of a |boc| command, followed by any
  749. number of other commands that specify ``black'' pixels,
  750. followed by an |eoc| command. The characters appear in the order that \MF\
  751. generated them. If we ignore no-op commands (which are allowed between any
  752. two commands in the file), each |eoc| command is immediately followed by a
  753. |boc| command, or by a |post| command; in the latter case, there are no
  754. more characters in the file, and the remaining bytes form the postamble.
  755. Further details about the postamble will be explained later.
  756. Some parameters in \.{GF} commands are ``pointers.'' These are four-byte
  757. quantities that give the location number of some other byte in the file;
  758. the first file byte is number~0, then comes number~1, and so on.
  759. @ The \.{GF} format is intended to be both compact and easily interpreted
  760. by a machine. Compactness is achieved by making most of the information
  761. relative instead of absolute. When a \.{GF}-reading program reads the
  762. commands for a character, it keeps track of two quantities: (a)~the current
  763. column number,~|m|; and (b)~the current row number,~|n|.  These are 32-bit
  764. signed integers, although most actual font formats produced from \.{GF}
  765. files will need to curtail this vast range because of practical
  766. limitations. (\MF\ output will never allow $\vert m\vert$ or $\vert
  767. n\vert$ to get extremely large, but the \.{GF} format tries to be more general.)
  768. How do \.{GF}'s row and column numbers correspond to the conventions
  769. of \TeX\ and \MF? Well, the ``reference point'' of a character, in \TeX's
  770. view, is considered to be at the lower left corner of the pixel in row~0
  771. and column~0. This point is the intersection of the baseline with the left
  772. edge of the type; it corresponds to location $(0,0)$ in \MF\ programs.
  773. Thus the pixel in \.{GF} row~0 and column~0 is \MF's unit square, comprising the
  774. region of the plane whose coordinates both lie between 0 and~1. The
  775. pixel in \.{GF} row~|n| and column~|m| consists of the points whose \MF\
  776. coordinates |(x,y)| satisfy |m<=x<=m+1| and |n<=y<=n+1|.  Negative values of
  777. |m| and~|x| correspond to columns of pixels {\sl left\/} of the reference
  778. point; negative values of |n| and~|y| correspond to rows of pixels {\sl
  779. below\/} the baseline.
  780. Besides |m| and |n|, there's also a third aspect of the current
  781. state, namely the @!|paint_switch|, which is always either \\{black} or
  782. \\{white}. Each \\{paint} command advances |m| by a specified amount~|d|,
  783. and blackens the intervening pixels if |paint_switch=black|; then
  784. the |paint_switch| changes to the opposite state. \.{GF}'s commands are
  785. designed so that |m| will never decrease within a row, and |n| will never
  786. increase within a character; hence there is no way to whiten a pixel that
  787. has been blackened.
  788. @ Here is a list of all the commands that may appear in a \.{GF} file. Each
  789. command is specified by its symbolic name (e.g., |boc|), its opcode byte
  790. (e.g., 67), and its parameters (if any). The parameters are followed
  791. by a bracketed number telling how many bytes they occupy; for example,
  792. `|d[2]|' means that parameter |d| is two bytes long.
  793. \yskip\hang|paint_0| 0. This is a \\{paint} command with |d=0|; it does
  794. nothing but change the |paint_switch| from \\{black} to \\{white} or vice~versa.
  795. \yskip\hang\\{paint\_1} through \\{paint\_63} (opcodes 1 to 63).
  796. These are \\{paint} commands with |d=1| to~63, defined as follows: If
  797. |paint_switch=black|, blacken |d|~pixels of the current row~|n|,
  798. in columns |m| through |m+d-1| inclusive. Then, in any case,
  799. complement the |paint_switch| and advance |m| by~|d|.
  800. \yskip\hang|paint1| 64 |d[1]|. This is a \\{paint} command with a specified
  801. value of~|d|; \MF\ uses it to paint when |64<=d<256|.
  802. \yskip\hang|paint2| 65 |d[2]|. Same as |paint1|, but |d|~can be as high
  803. as~65535.
  804. \yskip\hang|paint3| 66 |d[3]|. Same as |paint1|, but |d|~can be as high
  805. as $2^{24}-1$. \MF\ never needs this command, and it is hard to imagine
  806. anybody making practical use of it; surely a more compact encoding will be
  807. desirable when characters can be this large. But the command is there,
  808. anyway, just in case.
  809. \yskip\hang|boc| 67 |c[4]| |p[4]| |min_m[4]| |max_m[4]| |min_n[4]|
  810. |max_n[4]|. Beginning of a character:  Here |c| is the character code, and
  811. |p| points to the previous character beginning (if any) for characters having
  812. this code number modulo 256.  (The pointer |p| is |-1| if there was no
  813. prior character with an equivalent code.) The values of registers |m| and |n|
  814. defined by the instructions that follow for this character must
  815. satisfy |min_m<=m<=max_m| and |min_n<=n<=max_n|.  (The values of |max_m| and
  816. |min_n| need not be the tightest bounds possible.)  When a \.{GF}-reading
  817. program sees a |boc|, it can use |min_m|, |max_m|, |min_n|, and |max_n| to
  818. initialize the bounds of an array. Then it sets |m:=min_m|, |n:=max_n|, and
  819. |paint_switch:=white|.
  820. \yskip\hang|boc1| 68 |c[1]| |@!del_m[1]| |max_m[1]| |@!del_n[1]| |max_n[1]|.
  821. Same as |boc|, but |p| is assumed to be~$-1$; also |del_m=max_m-min_m|
  822. and |del_n=max_n-min_n| are given instead of |min_m| and |min_n|.
  823. The one-byte parameters must be between 0 and 255, inclusive.
  824. \ (This abbreviated |boc| saves 19~bytes per character, in common cases.)
  825. \yskip\hang|eoc| 69. End of character: All pixels blackened so far
  826. constitute the pattern for this character. In particular, a completely
  827. blank character might have |eoc| immediately following |boc|.
  828. \yskip\hang|skip0| 70. Decrease |n| by 1 and set |m:=min_m|,
  829. |paint_switch:=white|. \ (This finishes one row and begins another,
  830. ready to whiten the leftmost pixel in the new row.)
  831. \yskip\hang|skip1| 71 |d[1]|. Decrease |n| by |d+1|, set |m:=min_m|, and set
  832. |paint_switch:=white|. This is a way to produce |d| all-white rows.
  833. \yskip\hang|skip2| 72 |d[2]|. Same as |skip1|, but |d| can be as large
  834. as 65535.
  835. \yskip\hang|skip3| 73 |d[3]|. Same as |skip1|, but |d| can be as large
  836. as $2^{24}-1$. \MF\ obviously never needs this command.
  837. \yskip\hang|new_row_0| 74. Decrease |n| by 1 and set |m:=min_m|,
  838. |paint_switch:=black|. \ (This finishes one row and begins another,
  839. ready to {\sl blacken\/} the leftmost pixel in the new row.)
  840. \yskip\hang|@!new_row_1| through |@!new_row_164| (opcodes 75 to 238). Same as
  841. |new_row_0|, but with |m:=min_m+1| through |min_m+164|, respectively.
  842. \yskip\hang|xxx1| 239 |k[1]| |x[k]|. This command is undefined in
  843. general; it functions as a $(k+2)$-byte |no_op| unless special \.{GF}-reading
  844. programs are being used. \MF\ generates \\{xxx} commands when encountering
  845. a \&{special} string; this occurs in the \.{GF} file only between
  846. characters, after the preamble, and before the postamble. However,
  847. \\{xxx} commands might appear within characters,
  848. in \.{GF} files generated by other
  849. processors. It is recommended that |x| be a string having the form of a
  850. keyword followed by possible parameters relevant to that keyword.
  851. \yskip\hang|xxx2| 240 |k[2]| |x[k]|. Like |xxx1|, but |0<=k<65536|.
  852. \yskip\hang|xxx3| 241 |k[3]| |x[k]|. Like |xxx1|, but |0<=k<@t$2^{24}$@>|.
  853. \MF\ uses this when sending a \&{special} string whose length exceeds~255.
  854. \yskip\hang|xxx4| 242 |k[4]| |x[k]|. Like |xxx1|, but |k| can be
  855. ridiculously large; |k| mustn't be negative.
  856. \yskip\hang|yyy| 243 |y[4]|. This command is undefined in general;
  857. it functions as a 5-byte |no_op| unless special \.{GF}-reading programs
  858. are being used. \MF\ puts |scaled| numbers into |yyy|'s, as a
  859. result of \&{numspecial} commands; the intent is to provide numeric
  860. parameters to \\{xxx} commands that immediately precede.
  861. \yskip\hang|no_op| 244. No operation, do nothing. Any number of |no_op|'s
  862. may occur between \.{GF} commands, but a |no_op| cannot be inserted between
  863. a command and its parameters or between two parameters.
  864. \yskip\hang|char_loc| 245 |c[1]| |dx[4]| |dy[4]| |w[4]| |p[4]|.
  865. This command will appear only in the postamble, which will be explained shortly.
  866. \yskip\hang|@!char_loc0| 246 |c[1]| |@!dm[1]| |w[4]| |p[4]|.
  867. Same as |char_loc|, except that |dy| is assumed to be zero, and the value
  868. of~|dx| is taken to be |65536*dm|, where |0<=dm<256|.
  869. \yskip\hang|pre| 247 |i[1]| |k[1]| |x[k]|.
  870. Beginning of the preamble; this must come at the very beginning of the
  871. file. Parameter |i| is an identifying number for \.{GF} format, currently
  872. 131. The other information is merely commentary; it is not given
  873. special interpretation like \\{xxx} commands are. (Note that \\{xxx}
  874. commands may immediately follow the preamble, before the first |boc|.)
  875. \yskip\hang|post| 248. Beginning of the postamble, see below.
  876. \yskip\hang|post_post| 249. Ending of the postamble, see below.
  877. \yskip\noindent Commands 250--255 are undefined at the present time.
  878. @d gf_id_byte=131 {identifies the kind of \.{GF} files described here}
  879. @ Here are the opcodes that \.{GFtoDVI} actually refers to.
  880. @d paint_0=0 {beginning of the \\{paint} commands}
  881. @d paint1=64 {move right a given number of columns, then
  882.   black${}\swap{}$white}
  883. @d paint2=65 {ditto, with potentially larger number of columns}
  884. @d paint3=66 {ditto, with potentially excessive number of columns}
  885. @d boc=67 {beginning of a character}
  886. @d boc1=68 {abbreviated |boc|}
  887. @d eoc=69 {end of a character}
  888. @d skip0=70 {skip no blank rows}
  889. @d skip1=71 {skip over blank rows}
  890. @d skip2=72 {skip over lots of blank rows}
  891. @d skip3=73 {skip over a huge number of blank rows}
  892. @d new_row_0=74 {move down one row and then right}
  893. @d xxx1=239 {for \&{special} strings}
  894. @d xxx2=240 {for somewhat long \&{special} strings}
  895. @d xxx3=241 {for extremely long \&{special} strings}
  896. @d xxx4=242 {for incredibly long \&{special} strings}
  897. @d yyy=243 {for \&{numspecial} numbers}
  898. @d no_op=244 {no operation}
  899. @ The last character in a \.{GF} file is followed by `|post|'; this command
  900. introduces the postamble, which summarizes important facts that \MF\ has
  901. accumulated. The postamble has the form
  902. $$\vbox{\halign{\hbox{#\hfil}\cr
  903.   |post| |p[4]| |@!ds[4]| |@!cs[4]| |@!hppp[4]| |@!vppp[4]|
  904.    |@!min_m[4]| |@!max_m[4]| |@!min_n[4]| |@!max_n[4]|\cr
  905.   $\langle\,$character locators$\,\rangle$\cr
  906.   |post_post| |q[4]| |i[1]| 223's$[{\G}4]$\cr}}$$
  907. Here |p| is a pointer to the byte following the final |eoc| in the file
  908. (or to the byte following the preamble, if there are no characters);
  909. it can be used to locate the beginning of \\{xxx} commands
  910. that might have preceded the postamble. The |ds| and |cs| parameters
  911. @^design size@> @^check sum@>
  912. give the design size and check sum, respectively, of the font (see the
  913. description of \.{TFM} format below).
  914. Parameters |hppp| and |vppp| are the ratios of
  915. pixels per point, horizontally and vertically, expressed as |scaled| integers
  916. (i.e., multiplied by $2^{16}$); they can be used to correlate the font
  917. with specific device resolutions, magnifications, and ``at sizes.''  Then
  918. come |min_m|, |max_m|, |min_n|, and |max_n|, which bound the values that
  919. registers |m| and~|n| assume in all characters in this \.{GF} file.
  920. (These bounds need not be the best possible; |max_m| and |min_n| may, on the
  921. other hand, be tighter than the similar bounds in |boc| commands. For
  922. example, some character may have |min_n=-100| in its |boc|, but it might
  923. turn out that |n| never gets lower than |-50| in any character; then
  924. |min_n| can have any value |<=-50|. If there are no characters in the file,
  925. it's possible to have |min_m>max_m| and/or |min_n>max_n|.)
  926. @ Character locators are introduced by |char_loc| commands,
  927. which specify a character residue~|c|, character escapements (|dx,dy|),
  928. a character width~|w|, and a pointer~|p|
  929. to the beginning of that character. (If two or more characters have the
  930. same code~|c| modulo 256, only the last will be indicated; the others can be
  931. located by following backpointers. Characters whose codes differ by a
  932. multiple of 256 are assumed to share the same font metric information,
  933. hence the \.{TFM} file contains only residues of character codes modulo~256.
  934. This convention is intended for oriental languages, when there are many
  935. character shapes but few distinct widths.)
  936. @^oriental characters@>@^Chinese characters@>@^Japanese characters@>
  937. The character escapements (|dx,dy|) are the values of \MF's \&{chardx}
  938. and \&{chardy} parameters; they are in units of |scaled| pixels;
  939. i.e., |dx| is in horizontal pixel units times $2^{16}$, and |dy| is in
  940. vertical pixel units times $2^{16}$.  This is the intended amount of
  941. displacement after typesetting the character; for \.{DVI} files, |dy|
  942. should be zero, but other document file formats allow nonzero vertical
  943. escapement.
  944. The character width~|w| duplicates the information in the \.{TFM} file; it
  945. is $2^{24}$ times the ratio of the true width to the font's design size.
  946. The backpointer |p| points to the character's |boc|, or to the first of
  947. a sequence of consecutive \\{xxx} or |yyy| or |no_op| commands that
  948. immediately precede the |boc|, if such commands exist; such ``special''
  949. commands essentially belong to the characters, while the special commands
  950. after the final character belong to the postamble (i.e., to the font
  951. as a whole). This convention about |p| applies also to the backpointers
  952. in |boc| commands, even though it wasn't explained in the description
  953. of~|boc|. @^backpointers@>
  954. Pointer |p| might be |-1| if the character exists in the \.{TFM} file
  955. but not in the \.{GF} file. This unusual situation can arise in \MF\ output
  956. if the user had |proofing<0| when the character was being shipped out,
  957. but then made |proofing>=0| in order to get a \.{GF} file.
  958. @ The last part of the postamble, following the |post_post| byte that
  959. signifies the end of the character locators, contains |q|, a pointer to the
  960. |post| command that started the postamble.  An identification byte, |i|,
  961. comes next; this currently equals~131, as in the preamble.
  962. The |i| byte is followed by four or more bytes that are all equal to
  963. the decimal number 223 (i.e., @'337 in octal). \MF\ puts out four to seven of
  964. these trailing bytes, until the total length of the file is a multiple of
  965. four bytes, since this works out best on machines that pack four bytes per
  966. word; but any number of 223's is allowed, as long as there are at least four
  967. of them. In effect, 223 is a sort of signature that is added at the very end.
  968. @^Fuchs, David Raymond@>
  969. This curious way to finish off a \.{GF} file makes it feasible for
  970. \.{GF}-reading programs to find the postamble first, on most computers,
  971. even though \MF\ wants to write the postamble last. Most operating
  972. systems permit random access to individual words or bytes of a file, so
  973. the \.{GF} reader can start at the end and skip backwards over the 223's
  974. until finding the identification byte. Then it can back up four bytes, read
  975. |q|, and move to byte |q| of the file. This byte should, of course,
  976. contain the value 248 (|post|); now the postamble can be read, so the
  977. \.{GF} reader can discover all the information needed for individual characters.
  978. Unfortunately, however, standard \PASCAL\ does not include the ability to
  979. @^system dependencies@>
  980. access a random position in a file, or even to determine the length of a file.
  981. Almost all systems nowadays provide the necessary capabilities, so \.{GF}
  982. format has been designed to work most efficiently with modern operating systems.
  983. But if \.{GF} files have to be processed under the restrictions of standard
  984. \PASCAL, one can simply read them from front to back. This will
  985. be adequate for most applications. However, the postamble-first approach
  986. would facilitate a program that merges two \.{GF} files, replacing data
  987. from one that is overridden by corresponding data in the other.
  988. @* Extensions to the generic format.
  989. The \\{xxx} and \\{yyy} instructions understood by \.{GFtoDVI} will be
  990. listed now, so that we have a convenient reference to all of the special
  991. assumptions made later.
  992. Each special instruction begins with an \\{xxx} command, which consists of
  993. either a keyword by itself, or a keyword followed by a space followed
  994. by arguments. This \\{xxx} command may then be followed by \\{yyy}
  995. commands that are understood to be arguments.
  996. The keywords of special instructions that are intended to be used at
  997. many different sites should be published as widely as possible in order
  998. to minimize conflicts. The first person to establish a keyword presumably
  999. has a right to define it; \.{GFtoDVI}, as the first program
  1000. to use extended \.{GF} commands, has the opportunity of choosing any
  1001. keywords it likes, and the responsibility of choosing reasonable ones.
  1002. Since labels are expected to account for the bulk of extended commands
  1003. in typical uses of \MF, the ``null'' keyword has been set aside to
  1004. denote a labeling command.
  1005. @ Here then are the special commands of \.{GFtoDVI}.
  1006. \def\string{$\langle\,$string$\,\rangle$}
  1007. \def\okpagebreak{\vfil\penalty-100\vfilneg}
  1008. \smallskip\hang\noindent
  1009. \.{\SP n}\string\ $x$ $y$. Here \.n denotes the type of label; the
  1010. characters \.1, \.2, \.3,~\.4 respectively denote labels forced to be
  1011. at the top, left, right, or bottom of their dot, and the characters
  1012. \.5, \.6, \.7,~\.8 stand for the same possibilities but with no dot printed.
  1013. The character \.0 instructs \.{GFtoDVI} to choose one of the first four
  1014. possibilities, if there's no overlap with other labels or dots, otherwise
  1015. an ``overflow'' entry is placed at the right of the figure. The character
  1016. \./ is the same as \.0 except that overflow entries are not produced. The
  1017. label itself is the \string\ that follows. \MF\ coordinates of the
  1018. point that is to receive this label are given by arguments $x$ and~$y$,
  1019. in units of scaled pixels. (These arguments appear in \\{yyy} commands.)
  1020. (Precise definitions of the size and positioning of labels, and of the
  1021. notion of ``conflicting'' labels, will be given later.)
  1022. \smallskip\hang\noindent
  1023. \.{rule} $x_1$ $y_1$ $x_2$ $y_2$. This command draws a line from
  1024. $(x_1,y_1)$ to $(x_2,y_2)$ in \MF\ coordinates. The present implementation
  1025. does this only if the line is either horizontal or vertical, or if its
  1026. slope matches the slope of the slant font.
  1027. \smallskip\hang\noindent
  1028. \.{title\SP}\string. This command (which is output by \MF\
  1029. when it sees a ``title statement'') specifies a string that will appear
  1030. at the top of the next proofsheet to be output by \.{GFtoDVI}.
  1031. If more than one title is given, they will appear in sequence; titles
  1032. should be short enough to fit on a single line.
  1033. \smallskip\hang\noindent
  1034. \.{titlefont\SP}\string. This command, and the other font-naming
  1035. commands below, must precede the first |boc| in the \.{GF} file.
  1036. It overrides the current font used to
  1037. typeset the titles at the top of proofsheets. \.{GFtoDVI} has default
  1038. fonts that will be used if none other are specified; the ``current'' title
  1039. font is initially the default title font.
  1040. \smallskip\hang\noindent
  1041. \.{titlefontarea\SP}\string. This command overrides the current
  1042. file area (or directory name) from which \.{GFtoDVI} will try to
  1043. find metric information for the title font.
  1044. \smallskip\hang\noindent
  1045. \.{titlefontat} $s$. This command overrides the current ``at size'' that
  1046. will be used for the title font. (See the discussion of font metric files
  1047. below, for the meaning of ``at size'' versus ``design size.'') The
  1048. value of~$s$ is given in units of scaled points.
  1049. \okpagebreak
  1050. \smallskip\hang\noindent
  1051. \.{labelfont\SP}\string. This command overrides the current font
  1052. used to typeset the labels that are superimposed on proof figures.
  1053. (The label font is fairly arbitrary, but it should be dark enough to
  1054. stand out when superimposed on gray pixels, and it should contain at
  1055. least the decimal digits and the characters `\.(', `\.)', `\.=', `\.+',
  1056. `\.-', `\.,', and `\..'.)
  1057. \smallskip\hang\noindent
  1058. \.{labelfontarea\SP}\string. This command overrides the current
  1059. file area (or directory name) from which \.{GFtoDVI} will try to
  1060. find metric information for the label font.
  1061. \smallskip\hang\noindent
  1062. \.{labelfontat} $s$. This command overrides the current ``at size'' that
  1063. will be used for the label font.
  1064. \okpagebreak
  1065. \smallskip\hang\noindent
  1066. \.{grayfont\SP}\string. This command overrides the current font
  1067. used to typeset the black pixels and the dots for labels. (Gray fonts
  1068. will be explained in detail later.)
  1069. @^gray fonts@>
  1070. \smallskip\hang\noindent
  1071. \.{grayfontarea\SP}\string. This command overrides the current
  1072. file area (or directory name) from which \.{GFtoDVI} will try to
  1073. find metric information for the gray font.
  1074. \smallskip\hang\noindent
  1075. \.{grayfontat} $s$. This command overrides the current ``at size'' that
  1076. will be used for the gray font.
  1077. \okpagebreak
  1078. \smallskip\hang\noindent
  1079. \.{slantfont\SP}\string. This command overrides the current font
  1080. used to typeset rules that are neither horizontal nor vertical. (Slant
  1081. fonts will be explained in detail later.)
  1082. @^slant fonts@>
  1083. \smallskip\hang\noindent
  1084. \.{slantfontarea\SP}\string. This command overrides the current
  1085. file area (or directory name) from which \.{GFtoDVI} will try to
  1086. find metric information for the slant font.
  1087. \smallskip\hang\noindent
  1088. \.{slantfontat} $s$. This command overrides the current ``at size'' that
  1089. will be used for the slant font.
  1090. \okpagebreak
  1091. \smallskip\hang\noindent
  1092. \.{rulethickness} $t$. This command overrides the current value used
  1093. for the thickness of rules. If the current value is negative, no rule
  1094. will be drawn; if the current value is zero, the rule thickness will
  1095. be specified by a parameter of the gray font. Each \.{rule} command
  1096. uses the rule thickness that is current at the time the command appears;
  1097. hence it is possible to get different thicknesses of rules on the same
  1098. figure. The value of $t$ is given in units of scaled points (\TeX's `\.{sp}').
  1099. At the beginning of each character the current rule thickness is zero.
  1100. \smallskip\hang\noindent
  1101. \.{offset} $x$ $y$. This command overrides the current offset values
  1102. that are added to all coordinates of a character being output; $x$ and
  1103. $y$ are given as scaled \MF\ coordinates. This simply has the effect
  1104. of repositioning the figures on the pages; the title line always appears
  1105. in the same place, but the figure can be moved up, down, left, or right.
  1106. At the beginning of each character the current offsets are zero.
  1107. \smallskip\hang\noindent
  1108. \.{xoffset} $x$. This command is output by \MF\ just before shipping out
  1109. a character whose $x$~offset is nonzero. \.{GFtoDVI} adds the specified
  1110. amount to the $x$ coordinates of all dots, labels, and rules
  1111. in the following character.
  1112. \smallskip\hang\noindent
  1113. \.{yoffset} $y$. This command is output by \MF\ just before shipping out
  1114. a character whose $y$~offset is nonzero. \.{GFtoDVI} adds the specified
  1115. amount to the $y$ coordinates of all dots, labels, and rules
  1116. in the following character.
  1117. @* Font metric data.
  1118. Before we can get into the meaty details of \.{GFtoDVI}, we need to
  1119. deal with yet another esoteric binary file format, since \.{GFtoDVI}
  1120. also does elementary typesetting operations. Therefore it has to
  1121. read important information about the fonts it will be using.
  1122. The following material (again copied almost verbatim from \TeX)
  1123. describes the contents of so-called \TeX\ font metric (\.{TFM}) files.
  1124. The idea behind \.{TFM} files is that typesetting routines
  1125. need a compact way to store the relevant information about
  1126. fonts, and computer centers need a compact way to store the
  1127. relevant information about several hundred fonts. \.{TFM} files are
  1128. compact, and most of the information they contain is highly relevant,
  1129. so they provide a solution to the problem. \.{GFtoDVI} uses only
  1130. four fonts, but interesting changes in its output will occur when
  1131. those fonts are varied.
  1132. The information in a \.{TFM} file appears in a sequence of 8-bit bytes.
  1133. Since the number of bytes is always a multiple of 4, we could
  1134. also regard the file as a sequence of 32-bit words; but \TeX\ uses the
  1135. byte interpretation, and so does \.{GFtoDVI}. The individual bytes
  1136. are considered to be unsigned numbers.
  1137. @ The first 24 bytes (6 words) of a \.{TFM} file contain twelve 16-bit
  1138. integers that give the lengths of the various subsequent portions
  1139. of the file. These twelve integers are, in order:
  1140. $$\vbox{\halign{\hfil#&$\null=\null$#\hfil\cr
  1141. |@!lf|&length of the entire file, in words;\cr
  1142. |@!lh|&length of the header data, in words;\cr
  1143. |@!bc|&smallest character code in the font;\cr
  1144. |@!ec|&largest character code in the font;\cr
  1145. |@!nw|&number of words in the width table;\cr
  1146. |@!nh|&number of words in the height table;\cr
  1147. |@!nd|&number of words in the depth table;\cr
  1148. |@!ni|&number of words in the italic correction table;\cr
  1149. |@!nl|&number of words in the lig/kern table;\cr
  1150. |@!nk|&number of words in the kern table;\cr
  1151. |@!ne|&number of words in the extensible character table;\cr
  1152. |@!np|&number of font parameter words.\cr}}$$
  1153. They are all nonnegative and less than $2^{15}$. We must have |bc-1<=ec<=255|,
  1154. $$\hbox{|lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$
  1155. Note that a font may contain as many as 256 characters (if |bc=0| and |ec=255|),
  1156. and as few as 0 characters (if |bc=ec+1|). When two or more 8-bit bytes are
  1157. combined to form an integer of 16 or more bits, the bytes appear in
  1158. BigEndian order.
  1159. @^BigEndian order@>
  1160. @<Glob...@>=
  1161. @!lf,@!lh,@!bc,@!ec,@!nw,@!nh,@!nd,@!ni,@!nl,@!nk,@!ne,@!np:0..@'77777;
  1162.   {subfile sizes}
  1163. @ The rest of the \.{TFM} file may be regarded as a sequence of ten data
  1164. arrays having the informal specification
  1165. $$\def\arr$[#1]#2${\&{array} $[#1]$ \&{of} #2}
  1166. \vbox{\halign{\hfil\\{#}&$\,:\,$\arr#\hfil\cr
  1167. header&|[0..lh-1]@t\\{stuff}@>|\cr
  1168. char\_info&|[bc..ec]char_info_word|\cr
  1169. width&|[0..nw-1]fix_word|\cr
  1170. height&|[0..nh-1]fix_word|\cr
  1171. depth&|[0..nd-1]fix_word|\cr
  1172. italic&|[0..ni-1]fix_word|\cr
  1173. lig\_kern&|[0..nl-1]lig_kern_command|\cr
  1174. kern&|[0..nk-1]fix_word|\cr
  1175. exten&|[0..ne-1]extensible_recipe|\cr
  1176. param&|[1..np]fix_word|\cr}}$$
  1177. The most important data type used here is a |@!fix_word|, which is
  1178. a 32-bit representation of a binary fraction. A |fix_word| is a signed
  1179. quantity, with the two's complement of the entire word used to represent
  1180. negation. Of the 32 bits in a |fix_word|, exactly 12 are to the left of the
  1181. binary point; thus, the largest |fix_word| value is $2048-2^{-20}$, and
  1182. the smallest is $-2048$. We will see below, however, that all but two of
  1183. the |fix_word| values must lie between $-16$ and $+16$.
  1184. @ The first data array is a block of header information, which contains
  1185. general facts about the font. The header must contain at least two words,
  1186. and for \.{TFM} files to be used with Xerox printing software it must
  1187. contain at least 18 words, allocated as described below. When different
  1188. kinds of devices need to be interfaced, it may be necessary to add further
  1189. words to the header block.
  1190. \yskip\hang|header[0]| is a 32-bit check sum that \.{GFtoDVI} will copy into the
  1191. \.{DVI} output file whenever it uses the font.  Later on when the \.{DVI}
  1192. file is printed, possibly on another computer, the actual font that gets
  1193. used is supposed to have a check sum that agrees with the one in the
  1194. \.{TFM} file used by \.{GFtoDVI}. In this way, users will be warned about
  1195. potential incompatibilities. (However, if the check sum is zero in either
  1196. the font file or the \.{TFM} file, no check is made.)  The actual relation
  1197. between this check sum and the rest of the \.{TFM} file is not important;
  1198. the check sum is simply an identification number with the property that
  1199. incompatible fonts almost always have distinct check sums.
  1200. @^check sum@>
  1201. \yskip\hang|header[1]| is a |fix_word| containing the design size of the
  1202. font, in units of \TeX\ points (7227 \TeX\ points = 254 cm).  This number
  1203. must be at least 1.0; it is fairly arbitrary, but usually the design size
  1204. is 10.0 for a ``10 point'' font, i.e., a font that was designed to look
  1205. best at a 10-point size, whatever that really means. When a \TeX\ user
  1206. asks for a font `\.{at} $\delta$ \.{pt}', the effect is to override the
  1207. design size and replace it by $\delta$, and to multiply the $x$ and~$y$
  1208. coordinates of the points in the font image by a factor of $\delta$
  1209. divided by the design size.  Similarly, specific sizes can be substituted
  1210. for the design size by \.{GFtoDVI} commands like `\.{titlefontat}'.  {\sl
  1211. All other dimensions in the\/\ \.{TFM} file are |fix_word| numbers in
  1212. design-size units.} Thus, for example, the value of |param[6]|, one \.{em}
  1213. or \.{\\quad}, is often the |fix_word| value $2^{20}=1.0$, since many
  1214. fonts have a design size equal to one em.  The other dimensions must be
  1215. less than 16 design-size units in absolute value; thus, |header[1]| and
  1216. |param[1]| are the only |fix_word| entries in the whole \.{TFM} file whose
  1217. first byte might be something besides 0 or 255.  @^design size@>@^at size@>
  1218. \yskip\hang|header[2..11]|, if present, contains 40 bytes that identify
  1219. the character coding scheme. The first byte, which must be between 0 and
  1220. 39, is the number of subsequent ASCII bytes actually relevant in this
  1221. string, which is intended to specify what character-code-to-symbol
  1222. convention is present in the font.  Examples are \.{ASCII} for standard
  1223. ASCII, \.{TeX text} for fonts like \.{cmr10} and \.{cmti9}, \.{TeX math
  1224. extension} for \.{cmex10}, \.{XEROX text} for Xerox fonts, \.{GRAPHIC} for
  1225. special-purpose non-alphabetic fonts, \.{GFGRAY} for \.{GFtoDVI}'s
  1226. gray fonts, \.{GFSLANT} for \.{GFtoDVI}'s slant fonts, \.{UNSPECIFIED} for
  1227. the default case when there is no information.  Parentheses should not
  1228. appear in this name.  (Such a string is said to be in {\mc BCPL} format.)
  1229. @^coding scheme@>@^gray fonts@>@^slant fonts@>
  1230. \yskip\hang|header[12..@twhatever@>]| might also be present.
  1231. @ Next comes the |char_info| array, which contains one |char_info_word|
  1232. per character. Each |char_info_word| contains six fields packed into
  1233. four bytes as follows.
  1234. \yskip\hang first byte: |@!width_index| (8 bits)\par
  1235. \hang second byte: |@!height_index| (4 bits) times 16, plus |@!depth_index|
  1236.   (4~bits)\par
  1237. \hang third byte: |@!italic_index| (6 bits) times 4, plus |@!tag|
  1238.   (2~bits)\par
  1239. \hang fourth byte: |@!remainder| (8 bits)\par
  1240. \yskip\noindent
  1241. The actual width of a character is \\{width}|[width_index]|, in design-size
  1242. units; this is a device for compressing information, since many characters
  1243. have the same width. Since it is quite common for many characters
  1244. to have the same height, depth, or italic correction, the \.{TFM} format
  1245. imposes a limit of 16 different heights, 16 different depths, and
  1246. 64 different italic corrections.
  1247. Incidentally, the relation $\\{width}[0]=\\{height}[0]=\\{depth}[0]=
  1248. \\{italic}[0]=0$ should always hold, so that an index of zero implies a
  1249. value of zero.  The |width_index| should never be zero unless the
  1250. character does not exist in the font, since a character is valid if and
  1251. only if it lies between |bc| and |ec| and has a nonzero |width_index|.
  1252. @ The |tag| field in a |char_info_word| has four values that explain how to
  1253. interpret the |remainder| field.
  1254. \yskip\hang|tag=0| (|no_tag|) means that |remainder| is unused.\par
  1255. \hang|tag=1| (|lig_tag|) means that this character has a ligature/kerning
  1256. program starting at |lig_kern[remainder]|.\par
  1257. \hang|tag=2| (|list_tag|) means that this character is part of a chain of
  1258. characters of ascending sizes, and not the largest in the chain.  The
  1259. |remainder| field gives the character code of the next larger character.\par
  1260. \hang|tag=3| (|ext_tag|) means that this character code represents an
  1261. extensible character, i.e., a character that is built up of smaller pieces
  1262. so that it can be made arbitrarily large. The pieces are specified in
  1263. |@!exten[remainder]|.\par
  1264. @d no_tag=0 {vanilla character}
  1265. @d lig_tag=1 {character has a ligature/kerning program}
  1266. @d list_tag=2 {character has a successor in a charlist}
  1267. @d ext_tag=3 {character is extensible}
  1268. @ The |lig_kern| array contains instructions in a simple programming language
  1269. that explains what to do for special letter pairs. Each word in this array is a
  1270. |@!lig_kern_command| of four bytes.
  1271. \yskip\hang first byte: |skip_byte|, indicates that this is the final program
  1272.   step if the byte is 128 or more, otherwise the next step is obtained by
  1273.   skipping this number of intervening steps.\par
  1274. \hang second byte: |next_char|, ``if |next_char| follows the current character,
  1275.   then perform the operation and stop, otherwise continue.''\par
  1276. \hang third byte: |op_byte|, indicates a ligature step if less than~128,
  1277.   a kern step otherwise.\par
  1278. \hang fourth byte: |remainder|.\par
  1279. \yskip\noindent
  1280. In a kern step, an
  1281. additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted
  1282. between the current character and |next_char|. This amount is
  1283. often negative, so that the characters are brought closer together
  1284. by kerning; but it might be positive.
  1285. There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where
  1286. $0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is
  1287. |remainder| is inserted between the current character and |next_char|;
  1288. then the current character is deleted if $b=0$, and |next_char| is
  1289. deleted if $c=0$; then we pass over $a$~characters to reach the next
  1290. current character (which may have a ligature/kerning program of its own).
  1291. If the very first instruction of the |lig_kern| array has |skip_byte=255|,
  1292. the |next_char| byte is the so-called right boundary character of this font;
  1293. the value of |next_char| need not lie between |bc| and~|ec|.
  1294. If the very last instruction of the |lig_kern| array has |skip_byte=255|,
  1295. there is a special ligature/kerning program for a left boundary character,
  1296. beginning at location |256*op_byte+remainder|.
  1297. The interpretation is that \TeX\ puts implicit boundary characters
  1298. before and after each consecutive string of characters from the same font.
  1299. These implicit characters do not appear in the output, but they can affect
  1300. ligatures and kerning.
  1301. If the very first instruction of a character's |lig_kern| program has
  1302. |skip_byte>128|, the program actually begins in location
  1303. |256*op_byte+remainder|. This feature allows access to large |lig_kern|
  1304. arrays, because the first instruction must otherwise
  1305. appear in a location |<=255|.
  1306. Any instruction with |skip_byte>128| in the |lig_kern| array must have
  1307. |256*op_byte+remainder<nl|. If such an instruction is encountered during
  1308. normal program execution, it denotes an unconditional halt; no ligature
  1309. or kerning command is performed.
  1310. @d stop_flag=128 {value indicating `\.{STOP}' in a lig/kern program}
  1311. @d kern_flag=128 {op code for a kern step}
  1312. @ Extensible characters are specified by an |@!extensible_recipe|, which
  1313. consists of four bytes called |@!top|, |@!mid|, |@!bot|, and |@!rep| (in this
  1314. order). These bytes are the character codes of individual pieces used to
  1315. build up a large symbol.  If |top|, |mid|, or |bot| are zero, they are not
  1316. present in the built-up result. For example, an extensible vertical line is
  1317. like an extensible bracket, except that the top and bottom pieces are missing.
  1318. @ The final portion of a \.{TFM} file is the |param| array, which is another
  1319. sequence of |fix_word| values.
  1320. \yskip\hang|param[1]=@!slant| is the amount of italic slant.
  1321. For example, |slant=.25| means that when you go
  1322. up one unit, you also go .25 units to the right. The |slant| is a pure
  1323. number; it's the only |fix_word| other than the design size itself that is
  1324. not scaled by the design size.
  1325. \hang|param[2]=space| is the normal spacing between words in text.
  1326. Note that character |" "| in the font need not have anything to do with
  1327. blank spaces.
  1328. \hang|param[3]=space_stretch| is the amount of glue stretching between words.
  1329. \hang|param[4]=space_shrink| is the amount of glue shrinking between words.
  1330. \hang|param[5]=x_height| is the height of letters for which accents don't
  1331. have to be raised or lowered.
  1332. \hang|param[6]=quad| is the size of one em in the font.
  1333. \hang|param[7]=extra_space| is the amount added to |param[2]| at the
  1334. ends of sentences.
  1335. When the character coding scheme is \.{GFGRAY} or \.{GFSLANT}, the font is
  1336. supposed to contain an additional parameter called
  1337. |default_rule_thickness|. Other special parameters go with other coding
  1338. schemes.
  1339. @* Input from binary files.
  1340. We have seen that \.{GF} and \.{DVI} and \.{TFM} files are sequences of
  1341. 8-bit bytes.  The bytes appear physically in what is called a `|packed
  1342. file of 0..255|' in \PASCAL\ lingo.
  1343. Packing is system dependent, and many \PASCAL\ systems fail to implement
  1344. such files in a sensible way (at least, from the viewpoint of producing
  1345. good production software).  For example, some systems treat all
  1346. byte-oriented files as text, looking for end-of-line marks and such
  1347. things. Therefore some system-dependent code is often needed to deal with
  1348. binary files, even though most of the program in this section of
  1349. \.{GFtoDVI} is written in standard \PASCAL.
  1350. @^system dependencies@>
  1351. One common way to solve the problem is to consider files of |integer|
  1352. numbers, and to convert an integer in the range $-2^{31}\L x<2^{31}$ to
  1353. a sequence of four bytes $(a,b,c,d)$ using the following code, which
  1354. avoids the controversial integer division of negative numbers:
  1355. $$\vbox{\halign{#\hfil\cr
  1356. |if x>=0 then a:=x div @'100000000|\cr
  1357. |else begin x:=(x+@'10000000000)+@'10000000000; a:=x div @'100000000+128;|\cr
  1358. \quad|end|;\cr
  1359. |x:=x mod @'100000000;|\cr
  1360. |b:=x div @'200000; x:=x mod @'200000;|\cr
  1361. |c:=x div @'400; d:=x mod @'400;|\cr}}$$
  1362. The four bytes are then kept in a buffer and output one by one. (On 36-bit
  1363. computers, an additional division by 16 is necessary at the beginning.
  1364. Another way to separate an integer into four bytes is to use/abuse
  1365. \PASCAL's variant records, storing an integer and retrieving bytes that are
  1366. packed in the same place; {\sl caveat implementor!\/}) It is also desirable
  1367. in some cases to read a hundred or so integers at a time, maintaining a
  1368. larger buffer.
  1369. We shall stick to simple \PASCAL\ in this program, for reasons of clarity,
  1370. even if such simplicity is sometimes unrealistic.
  1371. @<Types ...@>=
  1372. @!eight_bits=0..255; {unsigned one-byte quantity}
  1373. @!byte_file=packed file of eight_bits; {files that contain binary data}
  1374. @ The program deals with three binary file variables: |gf_file| is the main
  1375. input file that we are converting into a document; |dvi_file| is the main
  1376. output file that will specify that document; and |tfm_file| is
  1377. the current font metric file from which character-width information is
  1378. being read.
  1379. @<Glob...@>=
  1380. @!gf_file:byte_file; {the character data we are reading}
  1381. @!dvi_file:byte_file; {the typesetting instructions we are writing}
  1382. @!tfm_file:byte_file; {a font metric file}
  1383. @ To prepare these files for input or output, we |reset| or |rewrite|
  1384. them. An extension of \PASCAL\ is needed, since we want to associate
  1385. it with external files whose names are specified dynamically (i.e., not
  1386. known at compile time). The following code assumes that `|reset(f,s)|' and
  1387. `|rewrite(f,s)|' do this, when |f| is a file variable and |s| is a string
  1388. variable that specifies the file name.
  1389. @^system dependencies@>
  1390. @p procedure open_gf_file; {prepares to read packed bytes in |gf_file|}
  1391. begin reset(gf_file,name_of_file);
  1392. cur_loc:=0;
  1393. procedure open_tfm_file; {prepares to read packed bytes in |tfm_file|}
  1394. begin reset(tfm_file,name_of_file);
  1395. procedure open_dvi_file; {prepares to write packed bytes in |dvi_file|}
  1396. begin rewrite(dvi_file,name_of_file);
  1397. @ If you looked carefully at the preceding code, you probably asked,
  1398. ``What are |cur_loc| and |name_of_file|?'' Good question. They are global
  1399. variables: The integer |cur_loc| tells which byte of the input file will
  1400. be read next, and the string |name_of_file| will be set to the current
  1401. file name before the file-opening procedures are called.
  1402. @<Glob...@>=
  1403. @!cur_loc:integer; {current byte number in |gf_file|}
  1404. @!name_of_file:packed array[1..file_name_size] of char; {external file name}
  1405. @ It turns out to be convenient to read four bytes at a time, when we are
  1406. inputting from \.{TFM} files. The input goes into global variables
  1407. |b0|, |b1|, |b2|, and |b3|, with |b0| getting the first byte and |b3|
  1408. the fourth.
  1409. @<Glob...@>=
  1410. @!b0,@!b1,@!b2,@!b3: eight_bits; {four bytes input at once}
  1411. @ The |read_tfm_word| procedure sets |b0| through |b3| to the next
  1412. four bytes in the current \.{TFM} file.
  1413. @^system dependencies@>
  1414. @p procedure read_tfm_word;
  1415. begin read(tfm_file,b0); read(tfm_file,b1);
  1416. read(tfm_file,b2); read(tfm_file,b3);
  1417. @ We shall use another set of simple functions to read the next byte or
  1418. bytes from |gf_file|. There are four possibilities, each of which is
  1419. treated as a separate function in order to minimize the overhead for
  1420. subroutine calls.
  1421. @^system dependencies@>
  1422. @p function get_byte:integer; {returns the next byte, unsigned}
  1423. var b:eight_bits;
  1424. begin if eof(gf_file) then get_byte:=0
  1425. else  begin read(gf_file,b); incr(cur_loc); get_byte:=b;
  1426.   end;
  1427. function get_two_bytes:integer; {returns the next two bytes, unsigned}
  1428. var a,@!b:eight_bits;
  1429. begin read(gf_file,a); read(gf_file,b);
  1430. cur_loc:=cur_loc+2;
  1431. get_two_bytes:=a*256+b;
  1432. function get_three_bytes:integer; {returns the next three bytes, unsigned}
  1433. var a,@!b,@!c:eight_bits;
  1434. begin read(gf_file,a); read(gf_file,b); read(gf_file,c);
  1435. cur_loc:=cur_loc+3;
  1436. get_three_bytes:=(a*256+b)*256+c;
  1437. function signed_quad:integer; {returns the next four bytes, signed}
  1438. var a,@!b,@!c,@!d:eight_bits;
  1439. begin read(gf_file,a); read(gf_file,b); read(gf_file,c); read(gf_file,d);
  1440. cur_loc:=cur_loc+4;
  1441. if a<128 then signed_quad:=((a*256+b)*256+c)*256+d
  1442. else signed_quad:=(((a-256)*256+b)*256+c)*256+d;
  1443. @* Reading the font information.
  1444. Now let's get down to brass tacks and consider the more substantial
  1445. routines that actually convert \.{TFM} data into a form suitable for
  1446. computation.  The routines in this part of the program have been borrowed
  1447. from \TeX, with slight changes, since \.{GFtoDVI} has to do some of the
  1448. things that \TeX\ does.
  1449. The \.{TFM} data is stored in a large array called
  1450. |font_info|. Each item of |font_info| is a |memory_word|; the |fix_word|
  1451. data gets converted into |scaled| entries, while everything else goes into
  1452. words of type |four_quarters|. (These data structures are special cases of
  1453. the more general memory words of \TeX. On some machines it is necessary to
  1454. define |min_quarterword=-128| and |max_quarterword=127| in order to pack
  1455. four quarterwords into a single word.)
  1456. @^system dependencies@>
  1457. @d min_quarterword=0 {change this to allow efficient packing, if necessary}
  1458. @d max_quarterword=255 {ditto}
  1459. @d qi(#)==#+min_quarterword
  1460.   {to put an |eight_bits| item into a quarterword}
  1461. @d qo(#)==#-min_quarterword
  1462.   {to take an |eight_bits| item out of a quarterword}
  1463. @d title_font=1
  1464. @d label_font=2
  1465. @d gray_font=3
  1466. @d slant_font=4
  1467. @d logo_font=5
  1468. @d non_char==qi(256)
  1469. @d non_address==font_mem_size
  1470. @<Types ...@>=
  1471. @!font_index = 0..font_mem_size;
  1472. @!quarterword = min_quarterword..max_quarterword; {1/4 of a word}
  1473. @!four_quarters = packed record@;@/
  1474.   @!b0:quarterword;
  1475.   @!b1:quarterword;
  1476.   @!b2:quarterword;
  1477.   @!b3:quarterword;
  1478.   end;
  1479. @!memory_word = record@;@/
  1480.   case boolean of
  1481.   true: (@!sc:scaled);
  1482.   false: (@!qqqq:four_quarters);
  1483.   end;
  1484. @!internal_font_number=title_font..logo_font;
  1485. @ Besides |font_info|, there are also a number of index arrays that point
  1486. into it, so that we can locate width and height information, etc.  For
  1487. example, the |char_info| data for character |c| in font |f| will be in
  1488. |font_info[char_base[f]+c].qqqq|; and if |w| is the |width_index| part of
  1489. this word (the |b0| field), the width of the character is
  1490. |font_info[width_base[f]+w].sc|. (These formulas assume that
  1491. |min_quarterword| has already been added to |w|, but not to |c|.)
  1492. @<Glob...@>=
  1493. @!font_info:array[font_index] of memory_word; {the font metric data}
  1494. @!fmem_ptr:font_index; {first unused word of |font_info|}
  1495. @!font_check:array[internal_font_number] of four_quarters; {check sum}
  1496. @!font_size:array[internal_font_number] of scaled; {``at'' size}
  1497. @!font_dsize:array[internal_font_number] of scaled; {``design'' size}
  1498. @!font_bc:array[internal_font_number] of eight_bits;
  1499.   {beginning (smallest) character code}
  1500. @!font_ec:array[internal_font_number] of eight_bits;
  1501.   {ending (largest) character code}
  1502. @!char_base:array[internal_font_number] of integer;
  1503.   {base addresses for |char_info|}
  1504. @!width_base:array[internal_font_number] of integer;
  1505.   {base addresses for widths}
  1506. @!height_base:array[internal_font_number] of integer;
  1507.   {base addresses for heights}
  1508. @!depth_base:array[internal_font_number] of integer;
  1509.   {base addresses for depths}
  1510. @!italic_base:array[internal_font_number] of integer;
  1511.   {base addresses for italic corrections}
  1512. @!lig_kern_base:array[internal_font_number] of integer;
  1513.   {base addresses for ligature/kerning programs}
  1514. @!kern_base:array[internal_font_number] of integer;
  1515.   {base addresses for kerns}
  1516. @!exten_base:array[internal_font_number] of integer;
  1517.   {base addresses for extensible recipes}
  1518. @!param_base:array[internal_font_number] of integer;
  1519.   {base addresses for font parameters}
  1520. @!bchar_label:array[internal_font_number] of font_index;
  1521.   {start of |lig_kern| program for left boundary character,
  1522.   |non_address| if there is none}
  1523. @!font_bchar:array[internal_font_number] of min_quarterword..non_char;
  1524.   {right boundary character, |non_char| if there is none}
  1525. @ @<Set init...@>=
  1526. fmem_ptr:=0;
  1527. @ Of course we want to define macros that suppress the detail of how font
  1528. information is actually packed, so that we don't have to write things like
  1529. $$\hbox{|font_info[width_base[f]+font_info[char_base[f]+c].qqqq.b0].sc|}$$
  1530. too often. The \.{WEB} definitions here make |char_info(f)(c)| the
  1531. |four_quarters| word of font information corresponding to character
  1532. |c| of font |f|. If |q| is such a word, |char_width(f)(q)| will be
  1533. the character's width; hence the long formula above is at least
  1534. abbreviated to
  1535. $$\hbox{|char_width(f)(char_info(f)(c))|.}$$
  1536. In practice we will try to fetch |q| first and look at several of its
  1537. fields at the same time.
  1538. The italic correction of a character will be denoted by
  1539. |char_italic(f)(q)|, so it is analogous to |char_width|.  But we will get
  1540. at the height and depth in a slightly different way, since we usually want
  1541. to compute both height and depth if we want either one.  The value of
  1542. |height_depth(q)| will be the 8-bit quantity
  1543. $$b=|height_index|\times16+|depth_index|,$$ and if |b| is such a byte we
  1544. will write |char_height(f)(b)| and |char_depth(f)(b)| for the height and
  1545. depth of the character |c| for which |q=char_info(f)(c)|. Got that?
  1546. The tag field will be called |char_tag(q)|; and the remainder byte will be
  1547. called |rem_byte(q)|.
  1548. @d char_info_end(#)==#].qqqq
  1549. @d char_info(#)==font_info[char_base[#]+char_info_end
  1550. @d char_width_end(#)==#.b0].sc
  1551. @d char_width(#)==font_info[width_base[#]+char_width_end
  1552. @d char_exists(#)==(#.b0>min_quarterword)
  1553. @d char_italic_end(#)==(qo(#.b2)) div 4].sc
  1554. @d char_italic(#)==font_info[italic_base[#]+char_italic_end
  1555. @d height_depth(#)==qo(#.b1)
  1556. @d char_height_end(#)==(#) div 16].sc
  1557. @d char_height(#)==font_info[height_base[#]+char_height_end
  1558. @d char_depth_end(#)==# mod 16].sc
  1559. @d char_depth(#)==font_info[depth_base[#]+char_depth_end
  1560. @d char_tag(#)==((qo(#.b2)) mod 4)
  1561. @d skip_byte(#)==qo(#.b0)
  1562. @d next_char(#)==#.b1
  1563. @d op_byte(#)==qo(#.b2)
  1564. @d rem_byte(#)==#.b3
  1565. @ Here are some macros that help process ligatures and kerns.
  1566. We write |char_kern(f)(j)| to find the amount of kerning specified by
  1567. kerning command~|j| in font~|f|.
  1568. @d lig_kern_start(#)==lig_kern_base[#]+rem_byte {beginning of lig/kern program}
  1569. @d lig_kern_restart_end(#)==256*(op_byte(#))+rem_byte(#)
  1570. @d lig_kern_restart(#)==lig_kern_base[#]+lig_kern_restart_end
  1571. @d char_kern_end(#)==256*(op_byte(#)-128)+rem_byte(#)].sc
  1572. @d char_kern(#)==font_info[kern_base[#]+char_kern_end
  1573. @ Font parameters are referred to as |slant(f)|, |space(f)|, etc.
  1574. @d param_end(#)==param_base[#]].sc
  1575. @d param(#)==font_info[#+param_end
  1576. @d slant==param(1) {slant to the right, per unit distance upward}
  1577. @d space==param(2) {normal space between words}
  1578. @d x_height==param(5) {one ex}
  1579. @d default_rule_thickness==param(8) {thickness of rules}
  1580. @ Here is the subroutine that inputs the information on |tfm_file|, assuming
  1581. that the file has just been reset. Parameter~|f| tells which metric file is
  1582. being read (either |title_font| or |label_font| or |gray_font| or |slant_font|
  1583. or |logo_font|); parameter~|s| is the ``at'' size, which will be
  1584. substituted for the design size if it is positive.
  1585. This routine does only limited checking of the validity of the file,
  1586. because another program (\.{TFtoPL}) is available to diagnose errors in
  1587. the rare case that something is amiss.
  1588. @d bad_tfm=11 {label for |read_font_info|}
  1589. @d abend==goto bad_tfm {do this when the \.{TFM} data is wrong}
  1590. @p procedure read_font_info(@!f:integer;@!s:scaled); {input a \.{TFM} file}
  1591. label done,bad_tfm;
  1592. var k:font_index; {index into |font_info|}
  1593. @!lf,@!lh,@!bc,@!ec,@!nw,@!nh,@!nd,@!ni,@!nl,@!nk,@!ne,@!np:0..65535;
  1594.   {sizes of subfiles}
  1595. @!bch_label:integer; {left boundary label for ligatures}
  1596. @!bchar:0..256; {right boundary character for ligatures}
  1597. @!qw:four_quarters;@!sw:scaled; {accumulators}
  1598. @!z:scaled; {the design size or the ``at'' size}
  1599. @!alpha:integer;@!beta:1..16;
  1600.   {auxiliary quantities used in fixed-point multiplication}
  1601. begin @<Read and check the font data; |abend| if the \.{TFM} file is
  1602.   malformed; otherwise |goto done|@>;
  1603. bad_tfm: print_nl('Bad TFM file for');
  1604. @.Bad TFM file...@>
  1605. case f of
  1606. title_font:abort('titles!');
  1607. label_font:abort('labels!');
  1608. gray_font:abort('pixels!');
  1609. slant_font:abort('slants!');
  1610. logo_font:abort('METAFONT logo!');
  1611. end; {there are no other cases}
  1612. done: {it might be good to close |tfm_file| now}
  1613. @ @<Read and check...@>=
  1614. @<Read the {\.{TFM}} size fields@>;
  1615. @<Use size fields to allocate font information@>;
  1616. @<Read the {\.{TFM}} header@>;
  1617. @<Read character data@>;
  1618. @<Read box dimensions@>;
  1619. @<Read ligature/kern program@>;
  1620. @<Read extensible character recipes@>;
  1621. @<Read font parameters@>;
  1622. @<Make final adjustments and |goto done|@>
  1623. @ @d read_two_halves_end(#)==#:=b2*256+b3
  1624. @d read_two_halves(#)==read_tfm_word; #:=b0*256+b1; read_two_halves_end
  1625. @<Read the {\.{TFM}} size fields@>=
  1626. begin read_two_halves(lf)(lh);
  1627. read_two_halves(bc)(ec);
  1628. if (bc>ec+1)or(ec>255) then abend;
  1629. if bc>255 then {|bc=256| and |ec=255|}
  1630.   begin bc:=1; ec:=0;
  1631.   end;
  1632. read_two_halves(nw)(nh);
  1633. read_two_halves(nd)(ni);
  1634. read_two_halves(nl)(nk);
  1635. read_two_halves(ne)(np);
  1636. if lf<>6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np then abend;
  1637. @ The preliminary settings of the index variables |width_base|,
  1638. |lig_kern_base|, |kern_base|, and |exten_base| will be corrected later by
  1639. subtracting |min_quarterword| from them; and we will subtract 1 from
  1640. |param_base| too. It's best to forget about such anomalies until later.
  1641. @<Use size fields to allocate font information@>=
  1642. lf:=lf-6-lh; {|lf| words should be loaded into |font_info|}
  1643. if np<8 then lf:=lf+8-np; {at least eight parameters will appear}
  1644. if fmem_ptr+lf>font_mem_size then abort('No room for TFM file!');
  1645. @.No room for TFM file@>
  1646. char_base[f]:=fmem_ptr-bc;
  1647. width_base[f]:=char_base[f]+ec+1;
  1648. height_base[f]:=width_base[f]+nw;
  1649. depth_base[f]:=height_base[f]+nh;
  1650. italic_base[f]:=depth_base[f]+nd;
  1651. lig_kern_base[f]:=italic_base[f]+ni;
  1652. kern_base[f]:=lig_kern_base[f]+nl;
  1653. exten_base[f]:=kern_base[f]+nk;
  1654. param_base[f]:=exten_base[f]+ne
  1655. @ Only the first two words of the header are needed by \.{GFtoDVI}.
  1656. @d store_four_quarters(#)==
  1657.   begin read_tfm_word;
  1658.   qw.b0:=qi(b0); qw.b1:=qi(b1); qw.b2:=qi(b2); qw.b3:=qi(b3);
  1659.   #:=qw;
  1660.   end
  1661. @<Read the {\.{TFM}} header@>=
  1662. begin if lh<2 then abend;
  1663. store_four_quarters(font_check[f]);
  1664. read_tfm_word;
  1665. if b0>127 then abend; {design size must be positive}
  1666. z:=((b0*256+b1)*256+b2)*16+(b3 div 16);
  1667. if z<unity then abend;
  1668. while lh>2 do
  1669.   begin read_tfm_word; decr(lh); {ignore the rest of the header}
  1670.   end;
  1671. font_dsize[f]:=z;
  1672. if s>0 then z:=s;
  1673. font_size[f]:=z;
  1674. @ @<Read character data@>=
  1675. for k:=fmem_ptr to width_base[f]-1 do
  1676.   begin store_four_quarters(font_info[k].qqqq);
  1677.   if (b0>=nw)or(b1 div @'20>=nh)or(b1 mod @'20>=nd)or
  1678.     (b2 div 4>=ni) then abend;
  1679.   case b2 mod 4 of
  1680.   lig_tag: if b3>=nl then abend;
  1681.   ext_tag: if b3>=ne then abend;
  1682.   no_tag,list_tag: do_nothing;
  1683.   end; {there are no other cases}
  1684.   end
  1685. @ A |fix_word| whose four bytes are $(b0,b1,b2,b3)$ from left to right
  1686. represents the number
  1687. $$x=\left\{\vcenter{\halign{$#$,\hfil\qquad&if $#$\hfil\cr
  1688. b_1\cdot2^{-4}+b_2\cdot2^{-12}+b_3\cdot2^{-20}&b_0=0;\cr
  1689. -16+b_1\cdot2^{-4}+b_2\cdot2^{-12}+b_3\cdot2^{-20}&b_0=255.\cr}}\right.$$
  1690. (No other choices of |b0| are allowed, since the magnitude of a number in
  1691. design-size units must be less than 16.)  We want to multiply this
  1692. quantity by the integer~|z|, which is known to be less than $2^{27}$. Let
  1693. $\alpha=16z$.  If $|z|<2^{23}$, the individual multiplications $b\cdot z$,
  1694. $c\cdot z$, $d\cdot z$ cannot overflow; otherwise we will divide |z| by 2,
  1695. 4, 8, or 16, to obtain a multiplier less than $2^{23}$, and we can
  1696. compensate for this later. If |z| has thereby been replaced by
  1697. $|z|^\prime=|z|/2^e$, let $\beta=2^{4-e}$; we shall compute
  1698. $$\lfloor(b_1+b_2\cdot2^{-8}+b_3\cdot2^{-16})\,z^\prime/\beta\rfloor$$
  1699. if $a=0$, or the same quantity minus $\alpha$ if $a=255$.
  1700. @d store_scaled(#)==begin read_tfm_word;
  1701.   sw:=(((((b3*z)div@'400)+(b2*z))div@'400)+(b1*z))div beta;
  1702.   if b0=0 then #:=sw@+else if b0=255 then #:=sw-alpha@+else abend;
  1703.   end
  1704. @<Read box dimensions@>=
  1705. begin @<Replace |z| by $|z|^\prime$ and compute $\alpha,\beta$@>;
  1706. for k:=width_base[f] to lig_kern_base[f]-1 do
  1707.   store_scaled(font_info[k].sc);
  1708. if font_info[width_base[f]].sc<>0 then abend; {\\{width}[0] must be zero}
  1709. if font_info[height_base[f]].sc<>0 then abend; {\\{height}[0] must be zero}
  1710. if font_info[depth_base[f]].sc<>0 then abend; {\\{depth}[0] must be zero}
  1711. if font_info[italic_base[f]].sc<>0 then abend; {\\{italic}[0] must be zero}
  1712. @ @<Replace |z|...@>=
  1713. begin alpha:=16*z; beta:=16;
  1714. while z>=@'40000000 do
  1715.   begin z:=z div 2; beta:=beta div 2;
  1716.   end;
  1717. @ @d check_byte_range(#)==begin if (#<bc)or(#>ec) then abend@+end
  1718. @<Read ligature/kern program@>=
  1719. begin bch_label:=@'77777; bchar:=256;
  1720. if nl>0 then
  1721.   begin for k:=lig_kern_base[f] to kern_base[f]-1 do
  1722.     begin store_four_quarters(font_info[k].qqqq);
  1723.     if b0>stop_flag then
  1724.       begin if 256*b2+b3>=nl then abend;
  1725.       if b0=255 then if k=lig_kern_base[f] then bchar:=b1;
  1726.       end
  1727.     else begin if b1<>bchar then check_byte_range(b1);
  1728.       if b2<kern_flag then check_byte_range(b3)
  1729.       else if 256*(b2-128)+b3>=nk then abend;
  1730.       end;
  1731.     end;
  1732.   if b0=255 then bch_label:=256*b2+b3;
  1733.   end;
  1734. for k:=kern_base[f] to exten_base[f]-1 do
  1735.   store_scaled(font_info[k].sc);
  1736. @ @<Read extensible character recipes@>=
  1737. for k:=exten_base[f] to param_base[f]-1 do
  1738.   begin store_four_quarters(font_info[k].qqqq);
  1739.   if b0<>0 then check_byte_range(b0);
  1740.   if b1<>0 then check_byte_range(b1);
  1741.   if b2<>0 then check_byte_range(b2);
  1742.   check_byte_range(b3);
  1743.   end
  1744. @ @<Read font parameters@>=
  1745. begin for k:=1 to np do
  1746.   if k=1 then {the |slant| parameter is a pure number}
  1747.     begin read_tfm_word;
  1748.     if b0>127 then sw:=b0-256@+else sw:=b0;
  1749.     sw:=sw*@'400+b1; sw:=sw*@'400+b2;
  1750.     font_info[param_base[f]].sc:=(sw*@'20)+(b3 div@'20);
  1751.     end
  1752.   else store_scaled(font_info[param_base[f]+k-1].sc);
  1753. for k:=np+1 to 8 do font_info[param_base[f]+k-1].sc:=0;
  1754. @ Now to wrap it up, we have checked all the necessary things about the \.{TFM}
  1755. file, and all we need to do is put the finishing touches on the data for
  1756. the new font.
  1757. @d adjust(#)==#[f]:=qo(#[f])
  1758.   {correct for the excess |min_quarterword| that was added}
  1759. @<Make final adjustments...@>=
  1760. font_bc[f]:=bc; font_ec[f]:=ec;
  1761. if bch_label<nl then bchar_label[f]:=bch_label+lig_kern_base[f]
  1762. else bchar_label[f]:=non_address;
  1763. font_bchar[f]:=qi(bchar);
  1764. adjust(width_base); adjust(lig_kern_base);
  1765. adjust(kern_base); adjust(exten_base);
  1766. decr(param_base[f]);
  1767. fmem_ptr:=fmem_ptr+lf; goto done
  1768. @* The string pool.
  1769. \.{GFtoDVI} remembers strings by putting them into an array called
  1770. |str_pool|. The |str_start| array tells where each string starts in the pool.
  1771. @<Types ...@>=
  1772. @!pool_pointer = 0..pool_size; {for variables that point into |str_pool|}
  1773. @!str_number = 0..max_strings; {for variables that point into |str_start|}
  1774. @ As new strings enter, we keep track of the storage currently used, by
  1775. means of two global variables called |pool_ptr| and |str_ptr|. These are
  1776. periodically reset to their initial values when we move from one character
  1777. to another, because most strings are of only temporary interest.
  1778. @<Glob...@>=
  1779. @!str_pool:packed array[pool_pointer] of ASCII_code; {the characters}
  1780. @!str_start : array[str_number] of pool_pointer; {the starting pointers}
  1781. @!pool_ptr : pool_pointer; {first unused position in |str_pool|}
  1782. @!str_ptr : str_number; {start of the current string being created}
  1783. @!init_str_ptr:str_number; {|str_ptr| setting when a new character starts}
  1784. @ Several of the elementary string operations are performed using \.{WEB}
  1785. macros instead of using \PASCAL\ procedures, because many of the
  1786. operations are done quite frequently and we want to avoid the
  1787. overhead of procedure calls. For example, here is
  1788. a simple macro that computes the length of a string.
  1789. @.WEB@>
  1790. @d length(#)==(str_start[#+1]-str_start[#]) {the number of characters
  1791.   in string number \#}
  1792. @ Strings are created by appending character codes to |str_pool|.
  1793. The macro called |append_char|, defined here, does not check to see if the
  1794. value of |pool_ptr| has gotten too high; that test is supposed to be
  1795. made before |append_char| is used.
  1796. To test if there is room to append |l| more characters to |str_pool|,
  1797. we shall write |str_room(l)|, which aborts \.{GFtoDVI} and gives an
  1798. apologetic error message if there isn't enough room.
  1799. @d append_char(#) == {put |ASCII_code| \# at the end of |str_pool|}
  1800. begin str_pool[pool_ptr]:=#; incr(pool_ptr);
  1801. @d str_room(#) == {make sure that the pool hasn't overflowed}
  1802.   begin if pool_ptr+# > pool_size then
  1803.     abort('Too many strings!');
  1804. @.Too many strings@>
  1805.   end
  1806. @ Once a sequence of characters has been appended to |str_pool|, it
  1807. officially becomes a string when the function |make_string| is called.
  1808. This function returns the identification number of the new string as its
  1809. value.
  1810. @p function make_string : str_number; {current string enters the pool}
  1811. begin if str_ptr=max_strings then
  1812.   abort('Too many labels!');
  1813. @.Too many labels@>
  1814. incr(str_ptr); str_start[str_ptr]:=pool_ptr;
  1815. make_string:=str_ptr-1;
  1816. @ The first strings in the string pool are the keywords that \.{GFtoDVI}
  1817. recognizes in the \\{xxx} commands of a \.{GF} file. They are entered
  1818. into |str_pool| by means of a tedious bunch of assignment statements,
  1819. together with calls on the |first_string| subroutine.
  1820. @d init_str0(#)==first_string(#)
  1821. @d init_str1(#)==buffer[1]:=#; init_str0
  1822. @d init_str2(#)==buffer[2]:=#; init_str1
  1823. @d init_str3(#)==buffer[3]:=#; init_str2
  1824. @d init_str4(#)==buffer[4]:=#; init_str3
  1825. @d init_str5(#)==buffer[5]:=#; init_str4
  1826. @d init_str6(#)==buffer[6]:=#; init_str5
  1827. @d init_str7(#)==buffer[7]:=#; init_str6
  1828. @d init_str8(#)==buffer[8]:=#; init_str7
  1829. @d init_str9(#)==buffer[9]:=#; init_str8
  1830. @d init_str10(#)==buffer[10]:=#; init_str9
  1831. @d init_str11(#)==buffer[11]:=#; init_str10
  1832. @d init_str12(#)==buffer[12]:=#; init_str11
  1833. @d init_str13(#)==buffer[13]:=#; init_str12
  1834. @d longest_keyword=13
  1835. @p procedure first_string(@!c:integer);
  1836. begin if str_ptr<>c then abort('?'); {internal consistency check}
  1837. @.?@>
  1838. while l>0 do
  1839.   begin append_char(buffer[l]); decr(l);
  1840.   end;
  1841. incr(str_ptr); str_start[str_ptr]:=pool_ptr;
  1842. @ @<Glob...@>=
  1843. @!l:integer; {length of string being made by |first_string|}
  1844. @ Here are the tedious assignments just promised.
  1845. String number 0 is the empty string.
  1846. @d null_string=0 {the empty keyword}
  1847. @d area_code=4 {add to font code for the `\.{area}' keywords}
  1848. @d at_code=8 {add to font code for the `\.{at}' keywords}
  1849. @d rule_code=13 {code for the keyword `\.{rule}'}
  1850. @d title_code=14 {code for the keyword `\.{title}'}
  1851. @d rule_thickness_code=15 {code for the keyword `\.{rulethickness}'}
  1852. @d offset_code=16 {code for the keyword `\.{offset}'}
  1853. @d x_offset_code=17 {code for the keyword `\.{xoffset}'}
  1854. @d y_offset_code=18 {code for the keyword `\.{yoffset}'}
  1855. @d max_keyword=18 {largest keyword code number}
  1856. @<Initialize the strings@>=
  1857. str_ptr:=0; pool_ptr:=0; str_start[0]:=0;@/
  1858. l:=0; init_str0(null_string);@/
  1859. l:=9; init_str9("t")("i")("t")("l")("e")("f")("o")("n")("t")(title_font);@/
  1860. l:=9; init_str9("l")("a")("b")("e")("l")("f")("o")("n")("t")(label_font);@/
  1861. l:=8; init_str8("g")("r")("a")("y")("f")("o")("n")("t")(gray_font);@/
  1862. l:=9; init_str9("s")("l")("a")("n")("t")("f")("o")("n")("t")(slant_font);@/
  1863. l:=13; init_str13("t")("i")("t")("l")("e")
  1864.   ("f")("o")("n")("t")("a")("r")("e")("a")(title_font+area_code);@/
  1865. l:=13; init_str13("l")("a")("b")("e")("l")
  1866.   ("f")("o")("n")("t")("a")("r")("e")("a")(label_font+area_code);@/
  1867. l:=12; init_str12("g")("r")("a")("y")
  1868.   ("f")("o")("n")("t")("a")("r")("e")("a")(gray_font+area_code);@/
  1869. l:=13; init_str13("s")("l")("a")("n")("t")
  1870.   ("f")("o")("n")("t")("a")("r")("e")("a")(slant_font+area_code);@/
  1871. l:=11; init_str11("t")("i")("t")("l")("e")
  1872.   ("f")("o")("n")("t")("a")("t")(title_font+at_code);@/
  1873. l:=11; init_str11("l")("a")("b")("e")("l")
  1874.   ("f")("o")("n")("t")("a")("t")(label_font+at_code);@/
  1875. l:=10; init_str10("g")("r")("a")("y")
  1876.   ("f")("o")("n")("t")("a")("t")(gray_font+at_code);@/
  1877. l:=11; init_str11("s")("l")("a")("n")("t")
  1878.   ("f")("o")("n")("t")("a")("t")(slant_font+at_code);@/
  1879. l:=4; init_str4("r")("u")("l")("e")(rule_code);@/
  1880. l:=5; init_str5("t")("i")("t")("l")("e")(title_code);@/
  1881. l:=13; init_str13("r")("u")("l")("e")
  1882.   ("t")("h")("i")("c")("k")("n")("e")("s")("s")(rule_thickness_code);@/
  1883. l:=6; init_str6("o")("f")("f")("s")("e")("t")(offset_code);@/
  1884. l:=7; init_str7("x")("o")("f")("f")("s")("e")("t")(x_offset_code);@/
  1885. l:=7; init_str7("y")("o")("f")("f")("s")("e")("t")(y_offset_code);@/
  1886. @ We will also find it useful to have the following strings. (The names of
  1887. default fonts will presumably be different at different sites.)
  1888. @^system dependencies@>
  1889. @^default fonts@>
  1890. @d gf_ext=max_keyword+1 {string number for `\.{.gf}'}
  1891. @d dvi_ext=max_keyword+2 {string number for `\.{.dvi}'}
  1892. @d tfm_ext=max_keyword+3 {string number for `\.{.tfm}'}
  1893. @d page_header=max_keyword+4 {string number for `\.{\ \ Page\ }'}
  1894. @d char_header=max_keyword+5 {string number for `\.{\ \ Character\ }'}
  1895. @d ext_header=max_keyword+6 {string number for `\.{\ \ Ext\ }'}
  1896. @d left_quotes=max_keyword+7 {string number for `\.{\ \ ``}'}
  1897. @d right_quotes=max_keyword+8 {string number for `\.{''}'}
  1898. @d equals_sign=max_keyword+9 {string number for `\.{ = }'}
  1899. @d plus_sign=max_keyword+10 {string number for `\.{ + (}'}
  1900. @d default_title_font=max_keyword+11
  1901.   {string number for the default |title_font|}
  1902. @d default_label_font=max_keyword+12
  1903.   {string number for the default |label_font|}
  1904. @d default_gray_font=max_keyword+13 {string number for the default |gray_font|}
  1905. @d logo_font_name=max_keyword+14 {string number for the font with \MF\ logo}
  1906. @d small_logo=max_keyword+15 {string number for `\.{METAFONT}'}
  1907. @d home_font_area=max_keyword+16 {string number for system-dependent font area}
  1908. @<Initialize the strings@>=
  1909. l:=3; init_str3(".")("g")("f")(gf_ext);@/
  1910. l:=4; init_str4(".")("d")("v")("i")(dvi_ext);@/
  1911. l:=4; init_str4(".")("t")("f")("m")(tfm_ext);@/
  1912. l:=7; init_str7(" ")(" ")("P")("a")("g")("e")(" ")(page_header);@/
  1913. l:=12; init_str12(" ")(" ")("C")("h")("a")("r")("a")("c")("t")("e")("r")(" ")
  1914.   (char_header);@/
  1915. l:=6; init_str6(" ")(" ")("E")("x")("t")(" ")(ext_header);@/
  1916. l:=4; init_str4(" ")(" ")("`")("`")(left_quotes);@/
  1917. l:=2; init_str2("'")("'")(right_quotes);@/
  1918. l:=3; init_str3(" ")("=")(" ")(equals_sign);@/
  1919. l:=4; init_str4(" ")("+")(" ")("(")(plus_sign);@/
  1920. l:=4; init_str4("c")("m")("r")("8")(default_title_font);@/
  1921. l:=6; init_str6("c")("m")("t")("t")("1")("0")(default_label_font);@/
  1922. l:=4; init_str4("g")("r")("a")("y")(default_gray_font);@/
  1923. l:=5; init_str5("l")("o")("g")("o")("8")(logo_font_name);@/
  1924. l:=8; init_str8("M")("E")("T")("A")("F")("O")("N")("T")(small_logo);
  1925. @ If an \\{xxx} command has just been encountered in the \.{GF} file,
  1926. the following procedure interprets its keyword. More precisely, we assume
  1927. that |cur_gf| contains an op-code byte just read from the \.{GF} file,
  1928. where |xxx1<=cur_gf<=no_op|. The |interpret_xxx| procedure will read the
  1929. rest of the command, in the following way:
  1930. \smallskip
  1931. \item{1)} If |cur_gf| is |no_op| or |yyy|, or if it's an \\{xxx} command with
  1932. an unknown keyword, the bytes are simply read and ignored, and the
  1933. value |no_operation| is returned.
  1934. \item{2)} If |cur_gf| is an \\{xxx} command (either |xxx1| or $\cdots$
  1935. or |xxx4|), and if the associated string matches a keyword exactly,
  1936. the string number of that keyword is returned (e.g., |rule_thickness_code|).
  1937. \item{3)} If |cur_gf| is an \\{xxx} command whose string begins with
  1938. keyword and space, the string number of that keyword is returned, and
  1939. the remainder of the string is put into the string pool (where it will be
  1940. string number |cur_string|. Exception: If the keyword is |null_string|,
  1941. the character immediately following the blank space is put into the
  1942. global variable |label_type|, and the remaining characters go into the
  1943. string pool.
  1944. \smallskip\noindent
  1945. In all cases, |cur_gf| will then be reset to the op-code byte that
  1946. immediately follows the original command.
  1947. @d no_operation=max_keyword+1
  1948. @<Types ...@>=
  1949. @!keyword_code=null_string..no_operation;
  1950. @ @<Glob...@>=
  1951. @!cur_gf:eight_bits; {the byte most recently read from |gf_file|}
  1952. @!cur_string:str_number; {the string following a keyword and space}
  1953. @!label_type:eight_bits; {the character following a null keyword and space}
  1954. @ We will be using this procedure when reading the \.{GF} file just
  1955. after the preamble and just after |eoc| commands.
  1956. @p function interpret_xxx:keyword_code;
  1957. label done,done1,not_found;
  1958. var @!k:integer; {number of bytes in an \\{xxx} command}
  1959. @!j:integer; {number of bytes read so far}
  1960. @!l:0..longest_keyword; {length of keyword to check}
  1961. @!m:keyword_code; {runs through the list of known keywords}
  1962. @!n1:0..longest_keyword; {buffered character being checked}
  1963. @!n2:pool_pointer; {pool character being checked}
  1964. @!c:keyword_code; {the result to return}
  1965. begin c:=no_operation; cur_string:=null_string;
  1966. case cur_gf of
  1967. no_op:goto done;
  1968. yyy:begin k:=signed_quad; goto done;
  1969.   end;
  1970. xxx1:k:=get_byte;
  1971. xxx2:k:=get_two_bytes;
  1972. xxx3:k:=get_three_bytes;
  1973. xxx4:k:=signed_quad;
  1974. end; {there are no other cases}
  1975. @<Read the next |k| characters of the \.{GF} file;
  1976.   change |c| and |goto done| if a keyword is recognized@>;
  1977. done: cur_gf:=get_byte; interpret_xxx:=c;
  1978. @ @<Read the next |k|...@>=
  1979. j:=0;@+if k<2 then goto not_found;
  1980. loop@+  begin l:=j;
  1981.   if j=k then goto done1;
  1982.   if j=longest_keyword then goto not_found;
  1983.   incr(j); buffer[j]:=get_byte;
  1984.   if buffer[j]=" " then goto done1;
  1985.   end;
  1986. done1:@<If the keyword in |buffer[1..l]| is known, change |c| and |goto done|@>;
  1987. not_found: while j<k do
  1988.   begin incr(j); cur_gf:=get_byte;
  1989.   end
  1990. @ @<If the keyword...@>=
  1991. for m:=null_string to max_keyword do if length(m)=l then
  1992.   begin n1:=0; n2:=str_start[m];
  1993.   while (n1<l)and(buffer[n1+1]=str_pool[n2]) do
  1994.     begin incr(n1); incr(n2);
  1995.     end;
  1996.   if n1=l then
  1997.     begin c:=m;
  1998.     if m=null_string then
  1999.       begin incr(j); label_type:=get_byte;
  2000.       end;
  2001.     str_room(k-j);
  2002.     while j<k do
  2003.       begin incr(j); append_char(get_byte);
  2004.       end;
  2005.     cur_string:=make_string; goto done;
  2006.     end;
  2007.   end
  2008. @ When an \\{xxx} command takes a numeric argument, |get_yyy| reads
  2009. that argument and puts the following byte into |cur_gf|.
  2010. @p function get_yyy:scaled;
  2011. var @!v:scaled; {value just read}
  2012. begin if cur_gf<>yyy then get_yyy:=0
  2013. else  begin v:=signed_quad; cur_gf:=get_byte; get_yyy:=v;
  2014.   end;
  2015. @ A simpler method is used for special commands between |boc| and |eoc|,
  2016. since \.{GFtoDVI} doesn't even look at them.
  2017. @p procedure skip_nop;
  2018. label done;
  2019. var @!k:integer; {number of bytes in an \\{xxx} command}
  2020. @!j:integer; {number of bytes read so far}
  2021. begin case cur_gf of
  2022. no_op:goto done;
  2023. yyy:begin k:=signed_quad; goto done;
  2024.   end;
  2025. xxx1:k:=get_byte;
  2026. xxx2:k:=get_two_bytes;
  2027. xxx3:k:=get_three_bytes;
  2028. xxx4:k:=signed_quad;
  2029. end; {there are no other cases}
  2030. for j:=1 to k do cur_gf:=get_byte;
  2031. done: cur_gf:=get_byte;
  2032. @* File names.
  2033. It's time now to fret about file names. \.{GFtoDVI} uses the conventions of
  2034. \TeX\ and \MF\ to convert file names into strings that can be used to open
  2035. files. Three routines called |begin_name|, |more_name|, and |end_name| are
  2036. involved, so that the system-dependent parts of file naming conventions are
  2037. isolated from the system-independent ways in which file names are used.
  2038. (See the \TeX\ or \MF\ program listing for further explanation.)
  2039. @^system dependencies@>
  2040. @<Glob...@>=
  2041. @!cur_name:str_number; {name of file just scanned}
  2042. @!cur_area:str_number; {file area just scanned, or |null_string|}
  2043. @!cur_ext:str_number; {file extension just scanned, or |null_string|}
  2044. @ The file names we shall deal with for illustrative purposes have the
  2045. following structure:  If the name contains `\.>' or `\.:', the file area
  2046. consists of all characters up to and including the final such character;
  2047. otherwise the file area is null.  If the remaining file name contains
  2048. `\..', the file extension consists of all such characters from the first
  2049. remaining `\..' to the end, otherwise the file extension is null.
  2050. @^system dependencies@>
  2051. We can scan such file names easily by using two global variables that keep track
  2052. of the occurrences of area and extension delimiters:
  2053. @<Glob...@>=
  2054. @!area_delimiter:pool_pointer; {the most recent `\.>' or `\.:', if any}
  2055. @!ext_delimiter:pool_pointer; {the relevant `\..', if any}
  2056. @ Font metric files whose areas are not given
  2057. explicitly are assumed to appear in a standard system area called
  2058. |home_font_area|.  This system area name will, of course, vary from place
  2059. to place. The program here sets it to `\.{TeXfonts:}'.
  2060. @^system dependencies@>
  2061. @.TeXfonts@>
  2062. @<Initialize the strings@>=
  2063. l:=9; init_str9("T")("e")("X")("f")("o")("n")("t")("s")(":")(home_font_area);@/
  2064. @ Here now is the first of the system-dependent routines for file name scanning.
  2065. @^system dependencies@>
  2066. @p procedure begin_name;
  2067. begin area_delimiter:=0; ext_delimiter:=0;
  2068. @ And here's the second.
  2069. @^system dependencies@>
  2070. @p function more_name(@!c:ASCII_code):boolean;
  2071. begin if c=" " then more_name:=false
  2072. else  begin if (c=">")or(c=":") then
  2073.     begin area_delimiter:=pool_ptr; ext_delimiter:=0;
  2074.     end
  2075.   else if (c=".")and(ext_delimiter=0) then ext_delimiter:=pool_ptr;
  2076.   str_room(1); append_char(c); {contribute |c| to the current string}
  2077.   more_name:=true;
  2078.   end;
  2079. @ The third.
  2080. @^system dependencies@>
  2081. @p procedure end_name;
  2082. begin if str_ptr+3>max_strings then
  2083.   abort('Too many strings!');
  2084. @.Too many strings@>
  2085. if area_delimiter=0 then cur_area:=null_string
  2086. else  begin cur_area:=str_ptr; incr(str_ptr);
  2087.   str_start[str_ptr]:=area_delimiter+1;
  2088.   end;
  2089. if ext_delimiter=0 then
  2090.   begin cur_ext:=null_string; cur_name:=make_string;
  2091.   end
  2092. else  begin cur_name:=str_ptr; incr(str_ptr);
  2093.   str_start[str_ptr]:=ext_delimiter; cur_ext:=make_string;
  2094.   end;
  2095. @ Another system-dependent routine is needed to convert three strings
  2096. into the |name_of_file| value that is used to open files. The present code
  2097. allows both lowercase and uppercase letters in the file name.
  2098. @^system dependencies@>
  2099. @d append_to_name(#)==begin c:=#; incr(k);
  2100.   if k<=file_name_size then name_of_file[k]:=xchr[c];
  2101.   end
  2102. @p procedure pack_file_name(@!n,@!a,@!e:str_number);
  2103. var k:integer; {number of positions filled in |name_of_file|}
  2104. @!c: ASCII_code; {character being packed}
  2105. @!j:integer; {index into |str_pool|}
  2106. @!name_length:0..file_name_size; {number of characters packed}
  2107. begin k:=0;
  2108. for j:=str_start[a] to str_start[a+1]-1 do append_to_name(str_pool[j]);
  2109. for j:=str_start[n] to str_start[n+1]-1 do append_to_name(str_pool[j]);
  2110. for j:=str_start[e] to str_start[e+1]-1 do append_to_name(str_pool[j]);
  2111. if k<=file_name_size then name_length:=k@+else name_length:=file_name_size;
  2112. for k:=name_length+1 to file_name_size do name_of_file[k]:=' ';
  2113. @ Now let's consider the routines by which \.{GFtoDVI} deals with file names
  2114. in a system-independent manner.
  2115. The global variable |job_name| contains the \.{GF} file name that is
  2116. being input. This name is extended by `\.{dvi}'
  2117. in order to make the name of the output file.
  2118. @<Glob...@>=
  2119. @!job_name:str_number; {principal file name}
  2120. @ The |start_gf| procedure prompts the user for the name of the generic
  2121. font file to be input. It opens the file, making sure that some input is
  2122. present; then it opens the output file.
  2123. Although this routine is system-independent, it should probably be
  2124. modified to take the file name from the command line (without an initial
  2125. prompt), on systems that permit such things.
  2126. @p procedure start_gf;
  2127. label found,done;
  2128. begin loop@+begin print_nl('GF file name: '); input_ln;
  2129. @.GF file name@>
  2130.   buf_ptr:=0; buffer[line_length]:="?";
  2131.   while buffer[buf_ptr]=" " do incr(buf_ptr);
  2132.   if buf_ptr<line_length then
  2133.     begin @<Scan the file name in the buffer@>;
  2134.     if cur_ext=null_string then cur_ext:=gf_ext;
  2135.     pack_file_name(cur_name,cur_area,cur_ext); open_gf_file;
  2136.     if not eof(gf_file) then goto found;
  2137.     print_nl('Oops... I can''t find file '); print(name_of_file);
  2138. @.Oops...@>
  2139. @.I can't find...@>
  2140.     end;
  2141.   end;
  2142. found:job_name:=cur_name; pack_file_name(job_name,null_string,dvi_ext);
  2143. open_dvi_file;
  2144. @ @<Scan the file name in the buffer@>=
  2145. if buffer[line_length-1]="/" then
  2146.   begin interaction:=true; decr(line_length);
  2147.   end;
  2148. begin_name;
  2149. loop@+  begin if buf_ptr=line_length then goto done;
  2150.   if not more_name(buffer[buf_ptr]) then goto done;
  2151.   incr(buf_ptr);
  2152.   end;
  2153. done:end_name
  2154. @ Special instructions found near the beginning of the \.{GF} file might
  2155. change the names, areas, and ``at'' sizes of the fonts that \.{GFtoDVI}
  2156. will be using. But when we reach the first |boc| instruction, we input
  2157. all of the \.{TFM} files. The global variable |interaction| is set |true|
  2158. if a |"/"| was removed at the end of the file name; this means that the
  2159. user will have a chance to issue special instructions online just before
  2160. the fonts are loaded.
  2161. @d check_fonts==@+if fonts_not_loaded then load_fonts
  2162. @<Glob...@>=
  2163. @!interaction:boolean; {is the user allowed to type specials online?}
  2164. @!fonts_not_loaded:boolean; {have the \.{TFM} files still not been input?}
  2165. @!font_name:array[internal_font_number] of str_number; {current font names}
  2166. @!font_area:array[internal_font_number] of str_number; {current font areas}
  2167. @!font_at:array[internal_font_number] of scaled; {current font ``at'' sizes}
  2168. @ @<Set init...@>=
  2169. interaction:=false; fonts_not_loaded:=true;
  2170. font_name[title_font]:=default_title_font;
  2171. font_name[label_font]:=default_label_font;
  2172. font_name[gray_font]:=default_gray_font;
  2173. font_name[slant_font]:=null_string;
  2174. font_name[logo_font]:=logo_font_name;
  2175. for k:=title_font to logo_font do
  2176.   begin font_area[k]:=null_string; font_at[k]:=0;
  2177.   end;
  2178. @ After the following procedure has been performed, there will be no
  2179. turning back; the fonts will have been firmly established in
  2180. \.{GFtoDVI}'s memory.
  2181. @<Declare the procedure called |load_fonts|@>=
  2182. procedure load_fonts;
  2183. label done,continue,found,not_found;
  2184. var @!f:internal_font_number;
  2185. @!i:four_quarters; {font information word}
  2186. @!j,@!k,@!v:integer; {registers for initializing font tables}
  2187. @!m:title_font..slant_font+area_code; {keyword found}
  2188. @!n1:0..longest_keyword; {buffered character being checked}
  2189. @!n2:pool_pointer; {pool character being checked}
  2190. begin if interaction then @<Get online special input@>;
  2191. fonts_not_loaded:=false;
  2192. for f:=title_font to logo_font do
  2193.  if (f<>slant_font)or(length(font_name[f])>0) then
  2194.   begin if length(font_area[f])=0 then font_area[f]:=home_font_area;
  2195.   pack_file_name(font_name[f],font_area[f],tfm_ext);
  2196.   open_tfm_file; read_font_info(f,font_at[f]);
  2197.   if font_area[f]=home_font_area then font_area[f]:=null_string;
  2198.   dvi_font_def(f); {put the font name in the \.{DVI} file}
  2199.   end;
  2200. @<Initialize global variables that depend on the font data@>;
  2201. @ @<Get online special input@>=
  2202. loop@+  begin not_found: print_nl('Special font substitution: ');
  2203. @.Special font subst...@>
  2204.   continue: input_ln;
  2205.   if line_length=0 then goto done;
  2206.   @<Search buffer for valid keyword; if successful, |goto found|@>;
  2207.   print('Please say, e.g., "grayfont foo" or "slantfontarea baz".');
  2208.   goto not_found;
  2209.   found: @<Update the font name or area@>;
  2210.   print('OK; any more? '); goto continue;
  2211.   end;
  2212. done:
  2213. @ @<Search buffer for valid keyword; if successful, |goto found|@>=
  2214. buf_ptr:=0; buffer[line_length]:=" ";
  2215. while buffer[buf_ptr]<>" " do incr(buf_ptr);
  2216. for m:=title_font to slant_font+area_code do if length(m)=buf_ptr then
  2217.   begin n1:=0; n2:=str_start[m];
  2218.   while (n1<buf_ptr)and(buffer[n1]=str_pool[n2]) do
  2219.     begin incr(n1); incr(n2);
  2220.     end;
  2221.   if n1=buf_ptr then goto found;
  2222.   end
  2223. @ @<Update the font name or area@>=
  2224. incr(buf_ptr); str_room(line_length-buf_ptr);
  2225. while buf_ptr<line_length do
  2226.   begin append_char(buffer[buf_ptr]); incr(buf_ptr);
  2227.   end;
  2228. if m>area_code then font_area[m-area_code]:=make_string
  2229. else  begin font_name[m]:=make_string; font_area[m]:=null_string;
  2230.   font_at[m]:=0;
  2231.   end;
  2232. init_str_ptr:=str_ptr
  2233. @* Shipping pages out.
  2234. The following routines are used to write the \.{DVI} file. They have
  2235. been copied from \TeX, but simplified; we don't have to handle
  2236. nearly as much generality as \TeX\ does.
  2237. Statistics about the entire set of pages that will be shipped out must be
  2238. reported in the \.{DVI} postamble. The global variables |total_pages|,
  2239. |max_v|, |max_h|, and |last_bop| are used to record this information.
  2240. @<Glob...@>=
  2241. @!total_pages:integer; {the number of pages that have been shipped out}
  2242. @!max_v:scaled; {maximum height-plus-depth of pages shipped so far}
  2243. @!max_h:scaled; {maximum width of pages shipped so far}
  2244. @!last_bop:integer; {location of previous |bop| in the \.{DVI} output}
  2245. @ @<Set init...@>=
  2246. total_pages:=0; max_v:=0; max_h:=0; last_bop:=-1;
  2247. @ The \.{DVI} bytes are output to a buffer instead of being written directly
  2248. to the output file. This makes it possible to reduce the overhead of
  2249. subroutine calls.
  2250. The output buffer is divided into two parts of equal size; the bytes found
  2251. in |dvi_buf[0..half_buf-1]| constitute the first half, and those in
  2252. |dvi_buf[half_buf..dvi_buf_size-1]| constitute the second. The global
  2253. variable |dvi_ptr| points to the position that will receive the next
  2254. output byte. When |dvi_ptr| reaches |dvi_limit|, which is always equal
  2255. to one of the two values |half_buf| or |dvi_buf_size|, the half buffer that
  2256. is about to be invaded next is sent to the output and |dvi_limit| is
  2257. changed to its other value. Thus, there is always at least a half buffer's
  2258. worth of information present, except at the very beginning of the job.
  2259. Bytes of the \.{DVI} file are numbered sequentially starting with 0;
  2260. the next byte to be generated will be number |dvi_offset+dvi_ptr|.
  2261. @<Types ...@>=
  2262. @!dvi_index=0..dvi_buf_size; {an index into the output buffer}
  2263. @ Some systems may find it more efficient to make |dvi_buf| a |packed|
  2264. array, since output of four bytes at once may be facilitated.
  2265. @^system dependencies@>
  2266. @<Glob...@>=
  2267. @!dvi_buf:array[dvi_index] of eight_bits; {buffer for \.{DVI} output}
  2268. @!half_buf:dvi_index; {half of |dvi_buf_size|}
  2269. @!dvi_limit:dvi_index; {end of the current half buffer}
  2270. @!dvi_ptr:dvi_index; {the next available buffer address}
  2271. @!dvi_offset:integer; {|dvi_buf_size| times the number of times the
  2272.   output buffer has been fully emptied}
  2273. @ Initially the buffer is all in one piece; we will output half of it only
  2274. after it first fills up.
  2275. @<Set init...@>=
  2276. half_buf:=dvi_buf_size div 2; dvi_limit:=dvi_buf_size; dvi_ptr:=0;
  2277. dvi_offset:=0;
  2278. @ The actual output of |dvi_buf[a..b]| to |dvi_file| is performed by calling
  2279. |write_dvi(a,b)|. It is safe to assume that |a| and |b+1| will both be
  2280. multiples of 4 when |write_dvi(a,b)| is called; therefore it is possible on
  2281. many machines to use efficient methods to pack four bytes per word and to
  2282. output an array of words with one system call.
  2283. @^system dependencies@>
  2284. @p procedure write_dvi(@!a,@!b:dvi_index);
  2285. var k:dvi_index;
  2286. begin for k:=a to b do write(dvi_file,dvi_buf[k]);
  2287. @ To put a byte in the buffer without paying the cost of invoking a procedure
  2288. each time, we use the macro |dvi_out|.
  2289. @d dvi_out(#)==@+begin dvi_buf[dvi_ptr]:=#; incr(dvi_ptr);
  2290.   if dvi_ptr=dvi_limit then dvi_swap;
  2291.   end
  2292. @p procedure dvi_swap; {outputs half of the buffer}
  2293. begin if dvi_limit=dvi_buf_size then
  2294.   begin write_dvi(0,half_buf-1); dvi_limit:=half_buf;
  2295.   dvi_offset:=dvi_offset+dvi_buf_size; dvi_ptr:=0;
  2296.   end
  2297. else  begin write_dvi(half_buf,dvi_buf_size-1); dvi_limit:=dvi_buf_size;
  2298.   end;
  2299. @ Here is how we clean out the buffer when \TeX\ is all through; |dvi_ptr|
  2300. will be a multiple of~4.
  2301. @<Empty the last bytes out of |dvi_buf|@>=
  2302. if dvi_limit=half_buf then write_dvi(half_buf,dvi_buf_size-1);
  2303. if dvi_ptr>0 then write_dvi(0,dvi_ptr-1)
  2304. @ The |dvi_four| procedure outputs four bytes in two's complement notation,
  2305. without risking arithmetic overflow.
  2306. @p procedure dvi_four(@!x:integer);
  2307. begin if x>=0 then dvi_out(x div @'100000000)
  2308. else  begin x:=x+@'10000000000;
  2309.   x:=x+@'10000000000;
  2310.   dvi_out((x div @'100000000) + 128);
  2311.   end;
  2312. x:=x mod @'100000000; dvi_out(x div @'200000);
  2313. x:=x mod @'200000; dvi_out(x div @'400);
  2314. dvi_out(x mod @'400);
  2315. @ Here's a procedure that outputs a font definition.
  2316. @d select_font(#)==dvi_out(fnt_num_0+#) {set current font to \#}
  2317. @p procedure dvi_font_def(@!f:internal_font_number);
  2318. var k:integer; {index into |str_pool|}
  2319. begin dvi_out(fnt_def1);
  2320. dvi_out(f);@/
  2321. dvi_out(qo(font_check[f].b0));
  2322. dvi_out(qo(font_check[f].b1));
  2323. dvi_out(qo(font_check[f].b2));
  2324. dvi_out(qo(font_check[f].b3));@/
  2325. dvi_four(font_size[f]);
  2326. dvi_four(font_dsize[f]);@/
  2327. dvi_out(length(font_area[f]));
  2328. dvi_out(length(font_name[f]));
  2329. @<Output the font name whose internal number is |f|@>;
  2330. end;@/
  2331. @t\4@>@<Declare the procedure called |load_fonts|@>@;
  2332. @ @<Output the font name whose internal number is |f|@>=
  2333. for k:=str_start[font_area[f]] to str_start[font_area[f]+1]-1 do
  2334.   dvi_out(str_pool[k]);
  2335. for k:=str_start[font_name[f]] to str_start[font_name[f]+1]-1 do
  2336.   dvi_out(str_pool[k])
  2337. @ The |typeset| subroutine typesets any eight-bit character.
  2338. @p procedure typeset(@!c:eight_bits);
  2339. begin if c>=128 then dvi_out(set1);
  2340. dvi_out(c);
  2341. @ The |dvi_scaled| subroutine takes a |real| value |x| and outputs
  2342. a decimal approximation to |x/unity|, correct to one decimal place.
  2343. @p procedure dvi_scaled(@!x:real);
  2344. var @!n:integer; {an integer approximation to |10*x/unity|}
  2345. @!m:integer; {the integer part of the answer}
  2346. @!k:integer; {the number of digits in |m|}
  2347. begin n:=round(x/6553.6);
  2348. if n<0 then
  2349.   begin dvi_out("-"); n:=-n;
  2350.   end;
  2351. m:=n div 10; k:=0;
  2352. repeat incr(k); buffer[k]:=(m mod 10)+"0"; m:=m div 10;
  2353. until m=0;
  2354. repeat dvi_out(buffer[k]); decr(k);
  2355. until k=0;
  2356. if n mod 10 <> 0 then
  2357.   begin dvi_out("."); dvi_out((n mod 10)+"0");
  2358.   end;
  2359. @ At the end of the program, we must finish things off by writing the
  2360. post\-amble. An integer variable~|k| will be declared for use by this routine.
  2361. @<Finish the \.{DVI} file and |goto final_end|@>=
  2362. begin dvi_out(post); {beginning of the postamble}
  2363. dvi_four(last_bop); last_bop:=dvi_offset+dvi_ptr-5; {|post| location}
  2364. dvi_four(25400000); dvi_four(473628672); {conversion ratio for sp}
  2365. dvi_four(1000); {magnification factor}
  2366. dvi_four(max_v); dvi_four(max_h);@/
  2367. dvi_out(0); dvi_out(3); {`\\{max\_push}' is said to be 3}@/
  2368. dvi_out(total_pages div 256); dvi_out(total_pages mod 256);@/
  2369. if not fonts_not_loaded then
  2370.   for k:=title_font to logo_font do
  2371.     if length(font_name[k])>0 then dvi_font_def(k);
  2372. dvi_out(post_post); dvi_four(last_bop); dvi_out(dvi_id_byte);@/
  2373. k:=4+((dvi_buf_size-dvi_ptr) mod 4); {the number of 223's}
  2374. while k>0 do
  2375.   begin dvi_out(223); decr(k);
  2376.   end;
  2377. @<Empty the last bytes out of |dvi_buf|@>;
  2378. goto final_end;
  2379. @* Rudimentary typesetting.
  2380. One of \.{GFtoDVI}'s little duties is to be a mini-\TeX: It must be able
  2381. to typeset the equivalent of `\.{\\hbox\{}$\langle$string$\rangle$\.\}' for
  2382. a given string of ASCII characters, using either the title font or the
  2383. label font.
  2384. The |hbox| procedure does this. The width, height, and depth of the
  2385. box defined by string~|s| in font~|f| are computed in global variables
  2386. |box_width|, |box_height|, and |box_depth|.
  2387. The task would be trivial if it weren't for ligatures and kerns, which
  2388. are implemented here in full generality. (Infinite looping is possible
  2389. if the \.{TFM} file is malformed; \.{TFtoPL} will diagnose such problems.)
  2390. We assume that |" "| is a space character; character code @'40 will not
  2391. be typeset unless it is accessed via a ligature.
  2392. If parameter |send_it| is |false|, we merely want to know the box dimensions.
  2393. Otherwise typesetting commands are also sent to
  2394. the \.{DVI} file; we assume in this case that font |f| has already been
  2395. selected in the \.{DVI} file as the current font.
  2396. @d set_cur_r==if k<end_k then cur_r:=qi(str_pool[k])
  2397.     else cur_r:=bchar
  2398. @p procedure hbox(@!s:str_number;@!f:internal_font_number;@!send_it:boolean);
  2399. label continue, done;
  2400. var @!k,@!end_k,@!max_k:pool_pointer; {indices into |str_pool|}
  2401. @!i,@!j:four_quarters; {font information words}
  2402. @!cur_l:0..256; {character to the left of the ``cursor''}
  2403. @!cur_r:min_quarterword..non_char; {character to the right of the ``cursor''}
  2404. @!bchar:min_quarterword..non_char; {right boundary character}
  2405. @!stack_ptr:0..lig_lookahead; {number of entries on |lig_stack|}
  2406. @!l:font_index; {pointer to lig/kern instruction}
  2407. @!kern_amount:scaled; {extra space to be typeset}
  2408. @!hd:eight_bits; {height and depth indices for a character}
  2409. @!x:scaled; {temporary register}
  2410. @!save_c:ASCII_code; {character temporarily blanked out}
  2411. begin box_width:=0; box_height:=0; box_depth:=0;@/
  2412. k:=str_start[s]; max_k:=str_start[s+1];
  2413. save_c:=str_pool[max_k]; str_pool[max_k]:=" ";
  2414. while k<max_k do
  2415.   begin if str_pool[k]=" " then @<Typeset a space in font |f| and advance~|k|@>
  2416.   else begin end_k:=k;
  2417.     repeat incr(end_k); until str_pool[end_k]=" ";
  2418.     kern_amount:=0; cur_l:=256; stack_ptr:=0; bchar:=font_bchar[f];
  2419.     set_cur_r; suppress_lig:=false;
  2420. continue: @<If there's a ligature or kern at the cursor position,
  2421.      update the cursor data structures, possibly advancing~|k|; continue
  2422.      until the cursor wants to move right@>;
  2423.     @<Typeset character |cur_l|, if it exists in the font;
  2424.      also append an optional kern@>;
  2425.     @<Move the cursor to the right and |goto continue|, if there's
  2426.      more work to do in the current word@>;
  2427.     end; {now |k=end_k|}
  2428.   end;
  2429. str_pool[max_k]:=save_c;
  2430. @ @<Glob...@>=
  2431. @!box_width:scaled; {width of box constructed by |hbox|}
  2432. @!box_height:scaled; {height of box constructed by |hbox|}
  2433. @!box_depth:scaled; {depth of box constructed by |hbox|}
  2434. @!lig_stack:array[1..lig_lookahead] of quarterword; {inserted ligature chars}
  2435. @!dummy_info:four_quarters; {fake |char_info| for nonexistent character}
  2436. @!suppress_lig:boolean; {should we bypass checking for ligatures next time?}
  2437. @ @<Set init...@>=
  2438. dummy_info.b0:=qi(0); dummy_info.b1:=qi(0); dummy_info.b2:=qi(0);
  2439. dummy_info.b3:=qi(0);
  2440. @ @<Typeset a space...@>=
  2441. begin box_width:=box_width+space(f);
  2442. if send_it then
  2443.   begin dvi_out(right4); dvi_four(space(f));
  2444.   end;
  2445. incr(k);
  2446. @ @<If there's a ligature...@>=
  2447. if(cur_l<font_bc[f])or(cur_l>font_ec[f]) then
  2448.   begin i:=dummy_info;
  2449.   if cur_l=256 then l:=bchar_label[f]@+else l:=non_address;
  2450.   end
  2451. else begin i:=char_info(f)(cur_l);
  2452.   if char_tag(i)<>lig_tag then l:=non_address
  2453.   else begin l:=lig_kern_start(f)(i); j:=font_info[l].qqqq;
  2454.     if skip_byte(j)>stop_flag then l:=lig_kern_restart(f)(j);
  2455.     end;
  2456.   end;
  2457. if suppress_lig then suppress_lig:=false
  2458. else while l<qi(kern_base[f]) do
  2459.   begin j:=font_info[l].qqqq;
  2460.   if next_char(j)=cur_r then if skip_byte(j)<=stop_flag then
  2461.     if op_byte(j)>=kern_flag then
  2462.       begin kern_amount:=char_kern(f)(j); goto done;
  2463.       end
  2464.     else @<Carry out a ligature operation, updating the cursor structure
  2465.       and possibly advancing~|k|; |goto continue| if the cursor doesn't
  2466.       advance, otherwise |goto done|@>;
  2467.   if skip_byte(j)>=stop_flag then goto done;
  2468.   l:=l+skip_byte(j)+1;
  2469.   end;
  2470. done:
  2471. @ At this point |i| contains |char_info| for |cur_l|.
  2472. @<Typeset character...@>=
  2473. if char_exists(i) then
  2474.   begin box_width:=box_width+char_width(f)(i)+kern_amount;@/
  2475.   hd:=height_depth(i);
  2476.   x:=char_height(f)(hd);
  2477.   if x>box_height then box_height:=x;
  2478.   x:=char_depth(f)(hd);
  2479.   if x>box_depth then box_depth:=x;
  2480.   if send_it then
  2481.     begin typeset(cur_l);
  2482.     if kern_amount<>0 then
  2483.       begin dvi_out(right4); dvi_four(kern_amount);
  2484.       end;
  2485.     end;
  2486.   kern_amount:=0;
  2487.   end
  2488. @ @d pop_stack==begin decr(stack_ptr);
  2489.     if stack_ptr>0 then cur_r:=lig_stack[stack_ptr]
  2490.     else set_cur_r;
  2491.     end
  2492. @<Carry out a ligature operation, updating the cursor structure...@>=
  2493. begin case op_byte(j) of
  2494. 1,5:cur_l:=qo(rem_byte(j));
  2495. 2,6:begin cur_r:=rem_byte(j);
  2496.   if stack_ptr=0 then
  2497.     begin stack_ptr:=1;
  2498.     if k<end_k then incr(k) {a non-space character is consumed}
  2499.     else bchar:=non_char; {the right boundary character is consumed}
  2500.     end;
  2501.   lig_stack[stack_ptr]:=cur_r;
  2502.   end;
  2503. 3,7,11:begin cur_r:=rem_byte(j); incr(stack_ptr); lig_stack[stack_ptr]:=cur_r;
  2504.   if op_byte(j)=11 then suppress_lig:=true;
  2505.   end;
  2506. othercases begin cur_l:=qo(rem_byte(j));
  2507.   if stack_ptr>0 then pop_stack
  2508.   else if k=end_k then goto done
  2509.   else begin incr(k); set_cur_r;
  2510.     end;
  2511.   end
  2512. endcases;
  2513. if op_byte(j)>3 then goto done;
  2514. goto continue;
  2515. @ @<Move the cursor to the right and |goto continue|...@>=
  2516. cur_l:=qo(cur_r);
  2517. if stack_ptr>0 then
  2518.   begin pop_stack; goto continue;
  2519.   end;
  2520. if k<end_k then
  2521.   begin incr(k); set_cur_r; goto continue;
  2522.   end
  2523. @* Gray fonts.
  2524. A proof diagram constructed by \.{GFtoDVI}
  2525. can be regarded as an array of rectangles, where each rectangle is either
  2526. blank or filled with a special symbol that we shall call $x$. A blank
  2527. rectangle represents a white pixel, while $x$ represents a black pixel.
  2528. Additional labels and reference lines are often superimposed on this
  2529. array of rectangles; hence it is usually best to choose a symbol $x$ that
  2530. has a somewhat gray appearance, although any symbol can actually be used.
  2531. In order to construct such proofs, \.{GFtoDVI} needs to work with
  2532. a special type of font known as a ``gray font''; it's possible to
  2533. obtain a wide variety of different sorts of proofs by using different
  2534. sorts of gray fonts. The next few paragraphs explain exactly what gray
  2535. fonts are supposed to contain, in case you want to design your own.
  2536. @^gray fonts@>
  2537. @ The simplest gray font contains only two characters, namely $x$
  2538. and another symbol that is used for dots that identify key points.
  2539. If proofs with relatively large pixels are desired, a two-character
  2540. gray font is all that's needed. However, if the pixel size is to be
  2541. relatively small, practical considerations make a two-character
  2542. font too inefficient, since it requires the typesetting of tens
  2543. of thousands of tiny little characters; printing device drivers
  2544. rarely work very well when they are presented with data that is
  2545. so different from ordinary text. Therefore a gray font with small
  2546. pixels usually has a number of characters that replicate $x$ in
  2547. such a way that comparatively few characters actually need to be
  2548. typeset.
  2549. Since many printing devices are not able to cope with
  2550. arbitrarily large or complex characters, it is not possible for a
  2551. single gray font to work well on all machines. In fact,
  2552. $x$ must have a width that is an integer multiple of the printing
  2553. device's unit of horizontal position, since rounding the positions of grey
  2554. characters would otherwise produce unsightly streaks on proof output.
  2555. Thus, there is no way to make the gray font as device-independent as
  2556. the rest of the system, in the sense that we would expect approximately
  2557. identical output on machines with different resolution. Fortunately,
  2558. proof sheets are rarely considered to be final documents; hence
  2559. \.{GFtoDVI} is set up to provide results that adapt suitably to
  2560. local conditions.
  2561. @ With such constraints understood, we can now take a look at what
  2562. \.{GFtoDVI} expects to see in a gray font. The character~$x$ always
  2563. appears in position~1. It must have positive height~$h$ and positive
  2564. width~$w$; its depth and italic correction are ignored.
  2565. Positions 2--120 of a gray font are reserved for special combinations
  2566. of $x$'s and blanks, stacked on top of each other. None of these character
  2567. codes need be present in the font; but if they are, the slots should be
  2568. occupied by characters of width~$w$ that have certain configurations of
  2569. $x$'s and blanks, prescribed for each character position. For example,
  2570. position~3 of the font should either contain no character at all,
  2571. or it should contain a character consisting of two $x$'s, one above
  2572. the other; one of these $x$'s should appear immediately above the
  2573. baseline, and the other should appear immediately below.
  2574. It will be convenient to use a horizontal notation like `\.{XOXXO}'
  2575. to stand for a vertical stack of $x$'s and blanks. The convention
  2576. will be that the stack is built from bottom to top, and the topmost
  2577. rectangle should sit on the baseline. Thus, `\.{XOXXO}' stands
  2578. actually for a character of depth~$4h$ that looks like this:
  2579. $$\vcenter{\halign{\hfil#\hfil\cr
  2580. blank\cr
  2581. $x$\rlap{\qquad\raise8pt\hbox{\smash{\hbox{$\longleftarrow$ baseline}}}}\cr
  2582. $x$\cr
  2583. blank\cr
  2584. $x$\cr
  2585. (We use a horizontal notation instead of a vertical one in this explanation,
  2586. because column
  2587. vectors take too much space, and because the horizontal notation corresponds
  2588. to binary numbers in a convenient way.)
  2589. Positions 1--63 of a gray font are reserved for the patterns \.X, \.{XO},
  2590. \.{XX}, \.{XOO}, \.{XOX}, \dots, \.{XXXXXX}, just as in the normal
  2591. binary notation of the numbers 1--63. Positions 64--70 are reserved for
  2592. the special patterns \.{XOOOOOO}, \.{XXOOOOO}, \dots, \.{XXXXXXO},
  2593. \.{XXXXXXX} of length seven; positions 71--78 are, similarly, reserved for
  2594. the length-eight patterns \.{XOOOOOOO} through \.{XXXXXXXX}. The
  2595. length-nine patterns \.{XOOOOOOOO} through \.{XXXXXXXXX} are assigned
  2596. to positions 79--87, the length-ten patterns to positions 88--97,
  2597. the length-eleven patterns to positions 98--108, and the length-twelve
  2598. patterns to positions 109--120.
  2599. The following program sets a global array |c[1..120]| to the bit patterns
  2600. just described. Another array |d[1..120]| is set to contain only the next
  2601. higher bit; this determines the depth of the corresponding character.
  2602. @<Set init...@>=
  2603. c[1]:=1; d[1]:=2; two_to_the[0]:=1; m:=1;
  2604. for k:=1 to 13 do two_to_the[k]:=2*two_to_the[k-1];
  2605. for k:=2 to 6 do @<Add a full set of |k|-bit characters@>;
  2606. for k:=7 to 12 do @<Add special |k|-bit characters of the form \.{X..XO..O}@>;
  2607. @ @<Glob...@>=
  2608. @!c:array[1..120] of 1..4095; {bit patterns for a gray font}
  2609. @!d:array[1..120] of 2..4096; {the superleading bits}
  2610. @!two_to_the:array[0..13] of 1..8192; {powers of 2}
  2611. @ @<Add a full set of |k|-bit...@>=
  2612. begin n:=two_to_the[k-1];
  2613. for j:=0 to n-1 do
  2614.   begin incr(m); c[m]:=m; d[m]:=n+n;
  2615.   end;
  2616. @ @<Add special |k|-bit...@>=
  2617. begin n:=two_to_the[k-1];
  2618. for j:=k downto 1 do
  2619.   begin incr(m); d[m]:=n+n;
  2620.   if j=k then c[m]:=n
  2621.   else c[m]:=c[m-1]+two_to_the[j-1];
  2622.   end;
  2623. @ Position 0 of a gray font is reserved for the ``dot'' character, which
  2624. should have positive height~$h'$ and positive width~$w'$. When \.{GFtoDVI}
  2625. wants to put a dot at some place $(x,y)$ on the figure, it positions
  2626. the dot character so that its reference point is at $(x,y)$. The
  2627. dot will be considered to occupy a rectangle $(x+\delta,y+\epsilon)$
  2628. for $-w'\leq\delta\leq w'$ and $-h'\leq\epsilon\leq h'$; the rectangular
  2629. box for a label will butt up against the rectangle enclosing the dot.
  2630. @ All other character positions of a gray font (namely, positions 121--255)
  2631. are unreserved, in the sense that they have no predefined meaning.
  2632. But \.{GFtoDVI} may access them via the ``character list'' feature of
  2633. \.{TFM} files, starting with any of the characters in positions
  2634. 1--120. In such a case each succeeding character in a list should be
  2635. equivalent to two of its predecessors, horizontally adjacent to each other.
  2636. For example, in a character list like
  2637. $$53,\;121,\;122,\;123$$
  2638. character 121 will stand for two 53's, character 122 for two 121's (i.e.,
  2639. four 53's), and character 123 for two 122's (i.e., eight 53's). Since
  2640. position~53 contains the pattern \.{XXOXOX}, character~123 in this example
  2641. would have height~$h$, depth~$5h$, and width~$8w$, and it would stand for
  2642. the pattern
  2643. $$\vcenter{\halign{&$\hfil#\hfil$\cr
  2644. x&x&x&x&x&x&x&x\cr
  2645. &&&&&&&\cr
  2646. x&x&x&x&x&x&x&x\cr
  2647. &&&&&&&\cr
  2648. x&x&x&x&x&x&x&x\cr
  2649. x&x&x&x&x&x&x&x\cr}}$$
  2650. Such a pattern is, of course, rather unlikely to occur in a \.{GF} file,
  2651. but \.{GFtoDVI} would be able to use if it were present. Designers
  2652. of gray fonts should provide characters only for patterns that they think
  2653. will occur often enough to make the doubling worthwhile. For example,
  2654. the character in position 120 (\.{XXXXXXXXXXXX}), or whatever is the
  2655. tallest stack of $x$'s present in the font, is a natural candidate for
  2656. repeated doubling.
  2657. Here's how \.{GFtoDVI} decides what characters of the gray font will be used,
  2658. given a configuration of black and white pixels: If there are no black
  2659. pixels, stop. Otherwise look at the top row that contains at least one
  2660. black pixel, and the eleven rows that follow. For each such column,
  2661. find the largest~$k$ such that $1\leq k\leq120$ and the gray font contains
  2662. character~$k$ and the pattern assigned to position~$k$ appears in the
  2663. given column. Typeset character $k$ (unless no such character exists)
  2664. and erase the corresponding black pixels; use doubled characters,
  2665. if they are present in the gray font, if two or more consecutive equal
  2666. characters need to be typeset. Repeat the same process on the remaining
  2667. configuration, until all the black pixels have been erased.
  2668. If all characters in positions 1--120 are present, this process is guaranteed to
  2669. take care of at least six rows each time; and it usually takes care of
  2670. twelve, since all patterns that contain at most one ``run'' of $x$'s
  2671. are present.
  2672. @ Fonts have optional parameters, as described in Appendix~F of {\sl The
  2673. \TeX book}, and some of these are important in gray fonts. The
  2674. slant parameter~$s$, if nonzero, will cause \.{GFtoDVI} to skew its
  2675. output; in this case the character $x$ will presumably be a parallelogram
  2676. with a corresponding slant, rather than the usual rectangle. \MF's
  2677. coordinate $(x,y)$ will appear in physical position $(xw+yhs,yh)$
  2678. on the proofsheets.
  2679. Parameter number~8 of a gray font specifies the thickness of rules
  2680. that go on the proofs. If this parameter is zero, \TeX's default
  2681. rule thickness (0.4\thinspace pt) will be used.
  2682. The other parameters of a gray font are ignored by \.{GFtoDVI}, but
  2683. it is conventional to set the font space parameter to~$w$ and the
  2684. xheight parameter to~$h$.
  2685. @ For best results the designer of a gray font should choose $h$ and~$w$
  2686. so that the user's \.{DVI}-to-hardcopy software will not make any
  2687. rounding errors. Furthermore, the dot should be an even number~$2m$ of
  2688. pixels in diameter, and the rule thickness should work out to an
  2689. even number~$2n$ of pixels; then the dots and rules will be centered on
  2690. the correct positions, in case of integer coordinates. Gray fonts
  2691. are almost always intended for particular output devices, even though
  2692. `\.{DVI}' stands for `device independent'; we use \.{DVI} files for \MF\
  2693. proofs chiefly because software to print \.{DVI} files is already in place.
  2694. @* Slant fonts.
  2695. \.{GFtoDVI} also makes use of another special type of font, if it is
  2696. necessary to typeset slanted rules. The format of such  so-called
  2697. ``slant fonts'' is quite a bit simpler than the format of gray fonts.
  2698. A slant font should contain exactly $n$ characters, in positions 1 to~$n$,
  2699. where the character in position~$k$ represents a slanted line $k$ units
  2700. tall, starting at the baseline. These lines all have a fixed slant ratio~$s$.
  2701. The following simple algorithm is used to typeset a rule that is $m$ units
  2702. high: Compute $q=\lceil m/n\rceil$; then typeset $q$~characters of
  2703. approximately equal size, namely $(m\bmod q)$ copies of character number
  2704. $\lceil m/q\rceil$ and $q-(m\bmod q)$ copies of character number
  2705. $\lfloor m/q\rfloor$. For example, if $n=15$ and $m=100$, we have $q=7$;
  2706. a 100-unit-high rule will be composed of 7~pieces, using characters
  2707. 14,~14, 14, 14, 14, 15,~15.
  2708. @<Glob...@>=
  2709. @!rule_slant:real; {the slant ratio $s$ in the slant font,
  2710.   or zero if there is no slant font}
  2711. @!slant_n:integer; {the number of characters in the slant font}
  2712. @!slant_unit:real; {the number of scaled points in the slant font unit}
  2713. @!slant_reported:real; {invalid slant ratio reported to the user}
  2714. @ \.{GFtoDVI} looks only at the height of character $n$, so the \.{TFM} file
  2715. need not be accurate about the heights of the other characters. (This is
  2716. fortunate, since \.{TFM} format allows at most 16 different heights per font.)
  2717. The width of character~$k$ should be $k/n$ times $s$ times the height of
  2718. character~$n$.
  2719. The slant parameter of a slant file should be $s$. It is customary to
  2720. set the |default_rule_thickness| parameter (number~8) to the thickness of
  2721. the slanted rules, but \.{GFtoDVI} doesn't look at it.
  2722. @ For best results on a particular output device, it is usually wise to
  2723. choose the `unit' in the above discussion to be an integer number of pixels,
  2724. and to make it no larger than the default rule thickness in the gray font
  2725. being used.
  2726. @ @<Initialize glob...@>=
  2727. if length(font_name[slant_font])=0 then rule_slant:=0.0
  2728. else  begin rule_slant:=slant(slant_font)/unity;
  2729.   slant_n:=font_ec[slant_font];
  2730.   i:=char_info(slant_font)(slant_n);
  2731.   slant_unit:=char_height(slant_font)(height_depth(i))/slant_n;
  2732.   end;
  2733. slant_reported:=0.0;
  2734. @ The following error message is given when an absent slant has been
  2735. requested.
  2736. @p procedure slant_complaint(@!r:real);
  2737. begin if abs(r-slant_reported)>0.001 then
  2738.   begin print_nl('Sorry, I can''t make diagonal rules of slant ',r:10:5,'!');
  2739. @.Sorry, I can't...@>
  2740.   slant_reported:=r;
  2741.   end;
  2742. @* Representation of rectangles.
  2743. OK---the preliminary spadework has now been done. We're ready at last
  2744. to concentrate on \.{GFtoDVI}'s {\sl raison d'\^^Detre}.
  2745. One of the most interesting tasks remaining is to make
  2746. a ``map'' of the labels that have been allocated.
  2747. There usually aren't a great many labels, so we don't need fancy data
  2748. structures; but we do make use of linked nodes containing nine fields.
  2749. The nodes generally represent rectangular boxes according to the
  2750. following conventions:
  2751. \smallskip\hang\noindent
  2752. |xl|, |xr|, |yt|, and |yb| are the left, right, top, and bottom locations
  2753. of a rectangle, expressed in \.{DVI} coordinates. (This program uses
  2754. scaled points as \.{DVI} coordinates. Since \.{DVI} coordinates increase
  2755. as one moves down the page, |yb| will be greater than |yt|.)
  2756. \smallskip\hang\noindent
  2757. |xx| and |yy| are the coordinates of the reference point of a box to be
  2758. typeset from this node, again in \.{DVI} coordinates.
  2759. \smallskip\hang\noindent
  2760. |prev| and |next| point to the predecessor and successor of this node.
  2761. Sometimes the nodes are singly linked and only |next| is relevant; otherwise
  2762. the nodes are doubly linked in order of their |yy| coordinates, so that we
  2763. can move down by going to |next|, or up by going to |prev|.
  2764. \smallskip\hang\noindent
  2765. |info| is the number of a string associated with this node.
  2766. \smallskip\noindent
  2767. The nine fields of a node appear in nine global arrays.
  2768. Null pointers are denoted by |null|, which happens to be zero.
  2769. @d null=0
  2770. @<Types ...@>=
  2771. @!node_pointer=null..max_labels;
  2772. @ @<Glob...@>=
  2773. @!xl,@!xr,@!yt,@!yb:array[1..max_labels] of scaled; {boundary coordinates}
  2774. @!xx,@!yy:array[0..max_labels] of scaled; {reference coordinates}
  2775. @!prev,@!next:array[0..max_labels] of node_pointer; {links}
  2776. @!info:array[1..max_labels] of str_number; {associated strings}
  2777. @!max_node:node_pointer; {the largest node in use}
  2778. @!max_height:scaled; {greatest difference between |yy| and |yt|}
  2779. @!max_depth:scaled; {greatest difference between |yb| and |yy|}
  2780. @ It's easy to allocate a new node (unless no more room is left):
  2781. @p function get_avail:node_pointer;
  2782. begin incr(max_node);
  2783. if max_node=max_labels then abort('Too many labels and/or rules!');
  2784. @.Too many labels@>
  2785. get_avail:=max_node;
  2786. @ The doubly linked nodes are sorted by |yy| coordinates so that we don't have
  2787. to work too hard to find nearest neighbors or to determine if rectangles overlap.
  2788. The first node in the doubly linked rectangle list is always in location~0,
  2789. and the last node is always in location |max_labels|; the |yy| coordinates
  2790. of these nodes are very small and very large, respectively.
  2791. @d end_of_list==max_labels
  2792. @<Set init...@>=
  2793. yy[0]:=-@'10000000000; yy[end_of_list]:=@'10000000000;
  2794. @ The |node_ins| procedure inserts a new rectangle, represented by node~|p|,
  2795. into the doubly linked list. There's a second parameter, |q|; node~|q| should
  2796. already be in the doubly linked list, preferably with |yy[q]| near |yy[p]|.
  2797. @p procedure node_ins(@!p,@!q:node_pointer);
  2798. var @!r:node_pointer; {for tree traversal}
  2799. begin if yy[p]>=yy[q] then
  2800.   begin repeat r:=q; q:=next[q];@+until yy[p]<=yy[q];
  2801.   next[r]:=p; prev[p]:=r; next[p]:=q; prev[q]:=p;
  2802.   end
  2803. else  begin repeat r:=q; q:=prev[q];@+until yy[p]>=yy[q];
  2804.   prev[r]:=p; next[p]:=r; prev[p]:=q; next[q]:=p;
  2805.   end;
  2806. if yy[p]-yt[p]>max_height then max_height:=yy[p]-yt[p];
  2807. if yb[p]-yy[p]>max_depth then max_depth:=yb[p]-yy[p];
  2808. @ The data structures need to be initialized for each character in the
  2809. \.{GF} file.
  2810. @<Initialize variables for the next character@>=
  2811. max_node:=0; next[0]:=end_of_list; prev[end_of_list]:=0;
  2812. max_height:=0; max_depth:=0;
  2813. @ The |overlap| subroutine determines whether or not the rectangle specified
  2814. in node~|p| has a nonempty intersection with some rectangle in the doubly
  2815. linked list. Again |q|~is a parameter that gives us a starting point
  2816. in the list. We assume that |q<>end_of_list|, so that |next[q]| is meaningful.
  2817. @p function overlap(@!p,@!q:node_pointer):boolean;
  2818. label exit;
  2819. var @!y_thresh:scaled; {cutoff value to speed the search}
  2820. @!x_left,@!x_right,@!y_top,@!y_bot:scaled; {boundaries to test for overlap}
  2821. @!r:node_pointer; {runs through the neighbors of |q|}
  2822. begin x_left:=xl[p]; x_right:=xr[p]; y_top:=yt[p]; y_bot:=yb[p];
  2823. @<Look for overlaps in the successors of node |q|@>;
  2824. @<Look for overlaps in node |q| and its predecessors@>;
  2825. overlap:=false;
  2826. exit: end;
  2827. @ @<Look for overlaps in the successors of node |q|@>=
  2828. y_thresh:=y_bot+max_height; r:=next[q];
  2829. while yy[r]<y_thresh do
  2830.   begin if y_bot > yt[r] then if x_left<xr[r] then
  2831.    if x_right>xl[r] then if y_top<yb[r] then
  2832.     begin overlap:=true; return;
  2833.     end;
  2834.   r:=next[r];
  2835.   end
  2836. @ @<Look for overlaps in node |q| and its predecessors@>=
  2837. y_thresh:=y_top-max_depth; r:=q;
  2838. while yy[r]>y_thresh do
  2839.   begin if y_bot > yt[r] then if x_left<xr[r] then
  2840.    if x_right>xl[r] then if y_top<yb[r] then
  2841.     begin overlap:=true; return;
  2842.     end;
  2843.   r:=prev[r];
  2844.   end
  2845. @ Nodes that represent dots instead of labels satisfy the following
  2846. constraints:
  2847. $$\vcenter{\halign{#\hfil&\quad#\hfil\cr
  2848. |info[p]<0;|&|p>=first_dot|;\cr
  2849. |xl[p]=xx[p]-dot_width|,&|xr[p]=xx[p]+dot_width|;\cr
  2850. |yt[p]=yy[p]-dot_height|,&|yb[p]=yy[p]+dot_height|.\cr}}$$
  2851. The |nearest_dot| subroutine finds a node whose reference point is as
  2852. close as possible to a given position, ignoring nodes that are too close.
  2853. More precisely, the ``nearest'' node
  2854. minimizes$$d(q,p)=\max\bigl(\vert |xx|[q]-|xx|[p]\vert,
  2855.   \vert |yy|[q]-|yy|[p]\vert\bigr)$$ over all nodes~|q|
  2856. with |d(q,p)>=d0|. We call the subroutine |nearest_dot| because it is used only
  2857. when the doubly linked list contains nothing but dots.
  2858. The routine also sets the global variable |twin| to |true|, if there is a
  2859. node |q<>p| with |d(q,p)<d0|.
  2860. @ @<Glob...@>=
  2861. @!first_dot:node_pointer; {the node address where dots begin}
  2862. @!twin:boolean; {is there a nearer dot than the ``nearest'' dot?}
  2863. @ If there is no nearest dot, the value |null| is returned;
  2864. otherwise a pointer to the nearest dot is returned.
  2865. @p function nearest_dot(@!p:node_pointer; @!d0:scaled):node_pointer;
  2866. var @!best_q:node_pointer; {value to return}
  2867. @!d_min,@!d:scaled; {distances}
  2868. begin twin:=false; best_q:=0; d_min:=@'2000000000;
  2869. @<Search for the nearest dot in nodes following |p|@>;
  2870. @<Search for the nearest dot in nodes preceding |p|@>;
  2871. nearest_dot:=best_q;
  2872. @ @<Search for the nearest dot in nodes following |p|@>=
  2873. q:=next[p];
  2874. while yy[q]<yy[p]+d_min do
  2875.   begin d:=abs(xx[q]-xx[p]);
  2876.   if d<yy[q]-yy[p] then d:=yy[q]-yy[p];
  2877.   if d<d0 then twin:=true
  2878.   else if d<d_min then
  2879.     begin d_min:=d; best_q:=q;
  2880.     end;
  2881.   q:=next[q];
  2882.   end
  2883. @ @<Search for the nearest dot in nodes preceding |p|@>=
  2884. q:=prev[p];
  2885. while yy[q]>yy[p]-d_min do
  2886.   begin d:=abs(xx[q]-xx[p]);
  2887.   if d<yy[p]-yy[q] then d:=yy[p]-yy[q];
  2888.   if d<d0 then twin:=true
  2889.   else if d<d_min then
  2890.     begin d_min:=d; best_q:=q;
  2891.     end;
  2892.   q:=prev[q];
  2893.   end
  2894. @* Doing the labels.
  2895. Each ``character'' in the \.{GF} file is preceded by a number of special
  2896. commands that define labels, titles, rules, etc. We store these away,
  2897. to be considered later when the |boc| command appears. The |boc|
  2898. command establishes the size information by which labels and rules
  2899. can be positioned, so we spew out the label information as soon as
  2900. we see the |boc|. The gray pixels will be typeset after all the labels
  2901. for a particular character have been finished.
  2902. @ Here is the part of \.{GFtoDVI} that stores information preceding a~|boc|.
  2903. It comes into play when |cur_gf| is between |xxx1| and~|no_op|, inclusive.
  2904. @d font_change(#)==if fonts_not_loaded then
  2905.     begin #; end
  2906.   else print_nl('(Tardy font change will be ignored (byte ',
  2907. @.Tardy font change...@>
  2908.     cur_loc:1,')!)')
  2909. @<Process a no-op command@>=
  2910. begin k:=interpret_xxx;
  2911. case k of
  2912. no_operation: do_nothing;
  2913. title_font,label_font,gray_font,slant_font:font_change(font_name[k]:=cur_string;
  2914.   font_area[k]:=null_string;font_at[k]:=0;init_str_ptr:=str_ptr);
  2915. title_font+area_code,label_font+area_code,gray_font+area_code,
  2916.   slant_font+area_code:@|
  2917.   font_change(font_area[k-area_code]:=cur_string;init_str_ptr:=str_ptr);
  2918. title_font+at_code,label_font+at_code,gray_font+at_code,
  2919.   slant_font+at_code:@|
  2920.   font_change(font_at[k-at_code]:=get_yyy;init_str_ptr:=str_ptr);
  2921. rule_thickness_code:rule_thickness:=get_yyy;
  2922. rule_code:@<Store a rule@>;
  2923. offset_code:@<Override the offsets@>;
  2924. x_offset_code:x_offset:=get_yyy;
  2925. y_offset_code:y_offset:=get_yyy;
  2926. title_code:@<Store a title@>;
  2927. null_string:@<Store a label@>;
  2928. end; {there are no other cases}
  2929. @ The following quantities are cleared just before reading the
  2930. \.{GF} commands pertaining to a character.
  2931. @<Glob...@>=
  2932. @!rule_thickness:scaled; {the current rule thickness
  2933.   (zero means use the default)}
  2934. @!offset_x,@!offset_y:scaled; {the current offsets for images}
  2935. @!x_offset,@!y_offset:scaled; {the current offsets for labels}
  2936. @!pre_min_x,@!pre_max_x,@!pre_min_y,@!pre_max_y:scaled;
  2937.   {extreme values of coordinates preceding a character, in \MF\ pixels}
  2938. @ @<Initialize variables for the next character@>=
  2939. rule_thickness:=0;
  2940. offset_x:=0; offset_y:=0; x_offset:=0; y_offset:=0;
  2941. pre_min_x:=@'2000000000; pre_max_x:=-@'2000000000;
  2942. pre_min_y:=@'2000000000; pre_max_y:=-@'2000000000;
  2943. @ @<Override the offsets@>=
  2944. begin offset_x:=get_yyy; offset_y:=get_yyy;
  2945. @ Rules that will need to be drawn are kept in a linked list accessible
  2946. via |rule_ptr|, in last-in-first-out order.  The nodes of this list will
  2947. never get into the doubly linked list, and indeed these nodes use different
  2948. field conventions entirely (because rules may be slanted).
  2949. @d x0==xl {starting |x| coordinate of a stored rule}
  2950. @d y0==yt {starting |y| coordinate (in scaled \MF\ pixels)}
  2951. @d x1==xr {ending |x| coordinate of a stored rule}
  2952. @d y1==yb {ending |y| coordinate of a stored rule}
  2953. @d rule_size==xx {thickness of a stored rule, in scaled points}
  2954. @<Glob...@>=
  2955. @!rule_ptr:node_pointer; {top of the stack of remembered rules}
  2956. @ @<Store a rule@>=
  2957. begin p:=get_avail; next[p]:=rule_ptr; rule_ptr:=p;@/
  2958. x0[p]:=get_yyy; y0[p]:=get_yyy; x1[p]:=get_yyy; y1[p]:=get_yyy;
  2959. if x0[p]<pre_min_x then pre_min_x:=x0[p];
  2960. if x0[p]>pre_max_x then pre_max_x:=x0[p];
  2961. if y0[p]<pre_min_y then pre_min_y:=y0[p];
  2962. if y0[p]>pre_max_y then pre_max_y:=y0[p];
  2963. if x1[p]<pre_min_x then pre_min_x:=x1[p];
  2964. if x1[p]>pre_max_x then pre_max_x:=x1[p];
  2965. if y1[p]<pre_min_y then pre_min_y:=y1[p];
  2966. if y1[p]>pre_max_y then pre_max_y:=y1[p];
  2967. rule_size[p]:=rule_thickness;
  2968. @ Titles and labels are, likewise, stored temporarily in singly linked lists.
  2969. In this case the lists are first-in-first-out.
  2970. Variables |title_tail| and |label_tail| point to the most recently inserted
  2971. title or label; variables |title_head| and |label_head|
  2972. point to the beginning of the list. (A standard coding trick is used
  2973. for |label_head|, which is kept in |next[end_of_list]|; we have
  2974. |label_tail=end_of_list| when the list is empty.)
  2975. The |prev| field in nodes of the temporary label list specifies the
  2976. type of label, so we call it |lab_typ|.
  2977. @d lab_typ==prev {the type of a stored label (|"/"..."8"|)}
  2978. @d label_head==next[end_of_list]
  2979. @<Glob...@>=
  2980. @!label_tail:node_pointer; {tail of the queue of remembered labels}
  2981. @!title_head,@!title_tail:node_pointer; {head and tail of the queue for titles}
  2982. @ We must start the lists out empty.
  2983. @<Initialize variables for the next char...@>=
  2984. rule_ptr:=null;
  2985. title_head:=null; title_tail:=null; label_head:=null; label_tail:=end_of_list;
  2986. first_dot:=max_labels;
  2987. @ @<Store a title@>=
  2988. begin p:=get_avail; info[p]:=cur_string;
  2989. if title_head=null then title_head:=p
  2990. else next[title_tail]:=p;
  2991. title_tail:=p;
  2992. @ We store the coordinates of each label in units of \MF\ pixels; they
  2993. will be converted to \.{DVI} coordinates later.
  2994. @<Store a label@>=
  2995. if (label_type<"/")or(label_type>"8") then
  2996.   print_nl('Bad label type precedes byte ',cur_loc:1,'!')
  2997. @.Bad label type...@>
  2998. else  begin p:=get_avail; next[label_tail]:=p; label_tail:=p;@/
  2999.   lab_typ[p]:=label_type; info[p]:=cur_string;@/
  3000.   xx[p]:=get_yyy; yy[p]:=get_yyy;
  3001.   if xx[p]<pre_min_x then pre_min_x:=xx[p];
  3002.   if xx[p]>pre_max_x then pre_max_x:=xx[p];
  3003.   if yy[p]<pre_min_y then pre_min_y:=yy[p];
  3004.   if yy[p]>pre_max_y then pre_max_y:=yy[p];
  3005.   end
  3006. @ The process of ferreting everything away comes to an abrupt halt
  3007. when a |boc| command is sensed. The following steps are performed
  3008. at such times:
  3009. @<Process a character@>=
  3010. begin check_fonts;
  3011. @<Finish reading the parameters of the |boc|@>;
  3012. @<Get ready to convert \MF\ coordinates to \.{DVI} coordinates@>;
  3013. @<Output the |bop| and the title line@>;
  3014. print('[',total_pages:1); update_terminal; {print a progress report}
  3015. @<Output all rules for the current character@>;
  3016. @<Output all labels for the current character@>;
  3017. do_pixels;
  3018. dvi_out(eop); {finish the page}
  3019. @<Adjust the maximum page width@>;
  3020. print(']'); update_terminal;
  3021. @ @<Finish reading the parameters of the |boc|@>=
  3022. if cur_gf=boc then
  3023.   begin ext:=signed_quad; {read the character code}
  3024.   char_code:=ext mod 256;
  3025.   if char_code<0 then char_code:=char_code+256;
  3026.   ext:=(ext-char_code) div 256;
  3027.   k:=signed_quad; {read and ignore the prev pointer}
  3028.   min_x:=signed_quad; {read the minimum $x$ coordinate}
  3029.   max_x:=signed_quad; {read the maximum $x$ coordinate}
  3030.   min_y:=signed_quad; {read the minimum $y$ coordinate}
  3031.   max_y:=signed_quad; {read the maximum $y$ coordinate}
  3032.   end
  3033. else  begin ext:=0; char_code:=get_byte; {|cur_gf=boc1|}
  3034.   min_x:=get_byte; max_x:=get_byte; min_x:=max_x-min_x;@/
  3035.   min_y:=get_byte; max_y:=get_byte; min_y:=max_y-min_y;
  3036.   end;
  3037. if max_x-min_x>widest_row then abort('Character too wide!')
  3038. @.Character too wide@>
  3039. @ @<Glob...@>=
  3040. @!char_code,@!ext:integer; {the current character code and extension}
  3041. @!min_x,@!max_x,@!min_y,@!max_y:integer; {character boundaries, in pixels}
  3042. @!x,@!y:integer; {current painting position, in pixels}
  3043. @!z:integer; {initial painting position in row, relative to |min_x|}
  3044. @ \MF\ coordinates $(x,y)$ are converted to \.{DVI} coordinates by the
  3045. following routine. Real values |x_ratio|, |y_ratio|, and |slant_ratio|
  3046. will have been calculated based on the gray font; |scaled| values
  3047. |delta_x| and |delta_y| will have been computed so that, in the absence
  3048. of slanting and offsets, the \MF\ coordinates |(min_x,max_y+1)| will correspond
  3049. to the \.{DVI} coordinates $(0,50\,\rm pt)$.
  3050. @p procedure convert(@!x,@!y:scaled);
  3051. begin x:=x+x_offset; y:=y+y_offset;
  3052. dvi_y:=-round(y_ratio*y)+delta_y;
  3053. dvi_x:=round(x_ratio*x+slant_ratio*y)+delta_x;
  3054. @ @<Glob...@>=
  3055. @!x_ratio,@!y_ratio,@!slant_ratio:real; {conversion factors}
  3056. @!unsc_x_ratio,@!unsc_y_ratio,@!unsc_slant_ratio:real;
  3057.   {ditto, times |unity|}
  3058. @!fudge_factor:real; {unconversion factor}
  3059. @!delta_x,@!delta_y:scaled; {magic constants used by |convert|}
  3060. @!dvi_x,@!dvi_y:scaled; {outputs of |convert|, in scaled points}
  3061. @!over_col:scaled; {overflow labels start here}
  3062. @!page_height,page_width:scaled; {size of the current page}
  3063. @ @<Initialize global variables that depend on the font data@>=
  3064. i:=char_info(gray_font)(1);
  3065. if not char_exists(i) then abort('Missing pixel char!');
  3066. @.Missing pixel char@>
  3067. unsc_x_ratio:=char_width(gray_font)(i);
  3068. x_ratio:=unsc_x_ratio/unity;
  3069. unsc_y_ratio:=char_height(gray_font)(height_depth(i));
  3070. y_ratio:=unsc_y_ratio/unity;
  3071. unsc_slant_ratio:=slant(gray_font)*y_ratio;
  3072. slant_ratio:=unsc_slant_ratio/unity;
  3073. if x_ratio*y_ratio=0 then abort('Vanishing pixel size!');
  3074. @.Vanishing pixel size@>
  3075. fudge_factor:=(slant_ratio/x_ratio)/y_ratio;
  3076. @ @<Get ready to convert...@>=
  3077. if pre_min_x<min_x*unity then offset_x:=offset_x+min_x*unity-pre_min_x;
  3078. if pre_max_y>max_y*unity then offset_y:=offset_y+max_y*unity-pre_max_y;
  3079. if pre_max_x>max_x*unity then pre_max_x:=pre_max_x div unity
  3080. else pre_max_x:=max_x;
  3081. if pre_min_y<min_y*unity then pre_min_y:=pre_min_y div unity
  3082. else pre_min_y:=min_y;
  3083. delta_y:=round(unsc_y_ratio*(max_y+1)-y_ratio*offset_y)+3276800;
  3084. delta_x:=round(x_ratio*offset_x-unsc_x_ratio*min_x);
  3085. if slant_ratio>=0 then
  3086.   over_col:=round(unsc_x_ratio*pre_max_x+unsc_slant_ratio*max_y)
  3087. else over_col:=round(unsc_x_ratio*pre_max_x+unsc_slant_ratio*min_y);
  3088. over_col:=over_col+delta_x+10000000;
  3089. page_height:=round(unsc_y_ratio*(max_y+1-pre_min_y))+3276800-offset_y;
  3090. if page_height>max_v then max_v:=page_height;
  3091. page_width:=over_col-10000000
  3092. @ The |dvi_goto| subroutine outputs bytes to the \.{DVI} file that
  3093. will initiate typesetting at given \.{DVI} coordinates, assuming that
  3094. the current position of the \.{DVI} reader is $(0,0)$. This subroutine
  3095. begins by outputting a |push| command; therefore, a |pop| command should
  3096. be given later. That |pop| will restore the \.{DVI} position to $(0,0)$.
  3097. @p procedure dvi_goto(@!x,@!y:scaled);
  3098. begin dvi_out(push);
  3099. if x<>0 then
  3100.   begin dvi_out(right4); dvi_four(x);
  3101.   end;
  3102. if y<>0 then
  3103.   begin dvi_out(down4); dvi_four(y);
  3104.   end;
  3105. @ @<Output the |bop| and the title line@>=
  3106. dvi_out(bop); incr(total_pages); dvi_four(total_pages);
  3107. dvi_four(char_code); dvi_four(ext);
  3108. for k:=3 to 9 do dvi_four(0);
  3109. dvi_four(last_bop); last_bop:=dvi_offset+dvi_ptr-45;@/
  3110. dvi_goto(0,655360); {the top baseline is 10\thinspace pt down}
  3111. if use_logo then
  3112.   begin select_font(logo_font); hbox(small_logo,logo_font,true);
  3113.   end;
  3114. select_font(title_font); hbox(time_stamp,title_font,true);@/
  3115. hbox(page_header,title_font,true); dvi_scaled(total_pages*65536.0);@/
  3116. if (char_code<>0)or(ext<>0) then
  3117.   begin hbox(char_header,title_font,true); dvi_scaled(char_code*65536.0);
  3118.   if ext<>0 then
  3119.     begin hbox(ext_header,title_font,true); dvi_scaled(ext*65536.0);
  3120.     end;
  3121.   end;
  3122. if title_head<>null then
  3123.   begin next[title_tail]:=null;
  3124.   repeat hbox(left_quotes,title_font,true);
  3125.   hbox(info[title_head],title_font,true);
  3126.   hbox(right_quotes,title_font,true);
  3127.   title_head:=next[title_head];
  3128.   until title_head=null;
  3129.   end;
  3130. dvi_out(pop)
  3131. @ @d tol==6554 {one tenth of a point, in \.{DVI} coordinates}
  3132. @<Output all rules for the current character@>=
  3133. if rule_slant<>0 then select_font(slant_font);
  3134. while rule_ptr<>null do
  3135.   begin p:=rule_ptr; rule_ptr:=next[p];@/
  3136.   if rule_size[p]=0 then rule_size[p]:=gray_rule_thickness;
  3137.   if rule_size[p]>0 then
  3138.     begin convert(x0[p],y0[p]); temp_x:=dvi_x; temp_y:=dvi_y;
  3139.     convert(x1[p],y1[p]);
  3140.     if abs(temp_x-dvi_x)<tol then @<Output a vertical rule@>
  3141.     else if abs(temp_y-dvi_y)<tol then @<Output a horizontal rule@>
  3142.     else @<Try to output a diagonal rule@>;
  3143.     end;
  3144.   end
  3145. @ @<Glob...@>=
  3146. @!gray_rule_thickness:scaled; {thickness of rules, according to the gray font}
  3147. @!temp_x,@!temp_y:scaled; {temporary registers for intermediate calculations}
  3148. @ @<Initialize glob...@>=
  3149. gray_rule_thickness:=default_rule_thickness(gray_font);
  3150. if gray_rule_thickness=0 then gray_rule_thickness:=26214; {0.4\thinspace pt}
  3151. @ @<Output a vertical rule@>=
  3152. begin if temp_y>dvi_y then
  3153.   begin k:=temp_y; temp_y:=dvi_y; dvi_y:=k;
  3154.   end;
  3155. dvi_goto(dvi_x-(rule_size[p] div 2), dvi_y);
  3156. dvi_out(put_rule); dvi_four(dvi_y-temp_y); dvi_four(rule_size[p]);
  3157. dvi_out(pop);
  3158. @ @<Output a horizontal rule@>=
  3159. begin if temp_x<dvi_x then
  3160.   begin k:=temp_x; temp_x:=dvi_x; dvi_x:=k;
  3161.   end;
  3162. dvi_goto(dvi_x,dvi_y+(rule_size[p] div 2));
  3163. dvi_out(put_rule); dvi_four(rule_size[p]); dvi_four(temp_x-dvi_x);
  3164. dvi_out(pop);
  3165. @ @<Try to output a diagonal rule@>=
  3166. if (rule_slant=0)or@|
  3167.  (abs(temp_x+rule_slant*(temp_y-dvi_y)-dvi_x)>rule_size[p]) then
  3168.   slant_complaint((dvi_x-temp_x)/(temp_y-dvi_y))
  3169. else  begin if temp_y>dvi_y then
  3170.     begin k:=temp_y; temp_y:=dvi_y; dvi_y:=k;@/
  3171.     k:=temp_x; temp_x:=dvi_x; dvi_x:=k;
  3172.     end;
  3173.   m:=round((dvi_y-temp_y)/slant_unit);
  3174.   if m>0 then
  3175.     begin dvi_goto(dvi_x,dvi_y);
  3176.     q:=((m-1) div slant_n)+1; k:=m div q;
  3177.     p:=m mod q; q:=q-p;
  3178.     @<Vertically typeset |q| copies of character |k|@>;
  3179.     @<Vertically typeset |p| copies of character |k+1|@>;
  3180.     dvi_out(pop);
  3181.     end;
  3182.   end
  3183. @ @<Vertically typeset |q| copies of character |k|@>=
  3184. typeset(k); dy:=round(k*slant_unit); dvi_out(z4); dvi_four(-dy);
  3185. while q>1 do
  3186.   begin typeset(k); dvi_out(z0); decr(q);
  3187.   end
  3188. @ @<Vertically typeset |p| copies of character |k+1|@>=
  3189. if p>0 then
  3190.   begin incr(k); typeset(k);
  3191.   dy:=round(k*slant_unit); dvi_out(z4); dvi_four(-dy);
  3192.   while p>1 do
  3193.     begin typeset(k); dvi_out(z0); decr(p);
  3194.     end;
  3195.   end
  3196. @ Now we come to a more interesting part of the computation, where we
  3197. go through the stored labels and try to fit them in the illustration for
  3198. the current character, together with their associated dots.
  3199. It would simplify font-switching slightly if we were to typeset the labels
  3200. first, but we find it desirable to typeset the dots first and then turn to the
  3201. labels. This procedure makes it possible for us to allow the dots to
  3202. overlap each other without allowing the labels to overlap. After the
  3203. dots are in place, we typeset all prescribed labels, that is, labels with a
  3204. |lab_typ| of |"1".."8"|; these, too, are allowed to overlap the dots and
  3205. each other.
  3206. @<Output all labels for the current character@>=
  3207. overflow_line:=1;
  3208. if label_head<>null then
  3209.   begin next[label_tail]:=null; select_font(gray_font);
  3210.   @<Output all dots@>;
  3211.   @<Find nearest dots, to help in label positioning@>;
  3212.   select_font(label_font);
  3213.   @<Output all prescribed labels@>;
  3214.   @<Output all attachable labels@>;
  3215.   @<Output all overflow labels@>;
  3216.   end
  3217. @ @<Glob...@>=
  3218. @!overflow_line:integer; {the number of labels that didn't fit, plus~1}
  3219. @ A label that appears above its dot is considered to occupy a
  3220. rectangle of height~$h+\Delta$, depth~$d$, and width~$w+2\Delta$, where
  3221. $(h,w,d)$ are the height, width, and depth of the label computed by |hbox|,
  3222. and $\Delta$ is an additional amount of blank space that keeps labels from
  3223. coming too close to each other. (\.{GFtoDVI} arbitrarily defines $\Delta$
  3224. to be one half the width of a space in the label font.) This label is
  3225. centered over its dot, with its baseline $d+h'$ above the center of the dot;
  3226. here $h'=|dot_height|$ is the height of character~0 in the gray font.
  3227. Similarly, a label that appears below its dot is considered to occupy
  3228. a rectangle of height~$h$, depth~$d+\Delta$, and width~$w+2\Delta$; the
  3229. baseline is $h+h'$ below the center of the dot.
  3230. A label at the right of its dot is considered to occupy a rectangle of
  3231. height~$h+\Delta$, depth~$d+\Delta$, and width~$w+\Delta$. Its
  3232. reference point can be found by starting at the center of the dot and
  3233. moving right $w'=|dot_width|$ (i.e., the width of character~0 in the
  3234. gray font), then moving down by half the x-height of the label font.
  3235. A label at the left of its dot is similar.
  3236. A dot is considered to occupy a rectangle of height $2h'$ and width~$2w'$,
  3237. centered on the dot.
  3238. When the label type is |"1"| or more, the labels
  3239. are put into the doubly linked list unconditionally.
  3240.  Otherwise they are put into the list
  3241. only if we can find a way to fit them in without
  3242. overlapping any previously inserted rectangles.
  3243. @<Glob...@>=
  3244. @!delta:scaled; {extra padding to keep labels from being too close}
  3245. @!half_x_height:scaled; {amount to drop baseline of label below the dot center}
  3246. @!thrice_x_height:scaled; {baseline separation for overflow labels}
  3247. @!dot_width,@!dot_height:scaled; {$w'$ and $h'$ in the discussion above}
  3248. @ @<Initialize global variables that depend on the font data@>=
  3249. i:=char_info(gray_font)(0);
  3250. if not char_exists(i) then abort('Missing dot char!');
  3251. @.Missing dot char@>
  3252. dot_width:=char_width(gray_font)(i);
  3253. dot_height:=char_height(gray_font)(height_depth(i));
  3254. delta:=space(label_font) div 2;
  3255. thrice_x_height:=3*x_height(label_font);
  3256. half_x_height:=thrice_x_height div 6;
  3257. @ Here is a subroutine that computes the rectangle boundaries
  3258. |xl[p]|, |xr[p]|, |yt[p]|, |yb[p]|, and the reference point coordinates
  3259. |xx[p]|,~|yy[p]|, for a label that is to be placed above a dot.
  3260. The coordinates of the dot's center are assumed given in |dvi_x|
  3261. and |dvi_y|; the |hbox| subroutine is assumed to have
  3262. already computed the height, width, and depth of the label box.
  3263. @p procedure top_coords(@!p:node_pointer);
  3264. begin xx[p]:=dvi_x-(box_width div 2); xl[p]:=xx[p]-delta;
  3265. xr[p]:=xx[p]+box_width+delta;@/
  3266. yb[p]:=dvi_y-dot_height; yy[p]:=yb[p]-box_depth;
  3267. yt[p]:=yy[p]-box_height-delta;
  3268. @ The other three label positions are handled by similar routines.
  3269. @p procedure bot_coords(@!p:node_pointer);
  3270. begin xx[p]:=dvi_x-(box_width div 2); xl[p]:=xx[p]-delta;
  3271. xr[p]:=xx[p]+box_width+delta;@/
  3272. yt[p]:=dvi_y+dot_height; yy[p]:=yt[p]+box_height;
  3273. yb[p]:=yy[p]+box_depth+delta;
  3274. procedure right_coords(@!p:node_pointer);
  3275. begin xl[p]:=dvi_x+dot_width; xx[p]:=xl[p]; xr[p]:=xx[p]+box_width+delta;@/
  3276. yy[p]:=dvi_y+half_x_height; yb[p]:=yy[p]+box_depth+delta;
  3277. yt[p]:=yy[p]-box_height-delta;
  3278. procedure left_coords(@!p:node_pointer);
  3279. begin xr[p]:=dvi_x-dot_width; xx[p]:=xr[p]-box_width; xl[p]:=xx[p]-delta;@/
  3280. yy[p]:=dvi_y+half_x_height; yb[p]:=yy[p]+box_depth+delta;
  3281. yt[p]:=yy[p]-box_height-delta;
  3282. @ @<Output all dots@>=
  3283. p:=label_head; first_dot:=max_node+1;
  3284. while p<>null do
  3285.   begin convert(xx[p],yy[p]); xx[p]:=dvi_x; yy[p]:=dvi_y;
  3286.   if lab_typ[p]<"5" then
  3287.     @<Enter a dot for label |p| in the rectangle list,
  3288.       and typeset the dot@>;
  3289.   p:=next[p];
  3290.   end
  3291. @ We plant links between dots and their labels by using (or abusing) the
  3292. |xl| and |info| fields, which aren't needed for their normal purposes.
  3293. @d dot_for_label==xl
  3294. @d label_for_dot==info
  3295. @<Enter a dot...@>=
  3296. begin q:=get_avail; dot_for_label[p]:=q; label_for_dot[q]:=p;@/
  3297. xx[q]:=dvi_x; xl[q]:=dvi_x-dot_width; xr[q]:=dvi_x+dot_width;@/
  3298. yy[q]:=dvi_y; yt[q]:=dvi_y-dot_height; yb[q]:=dvi_y+dot_height;@/
  3299. node_ins(q,0);@/
  3300. dvi_goto(xx[q],yy[q]); dvi_out(0); dvi_out(pop);
  3301. @ Prescribed labels are now taken out of the singly linked list and
  3302. inserted into the doubly linked list.
  3303. @<Output all prescribed labels@>=
  3304. q:=end_of_list; {|label_head=next[q]|}
  3305. while next[q]<>null do
  3306.   begin p:=next[q];
  3307.   if lab_typ[p]>"0" then
  3308.     begin next[q]:=next[p];
  3309.     @<Enter a prescribed label for node |p| into the rectangle list,
  3310.       and typeset it@>;
  3311.     end
  3312.   else q:=next[q];
  3313.   end
  3314. @ @<Enter a prescr...@>=
  3315. begin hbox(info[p],label_font,false); {Compute the size of this label}
  3316. dvi_x:=xx[p];  dvi_y:=yy[p];
  3317. if lab_typ[p]<"5" then r:=dot_for_label[p]@+else r:=0;
  3318. case lab_typ[p] of
  3319. "1","5":top_coords(p);
  3320. "2","6":left_coords(p);
  3321. "3","7":right_coords(p);
  3322. "4","8":bot_coords(p);
  3323. end; {no other cases are possible}
  3324. node_ins(p,r);@/
  3325. dvi_goto(xx[p],yy[p]); hbox(info[p],label_font,true); dvi_out(pop);
  3326. @ \.{GFtoDVI}'s algorithm for positioning the ``floating'' labels
  3327. was devised by Arthur~L. Samuel.
  3328. @^Samuel, Arthur Lee@>
  3329. It tries to place labels in a priority order, based on the position of
  3330. the nearest dot to a given dot. If that dot, for example, lies in the first
  3331. octant (i.e., east to northeast of the given dot), the given label will
  3332. be put into the west slot unless that slot is already blocked; then the
  3333. south slot will be tried, etc.
  3334. First we need to compute the octants. We also note if two or more dots
  3335. are nearly coincident, since Samuel's algorithm modifies the priority
  3336. order on that case. The information is temporarily recorded in the |xr| array.
  3337. @d octant==xr {octant code for nearest dot, plus 8 for coincident dots}
  3338. @<Find nearest dots, to help in label positioning@>=
  3339. p:=label_head;
  3340. while p<>null do
  3341.   begin if lab_typ[p]<="0" then
  3342.     @<Compute the octant code for floating label |p|@>;
  3343.   p:=next[p];
  3344.   end;
  3345. @ There's a sneaky way to identify octant numbers, represented by the
  3346. code shown here. (Remember that |y|~coordinates increase downward
  3347. in the \.{DVI} convention.)
  3348. @d first_octant=0
  3349. @d second_octant=1
  3350. @d third_octant=2
  3351. @d fourth_octant=3
  3352. @d fifth_octant=7
  3353. @d sixth_octant=6
  3354. @d seventh_octant=5
  3355. @d eighth_octant=4
  3356. @<Compute the octant code for floating label |p|@>=
  3357. begin r:=dot_for_label[p]; q:=nearest_dot(r,10);
  3358. if twin then octant[p]:=8@+else octant[p]:=0;
  3359. if q<>null then
  3360.   begin dx:=xx[q]-xx[r]; dy:=yy[q]-yy[r];
  3361.   if dy>0 then octant[p]:=octant[p]+4;
  3362.   if dx<0 then incr(octant[p]);
  3363.   if dy>dx then incr(octant[p]);
  3364.   if -dy>dx then incr(octant[p]);
  3365.   end;
  3366. @ A procedure called |place_label| will try to place the remaining
  3367. labels in turn. If it fails, we ``disconnect'' the dot from this
  3368. label so that an unlabeled dot will not appear as a reference in the
  3369. overflow column.
  3370. @<Output all attachable labels@>=
  3371. q:=end_of_list; {now |next[q]=label_head|}
  3372. while next[q]<>null do
  3373.   begin p:=next[q]; r:=next[p]; s:=dot_for_label[p];
  3374.   if place_label(p) then next[q]:=r
  3375.   else  begin label_for_dot[s]:=null; {disconnect the dot}
  3376.     if lab_typ[p]="/" then next[q]:=r {remove label from list}
  3377.     else q:=p; {retain label in list for the overflow column}
  3378.     end;
  3379.   end
  3380. @ Here is the |place_label| routine, which uses the previously computed
  3381. |octant| information as a heuristic. If the label can be placed, it
  3382. is inserted into the rectangle list and typeset.
  3383. @p function place_label(@!p:node_pointer):boolean;
  3384. label exit, found;
  3385. var @!oct:0..15; {octant code}
  3386. @!dfl:node_pointer; {saved value of |dot_for_label[p]|}
  3387. begin hbox(info[p],label_font,false); {Compute the size of this label}
  3388. dvi_x:=xx[p]; dvi_y:=yy[p];
  3389. @<Find non-overlapping coordinates, if possible, and |goto| found;
  3390.   otherwise set |place_label:=false| and |return|@>;
  3391. found:node_ins(p,dfl);@/
  3392. dvi_goto(xx[p],yy[p]); hbox(info[p],label_font,true); dvi_out(pop);
  3393. place_label:=true;
  3394. exit:end;
  3395. @ @<Find non-overlapping coordinates, if possible...@>=
  3396. dfl:=dot_for_label[p]; oct:=octant[p];
  3397. @<Try the first choice for label direction@>;
  3398. @<Try the second choice for label direction@>;
  3399. @<Try the third choice for label direction@>;
  3400. @<Try the fourth choice for label direction@>;
  3401. xx[p]:=dvi_x;  yy[p]:=dvi_y; dot_for_label[p]:=dfl; {no luck; restore the coordinates}
  3402. place_label:=false; return
  3403. @ @<Try the first choice for label direction@>=
  3404. case oct of
  3405. first_octant,eighth_octant,second_octant+8,seventh_octant+8: left_coords(p);
  3406. second_octant,third_octant,first_octant+8,fourth_octant+8: bot_coords(p);
  3407. fourth_octant,fifth_octant,third_octant+8,sixth_octant+8: right_coords(p);
  3408. sixth_octant,seventh_octant,fifth_octant+8,eighth_octant+8: top_coords(p);
  3409. if not overlap(p,dfl) then goto found
  3410. @ @<Try the second choice for label direction@>=
  3411. case oct of
  3412. first_octant,fourth_octant,fifth_octant+8,eighth_octant+8: bot_coords(p);
  3413. second_octant,seventh_octant,third_octant+8,sixth_octant+8: left_coords(p);
  3414. third_octant,sixth_octant,second_octant+8,seventh_octant+8: right_coords(p);
  3415. fifth_octant,eighth_octant,first_octant+8,fourth_octant+8: top_coords(p);
  3416. if not overlap(p,dfl) then goto found
  3417. @ @<Try the third choice for label direction@>=
  3418. case oct of
  3419. first_octant,fourth_octant,sixth_octant+8,seventh_octant+8: top_coords(p);
  3420. second_octant,seventh_octant,fourth_octant+8,fifth_octant+8: right_coords(p);
  3421. third_octant,sixth_octant,first_octant+8,eighth_octant+8: left_coords(p);
  3422. fifth_octant,eighth_octant,second_octant+8,third_octant+8: bot_coords(p);
  3423. if not overlap(p,dfl) then goto found
  3424. @ @<Try the fourth choice for label direction@>=
  3425. case oct of
  3426. first_octant,eighth_octant,first_octant+8,eighth_octant+8: right_coords(p);
  3427. second_octant,third_octant,second_octant+8,third_octant+8: top_coords(p);
  3428. fourth_octant,fifth_octant,fourth_octant+8,fifth_octant+8: left_coords(p);
  3429. sixth_octant,seventh_octant,sixth_octant+8,seventh_octant+8: bot_coords(p);
  3430. if not overlap(p,dfl) then goto found
  3431. @ @<Output all overflow labels@>=
  3432. @<Remove all rectangles from list, except for dots that have labels@>;
  3433. p:=label_head;
  3434. while p<>null do
  3435.   begin @<Typeset an overflow label for |p|@>;
  3436.   p:=next[p];
  3437.   end
  3438. @ When we remove a dot that couldn't be labeled, we set its |next| field
  3439. to the preceding node that survives, so that we can use the |nearest_dot|
  3440. routine later. (This is a bit of a kludge.)
  3441. @<Remove all rectangles from list, except for dots that have labels@>=
  3442. p:=next[0];
  3443. while p<>end_of_list do
  3444.   begin q:=next[p];
  3445.   if (p<first_dot) or (label_for_dot[p]=null) then
  3446.     begin r:=prev[p]; next[r]:=q; prev[q]:=r; next[p]:=r;
  3447.     end;
  3448.   p:=q;
  3449.   end
  3450. @ Now we have to insert |p| into the list temporarily, because of the
  3451. way |nearest_dot| works.
  3452. @<Typeset an overflow label for |p|@>=
  3453. begin r:=next[dot_for_label[p]]; s:=next[r]; t:=next[p];
  3454. next[p]:=s; prev[s]:=p; next[r]:=p; prev[p]:=r;@/
  3455. q:=nearest_dot(p,0);@/
  3456. next[r]:=s; prev[s]:=r; next[p]:=t; {remove |p| again}
  3457. incr(overflow_line);
  3458. dvi_goto(over_col,overflow_line*thrice_x_height+655360);
  3459. hbox(info[p],label_font,true);
  3460. if q<>null then
  3461.   begin hbox(equals_sign,label_font,true);
  3462.   hbox(info[label_for_dot[q]],label_font,true);
  3463.   hbox(plus_sign,label_font,true);
  3464.   dvi_scaled((xx[p]-xx[q])/x_ratio+(yy[p]-yy[q])*fudge_factor);
  3465.   dvi_out(",");
  3466.   dvi_scaled((yy[q]-yy[p])/y_ratio);
  3467.   dvi_out(")");
  3468.   end;
  3469. dvi_out(pop);
  3470. @ @<Adjust the maximum page width@>=
  3471. if overflow_line>1 then page_width:=over_col+10000000;
  3472.   {overflow labels are estimated to occupy $10^7\,$sp}
  3473. if page_width>max_h then max_h:=page_width
  3474. @* Doing the pixels.
  3475. The most interesting part of \.{GFtoDVI} is the way it makes use of a gray
  3476. font to typeset the pixels of a character. In fact, the author must admit having
  3477. great fun devising the algorithms below. Perhaps the reader will also
  3478. enjoy reading them.
  3479. The basic idea will be to use an array of 12-bit integers to represent the next
  3480. twelve rows that need to be typeset. The binary expansions of these integers,
  3481. reading from least significant bit to most significant bit, will represent
  3482. pixels from top to bottom.
  3483. @ We have already used such a binary representation in the tables
  3484. |c[1..120]| and |d[1..120]| of bit patterns and lengths that are potentially
  3485. present in a gray font; we shall now use those tables to compute
  3486. an auxiliary array |b[0..4095]|. Given a 12-bit number~$v$, the gray-font
  3487. character appropriate to $v$'s binary pattern will be~|b[v]|. If no
  3488. character should be typeset for this pattern in the current row,
  3489. |b[v]| will be~0.
  3490. The array |b| can have many different configurations, depending on how
  3491. many characters are actually present in the gray font. But
  3492. it's not difficult to compute |b| by going through the existing characters
  3493. in increasing order and marking all patterns~$x$ to which they apply.
  3494. @<Initialize glob...@>=
  3495. for k:=0 to 4095 do b[k]:=0;
  3496. for k:=font_bc[gray_font] to font_ec[gray_font] do
  3497.  if k>=1 then if k<=120 then
  3498.   if char_exists(char_info(gray_font)(k)) then
  3499.   begin v:=c[k];
  3500.   repeat b[v]:=k; v:=v+d[k];
  3501.   until v>4095;
  3502.   end;
  3503. @ We also compute an auxiliary array |rho[0..4095]| such that $\\{rho}[v]=2^j$
  3504. when |v| is an odd multiple of~$2^j$; we also set $\\{rho}[0]=2^{12}$.
  3505. @<Initialize g...@>=
  3506. for j:=0 to 11 do
  3507.   begin k:=two_to_the[j]; v:=k;
  3508.   repeat rho[v]:=k; v:=v+k+k;
  3509.   until v>4095;
  3510.   end;
  3511. rho[0]:=4096;
  3512. @ @<Glob...@>=
  3513. @!b:array[0..4095] of 0..120; {largest existing character for a given pattern}
  3514. @!rho:array[0..4095] of 1..4096; {the ``ruler function''}
  3515. @ But how will we use these tables? Let's imagine that the \.{DVI} file
  3516. already contains instructions that have selected the gray font and moved
  3517. to the proper horizontal coordinate for the row that we wish to process next.
  3518. Let's suppose that 12-bit patterns have been set up in array~|a|, and that
  3519. the global variables |starting_col| and |finishing_col| are known such
  3520. that |a[j]| is zero unless |starting_col<=j<=finishing_col|. Here's what
  3521. we can do, assuming that appropriate local variables and labels have
  3522. been declared:
  3523. @<Typeset the pixels of the current row@>=
  3524. j:=starting_col;
  3525. loop@+  begin while (j<=finishing_col)and(b[a[j]]=0) do incr(j);
  3526.   if j>finishing_col then goto done;
  3527.   dvi_out(push); @<Move to column |j| in the \.{DVI} output@>;
  3528.   repeat v:=b[a[j]]; a[j]:=a[j]-c[v];
  3529.   k:=j; incr(j);
  3530.   while b[a[j]]=v do
  3531.     begin a[j]:=a[j]-c[v]; incr(j);
  3532.     end;
  3533.   k:=j-k; @<Output the equivalent of |k| copies of character |v|@>;
  3534.   until b[a[j]]=0;
  3535.   dvi_out(pop);
  3536.   end;
  3537. done:
  3538. @ @<Move to column |j| in the \.{DVI} output@>=
  3539. dvi_out(right4);
  3540. dvi_four(round(unsc_x_ratio*j+unsc_slant_ratio*y)+delta_x)
  3541. @ The doubling-up property of gray font character lists is utilized here.
  3542. @<Output the equivalent of |k| copies of character |v|@>=
  3543. reswitch: if k=1 then typeset(v)
  3544. else  begin i:=char_info(gray_font)(v);
  3545.   if char_tag(i)=list_tag then {|v| has a successor}
  3546.     begin if odd(k) then typeset(v);
  3547.     k:=k div 2; v:=qo(rem_byte(i)); goto reswitch;
  3548.     end
  3549.   else repeat typeset(v); decr(k);
  3550.     until k=0;
  3551.   end
  3552. @ @<Glob...@>=
  3553. @!a:array[0..widest_row] of 0..4095; {bit patterns for twelve rows}
  3554. @ In order to use the approach above, we need to be able to initialize
  3555. array~|a|, and we need to be able to keep it up to date as new rows
  3556. scroll by. A moment's thought about the problem reveals that we will either
  3557. have to read an entire character from the \.{GF} file into memory,
  3558. or we'll need to adopt a coroutine-like approach: A single \\{skip}
  3559. command in the \.{GF} file might need to be processed in pieces, since
  3560. it might generate more rows of zeroes than we are ready to absorb
  3561. all at once into~|a|.
  3562. The coroutine method actually turns out to be quite simple, so we shall
  3563. introduce a global variable |blank_rows|, which tells how many rows of
  3564. blanks should be generated before we read the \.{GF} instructions
  3565. for another row.
  3566. @<Glob...@>=
  3567. @!blank_rows:integer;
  3568.   {rows of blanks carried over from a previous \.{GF} command}
  3569. @ Initialization and updating of~|a| can now be handled as follows,
  3570. if we introduce another variable~|l| that is set initially to~1:
  3571. @<Add more rows to |a|, until 12-bit entries are obtained@>=
  3572. repeat @<Put the bits for the next row, times |l|, into |a|@>;
  3573. l:=l+l; decr(y);
  3574. until l=4096;
  3575. @ As before, |cur_gf| will contain the first \.{GF} command that has
  3576. not yet been interpreted.
  3577. @<Put the bits...@>=
  3578. if blank_rows>0 then decr(blank_rows)
  3579. else if cur_gf<>eoc then
  3580.   begin x:=z;
  3581.   if starting_col>x then starting_col:=x;
  3582.   @<Read and process \.{GF} commands until coming to the end of this row@>;
  3583.   end;
  3584. @ @d do_skip==z:=0; paint_black:=false
  3585. @d end_with(#)==begin #; cur_gf:=get_byte; goto done1;@+end
  3586. @d five_cases(#)==#,#+1,#+2,#+3,#+4
  3587. @d eight_cases(#)==#,#+1,#+2,#+3,#+4,#+5,#+6,#+7
  3588. @d thirty_two_cases(#)==eight_cases(#),eight_cases(#+8),
  3589.   eight_cases(#+16), eight_cases(#+24)
  3590. @d sixty_four_cases(#)==thirty_two_cases(#), thirty_two_cases(#+32)
  3591. @<Read and process...@>=
  3592. loop  @+begin continue: case cur_gf of
  3593.   sixty_four_cases(0): k:=cur_gf;
  3594.   paint1:k:=get_byte;
  3595.   paint2:k:=get_two_bytes;
  3596.   paint3:k:=get_three_bytes;
  3597.   eoc:goto done1;
  3598.   skip0:end_with(blank_rows:=0; do_skip);
  3599.   skip1:end_with(blank_rows:=get_byte; do_skip);
  3600.   skip2:end_with(blank_rows:=get_two_bytes; do_skip);
  3601.   skip3:end_with(blank_rows:=get_three_bytes; do_skip);
  3602.   sixty_four_cases(new_row_0),sixty_four_cases(new_row_0+64),
  3603.    thirty_two_cases(new_row_0+128),five_cases(new_row_0+160):
  3604.     end_with(z:=cur_gf-new_row_0;paint_black:=true);
  3605.   xxx1,xxx2,xxx3,xxx4,yyy,no_op:begin skip_nop; goto continue;
  3606.     end;
  3607.   othercases bad_gf('Improper opcode')
  3608.   endcases;@/
  3609.   @<Paint |k| bits and read another command@>;
  3610.   end;
  3611. done1:
  3612. @ @<Paint |k| bits and read another command@>=
  3613. if x+k>finishing_col then finishing_col:=x+k;
  3614. if paint_black then for j:=x to x+k-1 do a[j]:=a[j]+l;
  3615. paint_black:=not paint_black;
  3616. x:=x+k;
  3617. cur_gf:=get_byte
  3618. @ When the current row has been typeset, all entries of |a| will be even;
  3619. we want to divide them by~2 and incorporate a new row with $l=2^{11}$.
  3620. However, if they are all multiples of~4, we actually want to divide by~4
  3621. and incorporate two new rows, with $l=2^{10}$ and $l=2^{11}$. In general,
  3622. we want to divide by the maximum possible power of~2 and add the corresponding
  3623. number of new rows; that's where the |rho|~array comes in handy:
  3624. @<Advance to the next row that needs to be typeset;
  3625.   or |return|, if we're all done@>=
  3626. l:=rho[a[starting_col]];
  3627. for j:=starting_col+1 to finishing_col do if l>rho[a[j]] then l:=rho[a[j]];
  3628. if l=4096 then
  3629.   if cur_gf=eoc then return
  3630.   else  begin y:=y-blank_rows; blank_rows:=0; l:=1;
  3631.     starting_col:=z; finishing_col:=z;
  3632.     end
  3633. else  begin while a[starting_col]=0 do incr(starting_col);
  3634.   while a[finishing_col]=0 do decr(finishing_col);
  3635.   for j:=starting_col to finishing_col do a[j]:=a[j] div l;
  3636.   l:=4096 div l;
  3637.   end
  3638. @ We now have constructed the major components of the necessary routine;
  3639. it simply remains to glue them all together in the proper framework.
  3640. @p procedure do_pixels;
  3641. label done,done1,reswitch,continue,exit;
  3642. var @!paint_black:boolean; {the paint switch}
  3643. @!starting_col,@!finishing_col:0..widest_row; {currently nonzero area}
  3644. @!j:0..widest_row; {for traversing that area}
  3645. @!l:integer; {power of two used to manipulate bit patterns}
  3646. @!i:four_quarters; {character information word}
  3647. @!v:eight_bits; {character corresponding to a pixel pattern}
  3648. begin select_font(gray_font);
  3649. delta_x:=delta_x+round(unsc_x_ratio*min_x);
  3650. for j:=0 to max_x-min_x do a[j]:=0;
  3651. l:=1; z:=0; starting_col:=0; finishing_col:=0; y:=max_y+12; paint_black:=false;
  3652. blank_rows:=0; cur_gf:=get_byte;
  3653. loop@+  begin @<Add more rows...@>;
  3654.   dvi_goto(0,delta_y-round(unsc_y_ratio*y)); @<Typeset the pixels...@>;
  3655.   dvi_out(pop); @<Advance to the next...@>;
  3656.   end;
  3657. exit:end;
  3658. @* The main program.
  3659. Now we are ready to put it all together. This is where \.{GFtoDVI} starts,
  3660. and where it ends.
  3661. @p begin initialize; {get all variables initialized}
  3662. @<Initialize the strings@>;
  3663. start_gf; {open the input and output files}
  3664. @<Process the preamble@>;
  3665. cur_gf:=get_byte; init_str_ptr:=str_ptr;
  3666. loop@+  begin @<Initialize variables for the next character@>;
  3667.   while (cur_gf>=xxx1)and(cur_gf<=no_op) do @<Process a no-op command@>;
  3668.   if cur_gf=post then @<Finish the \.{DVI} file and |goto final_end|@>;
  3669.   if cur_gf<>boc then if cur_gf<>boc1 then abort('Missing boc!');
  3670. @.Missing boc@>
  3671.   @<Process a character@>;
  3672.   cur_gf:=get_byte; str_ptr:=init_str_ptr; pool_ptr:=str_start[str_ptr];
  3673.   end;
  3674. final_end:end.
  3675. @ The main program needs a few global variables in order to do its work.
  3676. @<Glob...@>=
  3677. @!k,@!m,@!p,@!q,@!r,@!s,@!t,@!dx,@!dy:integer; {general purpose registers}
  3678. @!time_stamp:str_number; {the date and time when the input file was made}
  3679. @!use_logo:boolean; {should \MF's logo be put on the title line?}
  3680. @ \MF\ sets the opening string to 32 bytes that give date and time as follows:
  3681. $$\hbox{|' METAFONT output yyyy.mm.dd:tttt'|}$$
  3682. We copy this to the \.{DVI} file, but remove the `\.{METAFONT}' part so that
  3683. it can be replaced by its proper logo.
  3684. @<Process the preamble@>=
  3685. if get_byte<>pre then bad_gf('No preamble');
  3686. @.No preamble@>
  3687. if get_byte<>gf_id_byte then bad_gf('Wrong ID');
  3688. @.Wrong ID@>
  3689. k:=get_byte; {|k| is the length of the initial string to be copied}
  3690. for m:=1 to k do append_char(get_byte);
  3691. dvi_out(pre); dvi_out(dvi_id_byte); {output the preamble}
  3692. dvi_four(25400000); dvi_four(473628672); {conversion ratio for sp}
  3693. dvi_four(1000); {magnification factor}
  3694. dvi_out(k); use_logo:=false; s:=str_start[str_ptr];
  3695. for m:=1 to k do dvi_out(str_pool[s+m-1]);
  3696. if str_pool[s]=" " then
  3697.  if str_pool[s+1]="M" then
  3698.   if str_pool[s+2]="E" then
  3699.    if str_pool[s+3]="T" then
  3700.     if str_pool[s+4]="A" then
  3701.      if str_pool[s+5]="F" then
  3702.       if str_pool[s+6]="O" then
  3703.        if str_pool[s+7]="N" then
  3704.         if str_pool[s+8]="T" then
  3705.     begin incr(str_ptr); str_start[str_ptr]:=s+9; use_logo:=true;
  3706.     end; {we will substitute `\MF' for \.{METAFONT}}
  3707. time_stamp:=make_string
  3708. @* System-dependent changes.
  3709. This section should be replaced, if necessary, by changes to the program
  3710. that are necessary to make \.{GFtoDVI} work at a particular installation.
  3711. It is usually best to design your change file so that all changes to
  3712. previous sections preserve the section numbering; then everybody's version
  3713. will be consistent with the printed program. More extensive changes,
  3714. which introduce new sections, can be inserted here; then only the index
  3715. itself will get a new section number.
  3716. @^system dependencies@>
  3717. @* Index.
  3718. Here is a list of the section numbers where each identifier is used.
  3719. Cross references to error messages and a few other tidbits of information
  3720. also appear.
  3721.