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