%%% ==================================================================== %%% @METAFONT-file{ %%% author = "Alan Jeffrey", %%% version = "1.1", %%% date = "02 June 1992", %%% time = "13:36:35 BST", %%% filename = "diagramf.mf", %%% address = "School of Cognitive and Computing Sciences %%% University of Sussex %%% Brighton BN1 9QH %%% UK", %%% telephone = "+44 273 606755 x 3238", %%% FAX = "+44 273 678188", %%% checksum = "49217 319 1584 10327", %%% email = "alanje@cogs.sussex.ac.uk", %%% codetable = "ISO/ASCII", %%% keywords = "diagrams, metafont", %%% supported = "yes", %%% abstract = "This is a metafont program which provides %%% commands for setting labels in TeX.", %%% docstring = "This is part of the diagramf package which %%% interfaces TeX and metafont. It is %%% described in diagramf.tex. %%% %%% Copyright 1992 Alan Jeffrey. %%% %%% The checksum field above contains a CRC-16 %%% checksum as the first value, followed by the %%% equivalent of the standard UNIX wc (word %%% count) utility output of lines, words, and %%% characters. This is produced by Robert %%% Solovay's checksum utility.", %%% package = "diagramf", %%% dependencies = "diagramf.sty", %%% maintainer = "Jeremy Gibbons", %%% address-maintainer = "Department of Computer Science %%% University of Aukland %%% Private Bag %%% Aukland %%% New Zealand", %%% email-maintainer = "jeremy@cs.aukuni.ac.nz", %%% } %%% ==================================================================== %%% %%% 25 Oct 1990, v1.0: Released version 1.0. %%% %%% 2 Jun 1992, v1.1: Added standard headers. diagramfbaseloaded := 1; % This is a metafont program for describing diagrams with TeX labels % on them. The mf code is of the form: % % begindiagram (NUMBER,WIDTH,HEIGHT,DEPTH); % hboxes (LISTOFBOXES); % ... % enddiagram; % % where NUMBER is the diagram number and LISTOFBOXES is a list of the % labels used in that diagram. The fancy thing is that characters can % contain the variables % % hboxSOMETHING[N] % % where N is a number and SOMETHING is one of bl, l, tl, br, r, tr, wd, % ht and dp. These represent the dimensions of a label which will % later on be put down by TeX, for example % % hboxbl3 --- the bottom left coordinate of the third label, % hboxr7 --- the right-hand baseline of the seventh label, % hboxht9 --- the height of the ninth label, % % and so on. You can then specify the contents of a label by saying % % setbox NUMBER "SOME", "TEX", "CODE"; % % for example % % setbox3 "Fred"; % setbox7 "$\begin{array}{c}", % "a\\b\\c", % "\end{array}$"; % % the comma-separated version is useful for labels more than one line % long. % % NB: Because of the way diagrams are implemented in LaTeX, it's a % {\em very bad idea\/} for labels to contain \diagramfile's. % % Your TeX file then says % % \diagramfile{FILENAME} % \diagramf{NUMBER} % % where FILENAME is the name of the mf file, and NUMBER is the diagram % number. It's a good idea not to have too many diagrams per file % (like more than about 50 or so) because TeX has to use up one box per % diagram. % % This all works by providing an interface between TeX and MF... MF % reads in a file JOBNAME.dim containing the dimensions of the TeX % labels and writes out a file JOBNAME.dia containing the TeX labels % and where they should be positioned. TeX then reads in the .dia % file and writes the .dim file. % % So the production cycle for a document containing diagrams is % % 1) Create an empty .dim file (because bloody MF can't tell % whether a file exists or not grumble grumble grumble...) % 2) Run MF to create the .dia file containing the labels, % 3) Run TeX to set the labels and find their dimensions, % 4) Run MF to create the final version of the diagram, now that we % know what size the labels are, and % 5) Run TeX to produce the document. % % A sample .dim file is % % wd#[2][0] := 20.3344pt#; % ht#[2][0] := 6.94444pt#; % dp#[2][0] := 1.94444pt#; % % which defines the size of the zeroth label of the second % diagram---it's width is 20.3344pt, height 6.94444pt and depth % 1.94444pt. % % A sample .dia file is (almost) % % \newdiagramfont{example} % \newdiagram{2} % \diagramlabel{0}{4.88908pt}{0pt} % $g \circ h$ % \enddiagramlabel % \diagramchar{2} % \endnewdiagram % % (The `almost' is because actually all the lines end with the comment % `% diagramf' to flag them.) % % This means that the diagram font is called % example, and diagram 2 contains label 0 at coordiates % (4.88908pt,0pt) which consists of the text $g \circ h$. % % That's enough interfaces, Ed. % % To begin with, we need to declare the variables used in the .dim % file. numeric wd#[][], ht#[][], dp#[][]; % Then we input the .dim file. scantokens ("input " & jobname & ".dim"); % Right, now we define the macros for writing the .dia file. Metafont % contains no (count 'em---none) primitives for file handling, except % for writing information out on the .log file. So we'll write the % .dia file to the .log file with tags saying `% diagramf'. You can then % use an incantation like % % grep "% diagramf" blah.log > blah.dia % % to recover the .dia file. This is a right pain! But there's no % other real way to do it---see Section 7 of Appendix D of the MFbook % for a similar hack by DEK. % % So to produce the TeX output % % blah% diagramf % waffle% diagramf % % you say % % texoutput "blah", "waffle"; % % which just produces the right messages. def texoutput text t = for s = t: message s & "% diagramf"; endfor message "" enddef; % So to begin with, we'll produce a header message which contains the % filename, the date, and the name of the font we're producing. string monthname[]; monthname[1] = "Jan"; monthname[2] = "Feb"; monthname[3] = "Mar"; monthname[4] = "Apr"; monthname[5] = "May"; monthname[6] = "Jun"; monthname[7] = "Jul"; monthname[8] = "Aug"; monthname[9] = "Sep"; monthname[10] = "Oct"; monthname[11] = "Nov"; monthname[12] = "Dec"; string today; today = decimal day & " " & monthname[month] & " " & decimal year; texoutput "% Filename: " & jobname & ".dia ", "% Generated by: diagramf.mf ", "% Date: " & today & " ", "\newdiagramfont{" & jobname & "}"; % To convert a coordinate (36pt,5.2pt) into a string "{36pt}{5.2pt}" % you use coordinate: def coordinate expr z = "{" & decimal (xpart z/hppp) & "pt}{" & decimal (ypart z/hppp) & "pt}" enddef; % We can now define the macros used in preparing diagrams. To begin % with, begindiagram... enddiagram. % % This sets variables % % diagram --- the number of the diagram, % character --- the number of the character produced (at the moment % this is just the same as the diagram number, but this may % change soon...) % hboxwd[], hboxht[], hboxdp[] --- the dimensions of the box, and % hboxl[] --- the left end of the box. % % It also produces the output \newdiagram{DIAGRAM} and does a % beginchar. % % We read in the dimensions of the character as a text parameter to % make sure they aren't evaluated until {\em after\/} diagram has been % set. This means you can use hboxwd#, hboxht# and hboxdp# in a % begindiagram and all will be well. def begindiagram (expr n) (text t) = begingroup; diagram:=n; character:=n; numeric hboxwd[], hboxht[], hboxdp[]; pair hboxl[]; texoutput "\newdiagram{" & decimal diagram & "}"; beginchar (character) (t) enddef; % enddiagram just closes down all the groups and outputs the % \diagramchar and \endnewdiagram TeX macros. def enddiagram = endchar; texoutput "\diagramchar{" & decimal character & "}"; texoutput "\endnewdiagram"; endgroup enddef; % Then the other coordinates of the box are vardefs based on hboxl@#, vardef hboxtl@# = hboxl@# + (0, hboxht@#) enddef; vardef hboxtr@# = hboxl@# + (hboxwd@#, hboxht@#) enddef; vardef hboxr@# = hboxl@# + (hboxwd@#, 0) enddef; vardef hboxbr@# = hboxl@# + (hboxwd@#, -hboxdp@#) enddef; vardef hboxbl@# = hboxl@# + (0, -hboxdp@#) enddef; % and the sharp dimensions of the boxes. vardef hboxwd#.@# = if unknown wd#[diagram]@#: eps else: wd#[diagram]@# fi enddef; vardef hboxht#.@# = if unknown ht#[diagram]@#: eps else: ht#[diagram]@# fi enddef; vardef hboxdp#.@# = if unknown dp#[diagram]@#: eps else: dp#[diagram]@# fi enddef; % Then hboxes (sigma) sets the constraints on all the hboxes from % sigma. For example, hboxes (1,2,3) sets up hbox1, hbox2 and hbox3. def hboxes (text t) = for n = t: hboxwd[n] = hboxwd#[n] * hppp; hboxht[n] = hboxht#[n] * hppp; hboxdp[n] = hboxdp#[n] * hppp; endfor enddef; % We can then set a box by outputting the TeX code for it. If % proofing is set, we draw a box to show where the label goes. vardef setbox@# text t = texoutput "\diagramlabel{" & decimal @# & "}" & coordinate hboxl@#, t, "\enddiagramlabel"; if proofing=2: prooflabel@# fi enddef; % If we're in a proofing mode, we'll draw the label with a .25pt % pen. vardef prooflabel@# = begingroup; localpen; pickup pencircle scaled .25pt; draw hboxbl@# -- hboxtl@# -- hboxtr@# -- hboxbr@# -- cycle; draw hboxl@# -- hboxr@#; endgroup enddef; % Where localpen provides local variables for all the pen values. def localpen = interim pen_lft:=0; interim pen_rt:=0; interim pen_top:=0; interim pen_bot:=0; if known currentbreadth: interim currentbreadth:=0; fi save currentpen, currentpen_path; pen currentpen; path currentpen_path; enddef;