DVI Driver Family Update #19 [23-Nov-88] ============ INTRODUCTION ============ This issue is somewhat different than previous ones, in that it asks for some user feedback on ideas presented here, rather than reporting bugs and announcing new drivers and new ports. ================================ PAPER HANDLING AND SPECIFICATION ================================ I have now made considerable progress toward resolving the question of paper handling for the next release of the DVI drivers (2.11). This involved intensive work this past weekend, with the production of 1264 lines of C code to implement and test the ideas, and the verification of the correct functioning of that code with 6 different compilers on 4 different operating systems. Because this is new, I am certain to have overlooked some important considerations, and so I ask for your comments. I am trying to design something that will be suitable not only for my DVI driver family, but that can also be used in my work on the TUG DVI standards committee. Since the code will be in the public domain, other DVI driver developers will be free to use the code too without restriction. I feel that paper handling is a complex issue, and cannot be satisfactorily solved by simple means. I've therefore designed a minilanguage to specify paper characteristics, with the notion that drivers will read startup files that provide such specifications; they could also have common paper types compiled in. However, I want to get away from having paper dimensions, orientation, stacking order, etc. inflexibly specified in the code at compile time, as is currently the case. The remainder of this issue therefore consists of the complete leading comments of paper.c which gets into the details, followed by paper.dat, which contains specifications for over a score of paper sizes, with samples showing how peculiarities of individual printers might be handled. If you know of other paper types, or find errors, please inform me. When paper.dat eventually becomes a startup configuration file, its format may change slightly, such as the insertion of "-paper:" in front of every open curly brace. ------------------------------------------------------------------------ paper.c comment header: /*********************************************************************** Paper handling and specification is a complex issue, and may require future extensions. Thus, it is desirable to have a flexible means of specifying paper characteristics, and a reasonable scheme seems to be to have the -paper switch take as an argument a small program in a minilanguage that contains a compound statement with embedded simple assignment statements. The variables to which values are assigned are given in the form_record structure, and the symbol_table[] array; those two variables, plus the bodies of copy_form(), find_form(), init_form(), and print_form() need to be modified to add support for new ones. The -paper switch should be able to both select a pre-defined paper type, and define a new paper type. Usually, the latter usage will appear only in startup files. An example of command-line selection of paper type might be -paper:letter A definition of paper characteristics might be compactly specified as -paper:{paper="letter";width=8.5in;height=11in;dev_init="...";} or more readably, as -paper: { paper = "letter"; % standard US paper size width = 8.5in; height = 11in; x_origin = 1.05in; % printer origin is off by 0.05in y_origin = 1in; x_clip = 1; % printer wraps coordinates, so y_clip = 1; % we need clipping turned on x_left = 0.3in; % not all of page is imageable x_right = 0.3in; y_top = 0.5in; y_bottom = 0.5in; output_order = -1; % print pages from last to first dev_init = "...." % adjacent strings are concatenated "...." "...."; dev_term = "\f\033E"; % final formfeed and printer reset } Comments are from percent to end-of-line (like TeX), and letter case is not significant in variable names. Whitespace is ignored, so the specification can be formatted for readability, or for compactness. Dimensions can be given in any unit known to TeX (bp cc cm dd in mm pc pt sp). The presence of a left brace following the paper switch signals that a forms definition follows; otherwise, the following token is a paper name. To facilitate collection of the complete specification at a higher level without having to parse it in detail, braces must be balanced; escape sequences and comments provide ways to ensure this. UNIX supports multiline arguments, so the paper specification could come on the command line; most other systems do not, but the startup files provide the facility. The variables that can be specified in the language are as follows: ---- ---- ---------------------------------------- name type value ---- ---- ---------------------------------------- paper string standard form name (e.g. "A4", "US-legal") use string name of form to copy values from dev_init string device initialization string dev_term string device termination string height dimension physical paper height output_order number negative value means print in reverse order width dimension physical paper width x_origin dimension offset of TeX (0,0) point from left edge y_origin dimension offset of TeX (0,0) point from top edge x_left dimension width of unprintable region on left edge x_right dimension width of unprintable region on right edge y_top dimension width of unprintable region on top edge y_bottom dimension width of unprintable region on bottom edge x_clip number non-zero means x clipping enabled y_clip number non-zero means y clipping enabled ---- ---- ---------------------------------------- The PAPER variable must always be given, since it is the key into the paper_table[] array, and its values represent the legal set of -paper:xxx switches. If it is omitted, then the accumulated variables will silently be discarded, since no acceptable entry in paper_table[] will have been found. The paper_table[] array is expanded dynamically to handle any number of entries. Existing paper_table[] entries can be modified by later programs, making it convenient to maintain a base file containing standard paper definitions that are later modified to specify additional peculiarities of particular printers. The USE variable requests copying parameters from an already-existing form. Such copying happens BEFORE any other parameters from the current program are copied, and that is done AFTER the complete program has been successfully parsed. Thus, only the last USE parameter given in a program is effective. This makes it easy to prepare modifications of base forms. For example, most laser printers use the same size paper, but differ in the imageable area and output stacking order. Programs like { paper = "ALW-note"; use = "letter"; x_left = 0.41in; x_right = 0.41in; y_top = 0.42in; y_bottom = 0.42in; } { paper = "ALW-letter"; use = "letter"; x_left = 0.25in; x_right = 0.25in; y_top = 0.04in; y_bottom = 0.04in; } { paper = "ALW-legal"; use = "US-legal"; x_left = 0.89in; x_right = 0.89in; y_top = 0.5in; y_bottom = 0.5in; } would describe the three paper types note, letter, and legal known to the Apple LaserWriter. The DEV_INIT and DEV_TERM strings supply information that informs the printer about the paper types; the strings will be sent at the beginning and end of the output. In the case of PostScript devices, which have macro definitions downloaded before the printing commands, the device initialization string will come between the two. Generally, only expensive high-performance printers offer facilities these strings can take advantage of, so for most applications, they need not be specified. The internal token buffer expands dynamically to accommodate long strings, so there is no limit, other than total available memory, on the size of these strings. By decree of the Stanford TeX Project, (X_ORIGIN,Y_ORIGIN) = (1in,1in) for a DVI driver, and all standard macro packages (LaTeX, SliTeX, AMSTeX, Plain TeX) assume this. In rare circumstances, it may be desirable to change it. The HEIGHT and WIDTH values define the physical page dimensions. The variables X_LEFT, X_RIGHT, Y_TOP, and Y_BOTTOM measure unprintable regions in the margins; for example, many laser printers cannot print closer than about 0.3in from the paper edges. These values are used when X_CLIP or Y_CLIP is selected. For devices which must be sent a page bitmap, the dimensions of the printable region define the size of the page bitmap, which is allocated dynamically by the DVI drivers. For high-resolution printers on machines with limited memory, the page bitmap requirements can be large, and the availability of these parameters in a configuration file, instead of as hardcoded values in the compiled program, should facilitate tuning memory usage. Although the page printing order is already a run-time selectable option, there are now several models of Hewlett-Packard LaserJet printers, and clones, with different paper stacking order, The OUTPUT_ORDER option makes it convenient to choose the order as part of the paper definition. The clipping actions implemented with X_CLIP or Y_CLIP are non-zero save unnecessary transmission of off-page characters to the printer, and prevent unpleasant side effects, such as coordinate wrap on some printers (e.g. Hewlett-Packard LaserJet Plus and Series II). For most applications, clipping should be enabled. The grammar for the minilanguage is based on the C language grammar given in Appendix B of @Book{Harbison:carm-2, author = "Samuel P. Harbison and Guy L. {Steele Jr.}", title = "C---A Reference Manual", publisher = "Prentice-Hall", year = 1987, edition = "Second", } with changes affecting hexadecimal escape sequences in strings, and concatenation of adjacent strings, as specified in the January 1988 draft ANSI C standard. Adjacent string concatenation is a convenient way of working around limitations on line length when long strings are needed, and adding support for it took only 4 lines of code. Hexadecimal escape sequences of arbitrary length permit transparent support for character sizes larger than 8 bits. Octal escape sequences remain limited to 3 digits (for backward compatibility; hexadecimal escape sequences are new with the draft ANSI C standard). In the following grammar, the suffix -opt means that the item is optional. Numeric constants are not specified in grammatical form. They are parsed by the ANSI standard library routine, strtod(), which expects numbers in the form ([] marks optional fields, {|} marks alternatives): [whitespace][sign][digits][. digits][{e|E}[sign]digits] Except in quoted strings, tokens may not contain embedded blanks. Thus, 210mm is legal input, but 210 mm is not. Here finally is the grammar parsed by paper(), which expects a program as its argument: program: statement statement: assignment-statement compound-statement null-statement assignment-statement: name = constant ; compound-statement: { statement-list-opt } null-statement: ; statement-list: statement statement-list statement constant: dimension-constant float-constant string-constant dimension-constant: float-constant dimension-unit dimension-unit: one of bp cc cm dd in mm pc pt sp string-constant: simple-string-constant string-constant simple-string-constant simple-string-constant: " character-sequence-opt " character-sequence: character character-sequence character character: printing-character escape-character printing-character: one of (note that " and \ are omitted, and ' may be specified by \' as well) ! # $ % & ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ escape-character: \ escape-code escape-code: character-escape-code octal-escape-code hexadecimal-escape-code character-escape-code: a b f n r t v \ ' " octal-escape-code: octal-digit octal-digit octal-digit octal-digit octal-digit octal-digit hexadecimal-escape-code: x hexadecimal-digit hexadecimal-escape-code hexadecimal-digit octal-digit: one of 0 1 2 3 4 5 6 7 hexadecimal-digit: one of 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f name: letter-sequence letter-sequence: letter letter-sequence letter letter: one of alphabetic or underscore characters A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z _ The code below uses private objects yylex(), yypeek(), yyerrors, yyleng, yypending, yytoken, and yytype, by analogy with the UNIX lexical analyzer generator, lex . However, in the interests of wide portability, lex and yacc (the UNIX parser generator) are rejected in favor of a hand-coded recursive descent parser, with lexical analysis implemented in next_token(), and accessed by calls to yylex() and yypeek(). Most of the functions defined here are declared static, so that they are known only within this file. The public ones available outside are find_form(const char* formname) Find the index of a form in paper_table[]. If the form does not already exist, the index of the first empty slot will be returned. The table is automatically expanded as necessary. paper(const char* pgm) Parse a paper specification program. print_form(FILE* fp, form_record* ppt) Print the fields of a single form. [22-Nov-88] ***********************************************************************/ ------------------------------------------------------------------------ paper.dat: % This is the master paper characteristics definition file for the DVI % driver family. It defines all standard US, British, and ISO paper % types that I have been able to find, plus several others. % [21-Nov-88] % ---------------------------------------------------------------------- % British paper sizes (some also used in USA): { paper = "Octavo"; height = 8in; width = 5in; } { paper = "Sixmo"; height = 8in; width = 6.5in; } { paper = "Quarto"; height = 10in; width = 8in; } { paper = "Letter"; height = 11in; width = 8.5in; } { paper = "Foolscap"; height = 13in; width = 8in; } { paper = "Government-legal"; use = "Foolscap"; } { paper = "Folio"; height = 13in; width = 8.3in; } { paper = "Legal"; height = 13in; width = 8.5in; } { paper = "US-legal"; height = 14in; width = 8.5in; } { paper = "Computer-1411"; height = 11in; width = 14in; } % ---------------------------------------------------------------------- % ANSI (note that B folded in half becomes A, etc.): { paper = "A"; % (216mm x 279mm) height = 11in; width = 8.5in; } { paper = "B"; % (279mm x 432mm) height = 17in; width = 11in; } { paper = "C"; % (432mm x 559mm) height = 22in; width = 17in; } { paper = "D"; % (559mm x 864mm) height = 34in; width = 22in; } { paper = "E"; % (864mm x 1118mm) height = 44in; width = 34in; } % ---------------------------------------------------------------------- % ISO sizes. Note that Xn folded in half becomes Xn+1 (X = A, B, C) % X0 base sizes taken from pp. 165--169 of % @Book{White:design, % author = "Jan V. White", % title = "Graphic Design for the Electronic Age", % publisher = "Watson-Guptill Publications", % year = "1988", % ISBN = "0-8230-2122-X", % } % and converted automatically by gensiz.c % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % ISO standard paper A-series (portrait) % { paper = "A0"; % (33.11w x 46.81h in) height = 1189mm; width = 841mm; } { paper = "A1"; % (23.41w x 33.11h in) height = 841mm; width = 594mm; } { paper = "A2"; % (16.56w x 23.41h in) height = 594mm; width = 420mm; } { paper = "A3"; % (11.71w x 16.56h in) height = 420mm; width = 297mm; } { paper = "A4"; % (8.28w x 11.71h in) height = 297mm; width = 210mm; } { paper = "A5"; % (5.85w x 8.28h in) height = 210mm; width = 148mm; } { paper = "A6"; % (4.14w x 5.85h in) height = 148mm; width = 105mm; } { paper = "A7"; % (2.93w x 4.14h in) height = 105mm; width = 74mm; } { paper = "A8"; % (2.07w x 2.93h in) height = 74mm; width = 52mm; } { paper = "A9"; % (1.46w x 2.07h in) height = 52mm; width = 37mm; } { paper = "A10"; % (1.03w x 1.46h in) height = 37mm; width = 26mm; } % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % ISO standard paper A-series (landscape) % { paper = "A0L"; % (46.81w x 33.11h in) height = 841mm; width = 1189mm; } { paper = "A1L"; % (33.11w x 23.41h in) height = 594mm; width = 841mm; } { paper = "A2L"; % (23.41w x 16.56h in) height = 420mm; width = 594mm; } { paper = "A3L"; % (16.56w x 11.71h in) height = 297mm; width = 420mm; } { paper = "A4L"; % (11.71w x 8.28h in) height = 210mm; width = 297mm; } { paper = "A5L"; % (8.28w x 5.85h in) height = 148mm; width = 210mm; } { paper = "A6L"; % (5.85w x 4.14h in) height = 105mm; width = 148mm; } { paper = "A7L"; % (4.14w x 2.93h in) height = 74mm; width = 105mm; } { paper = "A8L"; % (2.93w x 2.07h in) height = 52mm; width = 74mm; } { paper = "A9L"; % (2.07w x 1.46h in) height = 37mm; width = 52mm; } { paper = "A10L"; % (1.46w x 1.03h in) height = 26mm; width = 37mm; } % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % ISO intermediate paper B-series (portrait) % { paper = "B0"; % (39.37w x 55.67h in) height = 1414mm; width = 1000mm; } { paper = "B1"; % (27.84w x 39.37h in) height = 1000mm; width = 707mm; } { paper = "B2"; % (19.69w x 27.84h in) height = 707mm; width = 500mm; } { paper = "B3"; % (13.92w x 19.69h in) height = 500mm; width = 353mm; } { paper = "B4"; % (9.84w x 13.92h in) height = 353mm; width = 250mm; } { paper = "B5"; % (6.96w x 9.84h in) height = 250mm; width = 176mm; } { paper = "B6"; % (4.92w x 6.96h in) height = 176mm; width = 125mm; } % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % ISO intermediate paper B-series (landscape) % { paper = "B0L"; % (55.67w x 39.37h in) height = 1000mm; width = 1414mm; } { paper = "B1L"; % (39.37w x 27.84h in) height = 707mm; width = 1000mm; } { paper = "B2L"; % (27.84w x 19.69h in) height = 500mm; width = 707mm; } { paper = "B3L"; % (19.69w x 13.92h in) height = 353mm; width = 500mm; } { paper = "B4L"; % (13.92w x 9.84h in) height = 250mm; width = 353mm; } { paper = "B5L"; % (9.84w x 6.96h in) height = 176mm; width = 250mm; } { paper = "B6L"; % (6.96w x 4.92h in) height = 125mm; width = 176mm; } % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % % ISO envelopes for A-series % { paper = "C0"; % (50.94w x 36.06h in) height = 916mm; width = 1294mm; } { paper = "C1"; % (36.06w x 25.50h in) height = 647mm; width = 916mm; } { paper = "C2"; % (25.50w x 18.03h in) height = 458mm; width = 647mm; } { paper = "C3"; % (18.03w x 12.75h in) height = 323mm; width = 458mm; } { paper = "C4"; % (12.75w x 9.02h in) height = 229mm; width = 323mm; } { paper = "C5"; % (9.02w x 6.38h in) height = 161mm; width = 229mm; } { paper = "C6"; % (6.38w x 4.51h in) height = 114mm; width = 161mm; } % ---------------------------------------------------------------------- % Miscellaneous others for testing purposes. { paper = "ALW-note"; use = "letter"; x_left = 0.41in; x_right = 0.41in; y_top = 0.42in; y_bottom = 0.42in; } { paper = "ALW-letter"; use = "letter"; x_left = 0.25in; x_right = 0.25in; y_top = 0.04in; y_bottom = 0.04in; } { paper = "ALW-legal"; use = "US-legal"; x_left = 0.89in; x_right = 0.89in; y_top = 0.5in; y_bottom = 0.5in; } ------------------------------------------------------------------------ =============================THE END=============================