diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex209/contrib/textyl |
Initial commit
Diffstat (limited to 'macros/latex209/contrib/textyl')
109 files changed, 27427 insertions, 0 deletions
diff --git a/macros/latex209/contrib/textyl/README b/macros/latex209/contrib/textyl/README new file mode 100644 index 0000000000..659d399050 --- /dev/null +++ b/macros/latex209/contrib/textyl/README @@ -0,0 +1,84 @@ + + +This is TeXtyl, a post-processor for TeX, which +allows you to typeset graphic line-drawings in +a device-independent manner. It makes use of the \special +facility of TeX to insert commands into the original + .DVI file produced by TeX, and post-processes that +file, producing another .DVI file for spooling to +your favorite printer. + +TeXtyl is written in Pascal because of portability +requirements while under development at Ohio State. For that +reason, the main portion is one monolithic file, with hooks +into Unix (in a manner similar to that of "dvitype"). The +original TeXtyl has/had the ability to typeset musical beams. +The enclosed version does not have that ability for reasons of +space and utility. If you feel that you really need it, write +to me at the address below. Positive suggestions and +ideas for improvements are welcomed, as are actual +improvements to the code. + +Also included is the TeXtyl manual, describing +how to use TeXtyl. It is a LaTeX document, using +TeXtyl-commands for examples. It is also available +as a technical report from Ohio State University's +Computer & Information Sciences Dept. at +1036 Neil Avenue, Columbus, OH 43210. +TR #OSU-CISRC-4/87-TR9. The current version has the +added flexiblity of patterned lines, which is not +reflected in the OSU report. + +Finally, in a subsequent posting, are the vector fonts +for actually typesetting the graphic figures. Although +given at a 300dpi resolution, the fonts were created +for device-independence. The file "vecbase.mf" is +included, but has not been translated to the newer +version of Metafont. See the TeXtyl manual for +implementation details of the vector fonts. + +This posting comes in several pieces. The directory +stucture currently looks like: +./TeXtyl +README doc/ src/ vecfonts/ + +./TeXtyl/doc: +Makefile TYLMAN.02 TYLMAN.05 TYLMAN.08 TYLMAN.11 +TYLMAN.00 TYLMAN.03 TYLMAN.06 TYLMAN.09 TYLMAN.12 +TYLMAN.01 TYLMAN.04 TYLMAN.07 TYLMAN.10 TYLMAN.13 +textyl.tex + +./TeXtyl/src: +h00vars.h textyl.pas.aa textyl.pas.ad textyl.pas.ag +makefile textyl.pas.ab textyl.pas.ae textyl.pas.ah +texpaths.h textyl.pas.ac textyl.pas.af tylext.c tylext.h + +./TeXtyl/vecfonts: +vecfonts.shar.aa vecfonts.shar.ab +vecfonts.shar.ac vecfonts.shar.ad + + +NOTICES: +TeXtyl was written by John Renner between 1984-1987 +while at the Ohio State University, and elsewhere/when. +These files and the TeXtyl system are Copyright (c) 1987 by +John S. Renner, All rights reserved. You may +freely use this program, as long as you do no +sell it (nor any derivatives of it), +and as long as I receive a copy of all modifications. +This copyright notice must stay intact and accompany +the TeXtyl sources and manual. + +The program, TeXtyl, and the vector fonts were +derived either independently or from sources noted +in the TeXtyl manual. There is absolutely NO relationship +between this work and the work done by Adobe Systems, Inc., +as TeXtyl was written entirely and independently by +John Renner prior to association with that company. + +Current Address: John Renner + 100 N Whisman #211 + Mountain View, CA 94043 + + adobe!renner@decwrl.dec.com + diff --git a/macros/latex209/contrib/textyl/README.27aug91 b/macros/latex209/contrib/textyl/README.27aug91 new file mode 100644 index 0000000000..11208d832c --- /dev/null +++ b/macros/latex209/contrib/textyl/README.27aug91 @@ -0,0 +1,29 @@ +This is a beta test version of a C port of Renner's TeXtyl, done using +Dave Gillespie's p2c and some manual touchup. I hope users will report +problems they encounter with getting it working it on various systems +so that I can improve the portability of this code. + +There are a couple of differences in usage from the manual. This +version takes arguments from the command line this way: + + textyl dvi-in dvi-out + +Messages are sent to standard output. No tlog file is generated. + +To compile for your machine, edit the font path in defs.h (DEFTEXFONTS) +before doing a make. If the environment variable TEXFONTS is defined at +runtime, textyl will use that path. + +The original Pascal source is in psrc/ in case you want to check how it +was done. doc/ contains the source for the manual. DVI files of the +manual, both in TeXtyl form and post-processed form are included for +regression testing, and for printing. The VMS part of the original +distribution is not included. If you still want that, contact me +directly. + +A contributed MF84 version of the vector fonts is in vecfonts/mf. Now +it is possible to generate fonts for non-300 dpi devices. + +Send all bug reports on this beta version to ken@syd.dit.csiro.au. + +27 August 1991 diff --git a/macros/latex209/contrib/textyl/TODO.27aug91 b/macros/latex209/contrib/textyl/TODO.27aug91 new file mode 100644 index 0000000000..1632abbded --- /dev/null +++ b/macros/latex209/contrib/textyl/TODO.27aug91 @@ -0,0 +1,5 @@ +Clean up code a bit. +Improve portability. +Add tpic special handling. + +27 August 1991 diff --git a/macros/latex209/contrib/textyl/doc/textyl.tex b/macros/latex209/contrib/textyl/doc/textyl.tex new file mode 100644 index 0000000000..d5059491c6 --- /dev/null +++ b/macros/latex209/contrib/textyl/doc/textyl.tex @@ -0,0 +1,42 @@ +% Inclusion file for TeXtyl +% This is textyl.tex +% +% John Renner (jsr@ohio-state.arpa) +% +% macros for figures for Tyling +% specify : +% \begintyl{vert_dimen}[optional_horiz_dimen] +% (with NO intervening space between the } and the [ chars) +% then the \special{tyl ...} strings +% then you must finish environment with \endtyl +% +% \begintyl and \endtyl are the only +% user-callable macros +% See the TeXtyl manual for a complete explanation. +\def\begintyl#1{\begingroup\endlinechar=-1\catcode `\^^I=9 + \dimen120=#1 + \ifhmode\toks0={\futurelet\tyltempb\begHtyl} + \let\endtyl=\endHtyl + \else\toks0={\futurelet\tyltempb\begVtyl} + \let\endtyl=\endVtyl\fi + \the\toks0} +% +%-------the rest are internal------ +\def\begHtyl{\ifx [\tyltempb \let\tylh=\tylHspace + \else\let\tylh=\tylHnospace\fi\tylh} +% +\def\tylHspace[#1]{\setbox0=\hbox to #1\bgroup + \vbox to \dimen120\bgroup\vss} +\def\tylHnospace{\setbox0=\hbox\bgroup + \vbox to \dimen120\bgroup\vss} +% +\def\begVtyl{\ifx [\tyltempb \let\tylv=\tylVspace + \else\let\tylv=\tylVnospace\fi\tylv} +% +\def\tylVspace[#1]{\setbox0=\vbox to \dimen120\bgroup\vss + \hbox to #1\bgroup} +\def\tylVnospace{\setbox0=\vbox to \dimen120\bgroup\vss + \hbox\bgroup} +% +\def\endHtyl{\egroup\hss\egroup\box0\endgroup} +\def\endVtyl{\hss\egroup\egroup\box0\endgroup} diff --git a/macros/latex209/contrib/textyl/doc/tylman.dvi b/macros/latex209/contrib/textyl/doc/tylman.dvi Binary files differnew file mode 100644 index 0000000000..7bfac681a8 --- /dev/null +++ b/macros/latex209/contrib/textyl/doc/tylman.dvi diff --git a/macros/latex209/contrib/textyl/doc/tylman.tex b/macros/latex209/contrib/textyl/doc/tylman.tex new file mode 100644 index 0000000000..071cf945ed --- /dev/null +++ b/macros/latex209/contrib/textyl/doc/tylman.tex @@ -0,0 +1,3144 @@ +% +% LaTeX file for the TeXtyl Manual +% Copyright (c) 1986, 1987 John S. Renner +% + +\documentstyle[twoside,12pt]{report} +\makeindex +\pagestyle{plain} +\pagenumbering{roman} +\begin{document} +\bibliographystyle{plain} +\hfuzz 5pt +\vfuzz 3pt +%\hoffset 1in +%\voffset 1in +\hyphenchar\tentt=-1 +% big tt font +\font\btt=cmtt10 scaled \magstep2 +\hyphenchar\btt=-1 +% font for small caps +\font\smallrm=cmr10 + +% special comma +\def\Coma{$\raise 2.5pt\hbox{\btt ,}$} +% macro for specifying a parameter +\def\Prm#1{\leavevmode \hbox{$\>\langle${\it #1\/}$\rangle\,$}} +% macro for specifying an optional parameter +\def\Opt#1{\leavevmode \hbox{$\>\lbrack\langle${\it #1\/}$\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\rbrack\,$}} +% optional parameter without large comma +\def\sOpt#1{\leavevmode \hbox{$\>\lbrack\langle${\it #1\/}$\rangle\, +\rbrack\,$}} +% used for simple verbatim environment using | | delimiters +% taken from TeXbook +\chardef\other=12 +\def\ttverbatim{\begingroup \catcode`\\=\other \catcode`\{=\other + \catcode`\}=\other \catcode`\$=\other \catcode`\&=\other + \catcode`\~=\other \catcode`\%=\other \catcode`\#=\other + \obeyspaces \obeylines \tt} +{\obeyspaces\gdef {\ }} +\outer\def\begintt{$$\let\par=\endgraf \ttverbatim \parskip=0pt + catcode`\|=0 \rightskip=-5pc \ttfinish} +{\catcode`\|=0 |catcode`|\=\other + |obeylines + |gdef|ttfinish#1^^M#2\endtt{#1|vbox{#2}|endgroup$$}} +\catcode`\|=\active +{\obeylines\gdef|{\ttverbatim\spaceskip=.5em plus .25em minus .15em\let^^M=\ \let|=\endgroup}} +% +% macro for figures for Tyling +\input{textyl} + +\newcommand{\TT}{{\it\TeX tyl\/} } +\newcommand{\TTN}{{\it\TeX tyl}} +\newcommand{\DVI}{{\smallrm DVI}} +\newcommand{\Makeodd}{{\ifodd\count0{\newpage\mbox{\ }\newpage}\fi}} + +\title{\TeX tyl: a line-drawing interface for \TeX} +\author{John S. Renner} +\date{14 March 1987 +\thanks{Copyright \copyright 1987~John~S.~Renner All rights reserved.}} +\maketitle +\clearpage %end page 0 +\begin{verse} +\it Geometry can produce legible letters,\\ + but art alone makes them beautiful.\\ +\end{verse}\par +\noindent\begintyl{260 pt}[1in] +\special{tyl beginfigure "zapf"} +\special{tyl line m 2 1,92; 45,92} +\special{tyl line m 2 1,92; 1,48} +\special{tyl line m 2 1,48; 111,48} +\special{tyl line m 2 45,92; 45,4} +\special{tyl line m 2 12,48; 12,92} +\special{tyl line m 2 23,48; 23,92} +\special{tyl line m 2 34,48;34,92} +\special{tyl line m 2 1,70;45,70} +\special{tyl line m 2 1,92; 23,48} +\special{tyl line m 2 1,92; 89,4} +\special{tyl line m 2 23,92;1,70} +\special{tyl line m 2 23,92;1,48} +\special{tyl line m 2 23,92; 45,48} +\special{tyl line m 2 45,92;1,48} +\special{tyl line m 2 45,92; 23,48} +\special{tyl line m 2 1,70,23,48} +\special{tyl arc m 2 11 @ 12,81 270,90} +\special{tyl arc m 2 11 @ 34,81 10 10} +\special{tyl arc m 2 11 @ 34,59 10 10} +\special{tyl arc m 2 11 @ 12,59 270 90} +\special{tyl arc m 2 22 @ 23,70 10 10} + +\special{tyl line m 2 45,92; 111,26} +\special{tyl line m 2 1,48; 45,4} +\special{tyl line m 2 45,4;100,60} +\special{tyl arc m 2 32 @ 45,48 10 10} +\special{tyl line m 2 45,4; 89,4} +\special{tyl line m 2 89,4; 89,60} +\special{tyl line m 2 89,4 111 26} +\special{tyl arc m 2 22 @ 67,26 10 10} +\special{tyl line m 2 67 26; 111 26} +\special{tyl arc m 2 16 @ 89,26 10 10} +\special{tyl line m 2 89,26; 111,48} +\special{tyl arc m 2 11 @ 100,37 10 10} +\special{tyl line m 2 100,37;100,60} +\special{tyl line m 2 111,26;111,48} +\special{tyl line m 2 111,48; 100,60} +\special{tyl arc m 2 8 @ 100 48 10 10} +\special{tyl arc m 2 6 @ 94 54 10 10} +\special{tyl line m 2 89,60; 100 48} +\special{tyl line m 2 95,54; 83 54} +\special{tyl arc m 2 4 @ 89 54 10 10} +\special{tyl line m 2 89 54; 100 54} +\special{tyl line m 2 89,60;83,54} +\special{tyl line m 2 89, 60; 100 60} +\special{tyl line m 2 83,54; 83,48} +\special{tyl line m 2 84,48; 89,54} +\special{tyl arc m 2 3 @ 86 51 10 10} +\special{tyl endfigure "zapf"} +\endtyl +\par +\nobreak +\begin{verse} +\it Art begins where geometry ends,\\* +and imparts to letters a character\\* +transcending mere measurement.\\* +\hskip 2in\hbox{\smallrm Paul Standard} +\end{verse}\index{Zapf{,} Hermann}\index{Standard{,} Paul} +\newpage %end page 1 +\mbox{ } +\newpage %clear page 2 +\tableofcontents + +\Makeodd +\chapter*{ Introduction} +\label{introduction} +\TT\index{{\TT}} is a prototype post-processing system to be used in +conjuction with {\TeX}\index{{\TeX}}\cite{knuth-tex82}, the typesetting program by Donald +Knuth. The purpose of \TT is to ``draw'' lines and curves in a +device-independent manner. \TT is a post-processor that +interprets certain commands in a {\DVI}\index{DVI} +({\underline d}e{\underline v}ice-{\underline i}ndependent) +file that is the +output of {\TeX} and contains the actual typesetting commands. +\TT will produce as its output another +{\DVI} file that contains the commands to typeset the lines and +curves on a printer or output device.\par + +In the current version of \TT (version 1.2 of March 1987), the simple line drawing +capabilities\index{capabilities} include several general types of straight lines, arcs, and +spline curves. Advanced features of \TT are for {\it MusiCopy}\index{MusiCopy}, the +music-typesetting\index{music} project at the Ohio State +University\cite{gourlay}, namely typesetting ties, slurs, and beams.\par + +The name\index{{\TT}, name} for \TT comes from three ideas: (1) a proper computer graphics +term for rendering images is called ``tiling,'' (2) the +mis-pro\-noun\-ci\-ation of the name sounds like ``textile,'' which evokes an image +of lines and bargello effects from weaving, and (3) this process of ``tyl''-ing\index{tyling} comes after {\TeX}.\par + +The main design goals\index{design goals} of \TT were (1) the minimization of data required +to typeset graphics on printers capable of setting only characters at +arbitrary positions on a page, +(2) the adherence to the {\DVI} format of {\TeX} output for specifying the +way to typeset a document in a device-independent manner, (3) + a simple, portable interface that would not require a change to the +functionality or design of {\TeX}, and (4) a user interface that is easy to +use by people and programs alike.\par + +\TT was not intended to mimic nor replace sexy programs like +{\it Ideal\/}\index{Ideal}\cite{vanwyk}, which know about constraints +and alignment niceties. +Rather, \TT is designed to +take care of medium-level details for {\TeX} for use on printing devices not +capable of directly accessing and +loading full bitmaps\index{bitmaps} produced by such systems as {\it +PostScript\/}\index{PostScript}\cite{adobe}. It is clear that {\DVI}-format is a subset of {\it +PostScript}, but a large community of users are not able to make use of such +a super-set, and \TT is intended to provide line-drawing +capabilities\index{capabilities} for them.\par + +Probably the best way to read this manual\index{{\TT}, how to read manual} + is to read the first four (4) +chapters, and skip right to the chapter entitled {\it Future Extensions}, +for a good introduction to \TTN. The other chapters deal with details of +the innards of \TTN, and describe the design in successively finer +detail.\par + +I would like to thank John Gourlay, and Clayton Elwell for their support, +comments, reminders, and good ideas during this three-year labor, and the +{\smallrm CGRG} for not hassling me about this.\par + +\Makeodd +\chapter{The Basics} +\pagenumbering{arabic} +\label{getting-started}So, let's draw. +I will assume that the reader has a reasonably good working knowledge of how to +use {\TeX}\index{{\TeX}} and/or {\LaTeX}\index{{\LaTeX}}, and sort of understands + Knuth's\index{Knuth{,} Donald} concept of ``boxes,''\index{boxes} and their +attributes of height, width, and current position\index{current position}. We need these concepts +because our direct interface is with {\TeX}, in the form of a {\tt .tex} +text-file\index{{\tt .tex} text file}. To typeset the line-drawings, we ask {\TeX} to place our drawing +at the current position on the page. Throughout this manual, I will provide +some examples of drawings to illustrate ideas. These figures are thumb-nail +size, but should be sufficient to get the idea across without using up lots +of space on a page. + Let's look at a simple example: After typing |\input{textyl}| \index{{\tt +textyl.tex} file}\index{{\tt input}} +near the +beginning of your file, but after any required preamble\index{preamble}, we +can obtain a trivial drawing like: +\index{line example}\par +\noindent\hskip 2in\begintyl{2truecm}[1in] +\special{tyl line 4 20, 0; 80,30} +\endtyl\par +\noindent Simple, but we achieved this + line by typing +\begin{verbatim} +...a trivial drawing like:\par +\noindent\hskip 2in\begintyl{2cm}[1in] +\special{tyl line 4 20, 0; 80,30} +\endtyl\par +\end{verbatim} + +The |\begintyl{2cm}[2in]| and |\endtyl| commands\index{macros}\index{space macros} were +\index{{\tt begintyl}}\index{{\tt endtyl}}\index{macros, {\it see} {\tt begintyl}}to give us some +space\index{space} to ``paste'' the picture in +(about 2 centimeters of vertical space, 1 inch of horizontal space, +and offset from the left-most margin by 2 inches),\footnote{See also Appendix~\ref{secapp}} + and the |\special...|\index{{\tt special}} is our way of asking for the above drawn line. + Here, we must use a ``|\special|'' to talk to {\TeX} +at this level. Later, \TT will actually do the work involved in +typesetting that line that {\TeX} recorded as being at this place on the +page. The |\special|\index{specials} is a way to make a kind of note or memo that {\TeX} +will write into the {\DVI} file for some other program like +\TT to work with, or choose to ignore, like most {\DVI} +filters do. \par + +Let's look at what |\special{tyl line 4 20, 0; 80,30}| is all about. First, +|tyl| is a name-string\index{{\tt tyl} name-string} asserting that this command + should make sense to \TTN. +Next, |line| is the name of the graphic +primitive\index{primitive} + to typeset: a +line segment (we will get to the other primitives later). The rest of the ``special'' +notes that the thickness\index{line thickness} of the line is $4$, and to draw the line from a +mark 20 printer's-points\index{printer's points, measurement} to the + right of the current position to a mark 80 +points over and 30 points higher from that current position. Mathematically, +we are using a {\bf first-quadrant} cartesian + coordinate-space\index{cartesian-space}\index{coordinates} + whose origin\index{origin}\index{coordinates, origin} is at the +current position\index{current position} on the page, and we are drawing a line from $(20,0)$ to +$(80,30)$ in integer units\index{measurement, units} of printer's-points in that space. It looks like this (magnified):\par +\noindent\hskip 1in\begintyl{130 pt} +\special{tyl beginfigure} +\special{tyl line m 2 0,0 0,40} +\special{tyl label m 1 0 43 "+Y"} +\special{tyl line m 2 0 0 90 0} +\special{tyl label m 1 93 0 "+X"} +\special{tyl arc m 1 2 10 10} +\special{tyl line m 8 20,0;80,30} +\special{tyl line m 1 0 10, -2,10} +\special{tyl line m 1 0 20, -2 20} +\special{tyl line m 1 0 30 -2 30} +\special{tyl line m 1 0 40 -2,38} +\special{tyl line m 1 0 40 2 38} + +\special{tyl line m 1 10 0 10 -2} +\special{tyl line m 1 20 0 20 -2} +\special{tyl line m 1 30 0 30 -2} +\special{tyl line m 1 40 0 40 -2} +\special{tyl line m 1 50 0 50 -2} +\special{tyl line m 1 60 0 60 -2} +\special{tyl line m 1 70 0 70 -2} +\special{tyl line m 1 80 0 80 -2} +\special{tyl line m 1 90 0 88 2} +\special{tyl line m 1 90 0 88 -2} +\special{tyl endfigure} +\endtyl +\par +\vskip 10pt +\noindent where we have emphasized the origin of the quadrant, and used +tick-marks for every ten printer's-points. In reality, someone preparing a +figure would sketch\index{figures, preparation} +\index{preparing a figure} something out on grid paper, and then use those +coordinates for use in the |\special|. If he were really in luck, he +could use a graphic editor that would take care of such numeric details, and +maybe even output the |\special| strings for direct insertion into the +{\tt .tex} file. Maybe. For now, we will have to stick to the grid-paper +method. The only things that we have to remember are that the origin\index{grid-origin} of our +quadrant is placed at the position\index{current position} on the page where we invoke the +|\special| of {\TeX}, and that we may want to leave white space\index{space}\index{leaving white space} for our +graphic to be drawn in. This last constraint is because {\TeX} does not +really know about the size of our drawing, it thinks that the |\special| is +a ``box''\index{boxes} with zero height and width placed at the current position on the +page. It is up to us to decide how much {\it real\/} space to tell {\TeX} to +leave for our drawing to be put into later by \TTN.\par +In the example above, +and the following examples, we will put our |\special| strings within an +environment that makes it easy to specify where the origin of our quadrant +should be placed. For example, |\begintyl{4cm}[1in]| \index{{\tt begintyl}} + tells {\TeX} to place +our origin 4 centimeters down from where it was just sitting. +A horizontal width is an optional second parameter to |\begintyl|, +and is enclosed in square braces immediately following the vertical +displacement parameter (with no spaces in-between). So |\begintyl{5cm}| +would place our origin 5 centimeters below the current position, with no +relative horizontal width. Other spacing requirements have to be done by +hand (e.g., like typing |\hskip 1in| before the |\begintyl|), or by putting the whole +|\begintyl| \ldots |\endtyl| group within a containing environment (e.g., +\LaTeX's |figure| environment). + We could, if +we wanted, +leave no extra white-space\index{leaving no space} and have the drawing extend into + and over any text that {\TeX} may typeset +before {\it or\/} after we invoke a |\special{tyl ...}| command. We would, +of course, start that tyling-environment with a + |\begintyl{0pt}| command, and finish with the |\endtyl| command, and it +might do something + like \begintyl{0pt}\special{tyl arc m 3 5 @4 0;5 5}\endtyl this. +\par + +\goodbreak Once we are satisfied with our {\tt .tex}\index{{\tt .tex} text file} + file containing |\special| strings +requesting line-drawings, we run the {\tt .tex} file through + {\TeX}\index{{\TeX}} or {\LaTeX}\index{{\LaTeX}}, and +(barring any fatal errors) end up with a {\tt .dvi} file\index{{\tt .dvi} file}. +We now run\index{running {\TT}} + this {\tt .dvi} file through \TT which goes through the file and converts our +|\special| strings left-over from {\TeX} into commands to actually typeset +the line-drawing. The whole process might look something like this:\par + +\bgroup\small +{\it prompt:}\underbar{\tt tex}\par +{\tt This is TeX, Version mumble...}\par +{\tt **}\underbar{\tt myfile.tex}\par +\hspace*{6em}$\ldots$ {\it output from \TeX}\par +{\tt Output written on myfile.dvi ( n pages , m bytes).}\par +{\it prompt:}\underbar{\tt textyl}\par +{\tt This is TeXtyl, Version blah...}\par +{\tt DVI-input File Name:}\underbar{\tt myfile.dvi}\par +{\tt DVI-output File Name}\par +{\tt (different than input name)[default of myfile.tyl]:} +\underbar{\tt myfile2.dvi}\par +\hspace*{6em}$\ldots$ {\it output from \TT}\par +{\tt Output written on myfile2.dvi}\par +{\tt Log written on myfile2.tlog}\par + +\egroup +\noindent So there you have it. All we have to do is give this +new {\tt .dvi} (or {\tt .tyl}) file to +a favorite {\DVI} filter\index{DVI-filters}, and look at the document with the +line-drawing results on that particular filter's output device\index{output +device} +(usually paper or a bitmapped screen). You should +contact your local maintainer\index{local maintainer} if \TT or the filter + cannot find the right fonts, and try again.\par +By the way, the {\tt .tlog} file is useful for finding out about the +``tyling'' of the {\tt .dvi} file. Besides noting any errors, the log file +contains the approximate height and depth of each non-trivial figure. A +portion of the {\tt .tlog}\index{{\tt .tlog} file} file for this document +might look like: +\vspace*{-20pt} + +{\footnotesize\begin{verbatim} +17] [ +Figure #1 on page 18 is approx. 33 pts high and 47 pts wide + +Figure #2 on page 18 is approx. 32 pts high and 51 pts wide + +Figure #3 on page 18 is approx. 27 pts high and 45 pts wide + +Figure #4 on page 18 is approx. 31 pts high and 82 pts wide +18] [19] [20] [ +\end{verbatim} + +} +This information allows you to re-edit the parameters to |\begintyl| so that +\index{{\tt begintyl}} they can better approximate the actual sizes of the figures.\par +\medskip\filbreak +Let's try a slightly more complicated example: drawing a spline.\index{spline, example} +\TT understands drawing smooth spline curves\index{spline curves}\index{curves} through +in\-teger co\-ordinate points (both positive and negative)\index{spline, coordinates} + on our grid. For example: +\vspace*{-10pt} +\begin{verbatim} +\begintyl{3cm}[1in] +\special{tyl spline m 4 K 7 5,10; 9,14; 15,7;22,13; + 17,14;12,5;7,0;} +\endtyl\par +\end{verbatim} +yields\par +\noindent\hskip 1in\begintyl{2cm}[1in] +\special{tyl spline m 4 K 7 5,10; 9,14; 15,7; 22,13;17,14;12,5; 7,0; } +\endtyl +\par\filbreak +\noindent Here, we are using units of millimeters for measurement (denoted +by an |m| or |M|,\index{{\tt M}-marker}\index{millimeters, measurement} a line thickness of $4$, and we + want to use a Catmull-Rom type spline\index{spline, +Catmull-Rom}\index{Catmull-Rom splines} +(denoted by |k| or |K|\index{{\tt K}-marker}---also the default type\index{spline, +default} + if none is specified). We + specify that there are $7$ control points\index{spline, control-points} +to interpolate through, and then +list those $x, y$ pairs. Some things are optional +\index{defaulting values}\index{optional values} + for you (like the spline type, or the units of measure), but +some are {\it not\/} (notably the line-thickness and the number of control points). +As we go through these examples, I will point out the minimum that we +need to specify a graphic primitive, and note other options or features that +we might want to use. For a detailed look at the specifications of the +primitives, please refer to the \underbar{\it User-Level +Details} in chapter~\ref{user-level}.\par\filbreak + +Let's try one more type of spline-primitive: the thick-n-thin +spline\index{ttspline}\index{Thick-n-thin spline}\index{spline, ttspline}. This +is a primitive that lets us specify a spline of varying line thickness along +the spline. An example\index{ttspline, example} invocation might be: +\begin{verbatim} +\special{TYL ttspline m 5 4,6; 14,25; 18,19; 21,15; 24,8; + 10; 2; 6; 3; 8} +\end{verbatim}\par +\noindent\hskip 1in +\begintyl{4cm}[2in] +\special{tyl ttspline m 5 4,6; 14,25; 18,19; 21,15; 24,8; + 10; 2; 6; 3; 8} +\endtyl\par +\noindent It looks similar to the |spline| primitive, but here we did not +specify a single line thickness right after the |m|\index{{\tt M}-marker} + measure-marker. The |5| +refers to the number of control-points as before, then is followed by the +$(x,y)$ coordinate pairs, and then the line-thicknesses\index{ttspline, thicknesses}. The first +number (here, |10|) refers to the line thickness at the first control-point +(here, $(4,6)$ ); the next for the second control-point, etc. We did not +need to align the thicknesses under the control-points, but it +makes the correspondence more apparent. We did not +specify the type of spline to use, so the Catmull-Rom interpolating spline +was used by default\index{ttspline, defaults}. We could have inserted a + |b| marker\index{{\tt B}-marker} + directly before the number of control-points,\label{thebases} +and gotten a spline using the B-spline basis\index{B-spline +basis}.\index{spline, B-spline} + Using +a |d| marker\index{{\tt D}-marker} yields a spline with the Cardinal +basis\index{Cardinal basis},\index{spline, Cardinal} and +an |i|\index{{\tt I}-marker} would indicate an +Interpolating B-spline\index{B-splines, interpolating-type}\index{spline, +Interpolating B-spline} + (which is a little different)\index{interpolating B-spline}. We will +look closer at these spline-types on page~\pageref{diffsplines}. +\par\filbreak + +If you've been very observant, you may have noticed that the way we type in +the |\special| strings\index{typing in special +strings}\index{specials, typing in} + (the letters and numbers within the |{| -- |}| pair) +has been rather indiscriminant about upper vs. lower-case\index{specials, case insensitivity}. + That's okay. \TT + has only a few things to worry about, and so it will try to +figure things out for you. It is pretty lenient about how you +punctuate\index{specials, punctuation} + and +separate (``delimit'')\index{delimiters} keywords\index{keywords} + and markers\index{markers}.\goodbreak\filbreak We only have to remember +\begin{enumerate} +\item the relative ordering of the keywords and integers, +\item being careful to avoid +mis-using the word markers\footnote{See the index for a list of markers} in +the wrong places, and +\item supplying enough parameters that are expected. +\end{enumerate} +Other than its own macro-expansions, {\TeX} really + doesn't care about the ``meaning'' of the final strings that + goes inside the curly braces of the +|\special{...}| command-strings, only \TT does.\par + +We'll briefly look at an example of one more graphic primitive, and then get +on to more advanced topics. \TT has the ability to draw arcs and +circles like\index{arcs}\index{circles}:\par +\noindent\hskip 2in\begintyl{7truecm}[2in] +% 15-Mar-87 15:51:23 +% TeXtyl figure written with width= 198 mm and height= 206 mm +% you may have to scale it with Transform or Fit operators in beginfigure +\special{tyl beginfigure m W 198 206 F 50 50} +\special{tyl arc m 3 c 64 @(134 114) 357 54} +\special{tyl arc m (T 120 80 0 0 0) 3 c 31 @(36 31) 10 10} +\special{tyl arc m 3 c 53 @(129 77) 94 58} +\special{tyl arc m 3 c 66 @(85 140) 27 323} +\special{tyl arc m 1 c 57 @(57 100) 10 10} +\special{tyl endfigure} +\endtyl\par\filbreak +\noindent Arcs are drawn from an initial angle (measured +from the horizontal (positive x-axis) in integer degrees) counter-clockwise +to a final angle with +the arc centered about the origin.\index{arcs, angles}\index{arcs, center} + If the +initial angle is the same as the final angle, we get a full circle\index{circles}\index{arcs, circles}. +A simple arc invocation might look like\index{arcs, example}:\par +|\special{tyl arc m 2 3, 48, 280}|\par +\noindent which would draw an arc of line thickness $2$, a radius\index{arcs, radius} of $3$ +millimeters, from an initial angle of 48 degrees until the final angle of 280 +degrees centered about the origin. We could specify that the arc is to be +centered\index{arcs, centering} +elsewhere by using a special |@|\index{{\tt @}-marker} marker. So,\par +|\special{tyl arc m 2 3, @ 7,7; 10 10 }|\par +\noindent would draw an arc of line-thickness $2$, radius of $3$ mm as before, +but centered at $(7,\, 7)$ from the origin. Also, since the initial and final +angles are the same in this example (|10|), we would get a full circle. +\par\vfill\pagebreak[4] +%\Makeodd +\chapter{Advanced Features} +\label{advanced-features}In the previous chapter, we saw basic examples of most of the graphic +primitives available in \TTN, how to invoke them\index{primitives, invoking}, and some of +the parameters\index{primitives, parameters} to the primitives. We also saw examples of how we interface +with {\TeX} using the |\special| command strings, and how the origin of our +drawing quadrant is placed at the reference point of the ``box'' containing +the |\special| (usually the lower-left corner of the box created with the +|\begintyl| and |\endtyl| macros.\index{macros}\index{boxes} + (see the {\TeX book}\cite{knuth-tex82}\index{\TeX book} for a better explaination of +``specials''). The rest of this chapter will look more at +the parameters available for the primitives, and how we can +combine\index{primitives, combining}\index{combining primitives} +primitives and manipulate them.\par + +\section{Transforms} +\label{transforms}\index{transforms} +The most interesting additional parameter for the primitives is a transform +operation. It allows us to modify an already-exisiting definition of a +primitive without our having to totally re-edit the |\special| +string, nor having +to explicitly re-compute the coordinates of the line/spline points. +Thus we can take a simple definition similar as before, like:\par +|\special{tyl line m 4 0,8; 39,44}|\par +\noindent and change its size, or rotate it, or translate (shift) +its position\index{scaling}\index{rotation}% +\index{translating}\index{primitives, scaling; rot\-ating; trans\-lating} +without completely changing the actual text of the + specification of the control points (this is really useful +when dealing with splines having many control points). +\index{transforms, scaling}\index{transforms, rotating} +\index{transforms, translation} +\filbreak + Let's look at an +example, and then go into more detail about the transform. For example, to +rotate the above definition about its center by 60 degrees +counter-clockwise, all we have to specify is +|\special{tyl line m T (100, 100, 0, 0, 60) 4 0,8; 39, 44}| + which yields\index{transforms, example}\par +\noindent\hskip 1in\begintyl{1in}[2in] +% 15-Mar-87 15:47:50 +% TeXtyl figure written with width= 196 mm and height= 71 mm +% you may have to scale it with Transform or Fit operators in beginfigure +\special{tyl beginfigure m W 196 71 F 51 51} +\special{tyl line m 4 c 170 0 154 71} +\special{tyl line m 4 c 54 61 0 11} +\special{tyl line m 1 c 109 28 114 37} +\special{tyl line m 1 c 107 45 114 37} +\special{tyl line m 1 c 110 34 87 34} +\special{tyl line m 1 c 111 37 89 37} +\special{tyl line m 1 c 110 39 87 39} +\special{tyl endfigure} +\endtyl\par +\noindent as expected. We use the |T|\index{{\tt T}-marker} marker to note the need for a +transformation, and follow it by five numbers\index{transforms, parameters}. + The first two are for +scaling, the next two for translation, and the last (here, |60|) is for our +rotation. In general, the +format for specifying some transformation on the currently-specified points +is:\par +\qquad{\btt T}\ \Prm{Sx}\Coma\Prm{Sy}\Coma\Prm{Tx}\Coma\Prm{Ty}\Coma\Prm{Rot}\Coma\par +\noindent where \Prm{Tx} and \Prm{Ty} are translations of the object in + the $X$ or $Y$ direction, respectively, by some signed distance according to the +current units of \Prm{measure} (|m|\index{{\tt M}-marker} still means millimeters in the above example). + \Prm{Rot} is a signed integer angle (in degrees) \index{rotation} +by which\index{rotation, using degrees measurement} +to rotate the primitive counter-clockwise about its center. + \Prm{Sx} and \Prm{Sy} are\index{transforms, parameters} +integer scale parameters representing the real values of the +transform multiplied by 100. For example, if you wanted to scale the drawing +in the $X$ direction (relative to the drawing's center) + by an additional 50\% (i.e., scale by 1.5), +\Prm{Sx} would be 150. Negative values are usuable, too, so +mirroring\index{transforms, mirroring} about the $Y$ axis is achievable by +scaling in the negative $X$ direction, like $\Prm{Sx} = -100$. +To obtain any transform, {\it all\/} the transform parameters must be +specified. A no-op transform\index{transforms, no-op} would look kind of like +{\tt T~(100,~100,~\kern-1pt0,~\kern-1pt0,~\kern-1pt0)} in the middle of +the |\special|. \par + +\section{Figures} +\label{figures} +The last major \TT concept is the idea of combining +several primitives\index{primitives, combining} into what we call a +``figure.''\index{figures}\index{combining primitives} +This figure can be manipulated either as a single entity or in parts +by +using the \Prm{transform} operations\index{figures, transforms} described +in the previous section. +These optional figure-level transformations +will transform all the figure's primitives (which may have local +transformations of their own). The result is a nested symbol definition +\index{nested symbols}\index{figures, nested symbols} +that has concatenatable transformations\index{transforms, concatenation}. +This is useful for defining some + symbol, created from various primitives, and dealing with it +as a unit. For example, a basic logotype can be defined, and then moved +about, scaled, or rotated as desired {\it without\/} having to change the +original definition of the logotype or its parts from scratch. +These commands are:\par +\medskip +{\btt\char'134 special\char'173 tyl beginfigure} +{\leavevmode \hbox{$\>\lbrack\langle${\it transform\/}$\rangle\, +\rbrack\,$}}{\btt\char'175}\par +\noindent which opens a level of definition\index{{\bf beginfigure}}\index{figures, defining}, +and\par +\medskip +{\btt\char'134 special\char'173 tyl endfigure}{\btt\char'175}\par +\noindent which closes that level of definition\index{{\bf endfigure}}. + Any calls to a +|\special{tyl ...| primitive within a |beginfigure| -- |endfigure| pair +become part of that figure's definition\index{figures, sub-figures}. +Note the definition of |beginfigure| allows the ability to apply a +transformation at the outer level. A simple example might be:\index{figures, +examples}\vspace*{-10pt} +\begin{verbatim} +\begintyl{2in} +\special{tyl beginfigure} + \special{tyl line m 2 5,10; 15,15 } + \special{tyl line m 4 10,20; 16,1 } + \special{tyl line m 8 15,10; 25,10 } +\special{tyl endfigure} +\endtyl +\end{verbatim} +giving a figure of three lines:\par +\noindent\hskip 2in\begintyl{1truein}[2in] +\special{tyl beginfigure "oflines"} +\special{tyl line m 2 5,10; 15,15 } +\special{tyl line m 4 10,20; 16,1 } +\special{tyl line m 8 15,10; 25,10 } +\special{tyl endfigure "oflines" } +\endtyl\par +\noindent We can also define sub-figures\index{sub-figures} within figures +and apply\label{sub-figures} +transformations\index{transforms, sub-figures} to those, too. The idea looks like:\par +|\begintyl{down-distance}[optional-width]|\par +|\special{tyl beginfigure}|\par +\qquad $\ldots$\par +\qquad|\special{tyl beginfigure}| {\it \% Some sub-figure }\par +\qquad $\ldots$\hbox{\hskip 2in} {\it \% of other primitives}\par +\qquad|\special{tyl endfigure}|\par +\qquad $\ldots$\par +|\special{tyl endfigure}|\par +|\endtyl|\par +\noindent Where ``$\ldots$'' means possible other invocations of +primitives with |\special{tyl...}| strings. We are +able to use spacing and tabbing to nicely indent our |\special| strings, +since {\TeX} considers all that white space to be non-existent within the +|\begintyl| -- |\endtyl| environment.\index{{\tt begintyl}}\index{{\tt +endtyl}} +\par\filbreak + +We'll look at a basic figure\index{figures, example}, and apply some +transforms to parts of it. + For the basic figure, we have:\par +\noindent\hskip 2in\begintyl{1in}[2in] +\special{tyl beginfigure "TeXtyl-logo-1"} + \special{tyl beginfigure "tex-logo"} + \special{tyl line m 3 2,13; 10,13} + \special{tyl line m 3 6,13; 6,6} + + \special{tyl line m 3 8,11;8,4} + \special{tyl line m 3 8,11;12,11} + \special{tyl line m 3 8,8; 11,8} + \special{tyl line m 3 8,4;12,4} + + \special{tyl line m 3 13,13;18,6} + \special{tyl line m 3 13,6;18,13} + \special{tyl endfigure} + \special{tyl beginfigure "tyl-logo"} + \special{tyl line m 3 20,10;24,10} + \special{tyl line m 3 22,12;22,6} + + \special{tyl line m 3 25,10;27,6} + \special{tyl line m 3 29,10;26,2} + + \special{tyl line m 3 31,13;31,6} + \special{tyl endfigure} +\special{tyl endfigure}\endtyl\par\filbreak +\noindent Now let's scale a sub-figure by using a |T|\index{{\tt T}-marker} + transform at the +|beginfigure| level; i.e., something like +\verb+\special{tyl beginfigure T 60 60 0 0 0}+ :\par +\noindent\hskip 2in\begintyl{ 1in}[2in] +\special{tyl beginfigure "TeXtyl-logo-2"} + \special{tyl beginfigure "tex-logo"} + \special{tyl line m 3 2,13; 10,13} + \special{tyl line m 3 6,13; 6,6} + + \special{tyl line m 3 8,11;8,4} + \special{tyl line m 3 8,11;12,11} + \special{tyl line m 3 8,8; 11,8} + \special{tyl line m 3 8,4;12,4} + + \special{tyl line m 3 13,13;18,6} + \special{tyl line m 3 13,6;18,13} + \special{tyl endfigure} + \special{tyl beginfigure T 60 60 0 0 0 "tyl-logo"} + \special{tyl line m 3 20,10;24,10} + \special{tyl line m 3 22,12;22,6} + + \special{tyl line m 3 25,10;27,6} + \special{tyl line m 3 29,10;26,2} + + \special{tyl line m 3 31,13;31,6} + \special{tyl endfigure} +\special{tyl endfigure}\endtyl\par\filbreak +\noindent We can rotate, and then also translate that same +sub-figure and achieve the next two examples. First, a rotation about +the sub-figure's center:\par +\noindent\hskip 2in\begintyl{ 1in}[2in] +\special{tyl beginfigure "TeXtyl-logo-3"} + \special{tyl beginfigure "tex-logo"} + \special{tyl line m 3 2,13; 10,13} + \special{tyl line m 3 6,13; 6,6} + + \special{tyl line m 3 8,11;8,4} + \special{tyl line m 3 8,11;12,11} + \special{tyl line m 3 8,8; 11,8} + \special{tyl line m 3 8,4;12,4} + + \special{tyl line m 3 13,13;18,6} + \special{tyl line m 3 13,6;18,13} + \special{tyl endfigure} + \special{tyl beginfigure T 60 60 0 0 -35 "tyl-logo"} + \special{tyl line m 3 20,10;24,10} + \special{tyl line m 3 22,12;22,6} + + \special{tyl line m 3 25,10;27,6} + \special{tyl line m 3 29,10;26,2} + + \special{tyl line m 3 31,13;31,6} + \special{tyl endfigure} +\special{tyl endfigure}\endtyl\par\filbreak +\noindent and now also translated {\it after\/} the rotation:\par +\noindent\hskip 2in\begintyl{1in}[2in] +\special{tyl beginfigure "TeXtyl-logo-4"} + \special{tyl beginfigure "tex-logo"} + \special{tyl line m 3 2,13; 10,13} + \special{tyl line m 3 6,13; 6,6} + + \special{tyl line m 3 8,11;8,4} + \special{tyl line m 3 8,11;12,11} + \special{tyl line m 3 8,8; 11,8} + \special{tyl line m 3 8,4;12,4} + + \special{tyl line m 3 13,13;18,6} + \special{tyl line m 3 13,6;18,13} + \special{tyl endfigure} + \special{tyl beginfigure T 60 60 -8 -8 -35 "tyl-logo"} + \special{tyl line m 3 20,10;24,10} + \special{tyl line m 3 22,12;22,6} + + \special{tyl line m 3 25,10;27,6} + \special{tyl line m 3 29,10;26,2} + + \special{tyl line m 3 31,13;31,6} + \special{tyl endfigure} +\special{tyl endfigure}\endtyl\par\filbreak +\noindent Finally, we can take the whole figure, and perform a scale and a +then a rotation on it (we evaluate scaling first, then rotations and finally +translations):\par +\noindent\hskip 2in\begintyl{3cm}[2in] +\special{tyl beginfigure T 80 80 0 0 60 "TeXtyl-logo-5"} + \special{tyl beginfigure "tex-logo"} + \special{tyl line m 3 2,13; 10,13} + \special{tyl line m 3 6,13; 6,6} + + \special{tyl line m 3 8,11;8,4} + \special{tyl line m 3 8,11;12,11} + \special{tyl line m 3 8,8; 11,8} + \special{tyl line m 3 8,4;12,4} + + \special{tyl line m 3 13,13;18,6} + \special{tyl line m 3 13,6;18,13} + \special{tyl endfigure} + \special{tyl beginfigure "tyl-logo"} + \special{tyl line m 3 20,10;24,10} + \special{tyl line m 3 22,12;22,6} + + \special{tyl line m 3 25,10;27,6} + \special{tyl line m 3 29,10;26,2} + + \special{tyl line m 3 31,13;31,6} + \special{tyl endfigure} +\special{tyl endfigure}\endtyl +\par\filbreak + +\section{Others} +We'll finish off this section with a couple more primitives: a simple spline +example, and the primitives for a music-typesetting project underway at Ohio +State University\cite{gourlay}\index{OSU}. The first example is not really that different from our +first spline example, except that in this case, we have a ``closed'' +spline:\index{splines, closed}\index{closed splines} one whose + first control-point will coincide with its last control-point. +We can type something that looks like: +\begin{verbatim} +\special{tyl spline m 3 b O 8 (10,9) (4,16) (8,23) + (11,21) (13,17) (20,16) (22,13) (19,8)} +\end{verbatim}\par +\noindent The |O| (letter ``Oh'')\index{{\tt O}-marker} + marker denotes a closed spline\index{closed splines}. The default +option is an ``open'' spline\index{open spline}\index{splines, open}, + and can be marked with a |U|\index{{\tt U}-marker} instead of the +|O| if you wish to be explicit. +The difference is in the way that \TT +manipulates the control points when doing the interpolation. + In this example, we used a B-spline, as marked with a +|b|\index{{\tt B}-marker}, and we listed {\it only\/} the unique +coordinates to get this nice bean-shape:\par +\noindent\begintyl{3cm}[2in] +\special{tyl spline m 3 b O 8 10,9;4,16;8,23;11,21;13,17;20,16;22,13;19,8} +\endtyl\par + +\label{diffsplines}\TT provides three types of spline interpolation which I alluded to on +page~\pageref{thebases}. The Catmull-Rom basis is probably the most +intuitively useful spline for users. It produces a smooth curve that goes +\index{splines, Catmull-Rom, example} +through the control points (which we can mark with dots):\par +\noindent\hskip 1in\begintyl{1in}[1in] +\special{tyl spline m 2 K X 8 7 5,10; 9,14; 15,7; 22,13;17,14;12,5; 7,0;} +\endtyl\par +The Cardinal basis\index{splines, Cardinal, example} is of the same family +as the Catmull-Rom. It, too, interpolates through the control points, and is +included for convenience and as an alternative to the Catmull-Rom. For +example:\par +\noindent\hskip 1in\begintyl{1in}[1in] +\special{tyl spline m 2 D X 8 7 5,10; 9,14; 15,7; 22,13;17,14;12,5; 7,0;} +\endtyl\par +The B-spline\index{splines, B-spline, example} is a little different in that +the curve {\it approximates\/} the control points. Using the same control points as +the above example, but using the B-spline basis, we see:\par +\noindent\hskip 1in\begintyl{1in}[1in] +\special{tyl spline m 3 B X 8 7 5,10; 9,14; 15,7; 22,13;17,14;12,5; 7,0;} +\endtyl\par +For the most part, you will probably want to draw curves through the control +points that you specify, and so the Catmull-Rom basis is the +convenient default. The B-spline type is provided for completeness for users +who might have data using that basis.\par + + There {\it are\/} times when the Catmull-Rom or Cardinal bases give flakey +curves and the B-spline basis is not appropriate either. \TT provides a +fourth type of spline for these situations: an interpolating B-spline +curve.\index{splines, Interpolating B-spline, example} It has the advantages +of Catmull-Rom's interpolation, and the special flexibilities of the +B-spline, but is computationally more expensive. See \cite{wu-abel} or \cite{barsky} for a +complete explanation. Here is an example using the same control points as +the above examples, but using the interpolating B-spline:\par +\noindent\hskip 1in\begintyl{1in}[1in] +\special{tyl spline m 3 I X 8 7 5,10; 9,14; 15,7; 22,13;17,14;12,5; 7,0;} +\endtyl\par + +For the {\it MusiCopy\/}\index{MusiCopy} project, we have the ability to draw ties and slurs +\index{ties}\index{slurs}---the long arcs connecting groups of notes. For the most part, I assume +that there is a program that is going to take care of the details of knowing where these +graphic elements are to be placed, and will produce the correct |\special| +string for inclusion in the {\tt .tex} file, but I will give an example for +completeness.\filbreak This graceful arc is produced by specifying a minimum and +\index{ties, {\it see also} slurs}\index{slurs, {\it see also} ties} +\index{ties, example} maximum thickness, and the five control points for the shape.\par +\noindent\begintyl{4truecm}[2in] +\special{tyl tieslur m 2 8 5 5,10; 7,13;15,16;24,17; 28,15 } +\endtyl\par\filbreak + +\noindent The call looked like\index{tieslur, example}:\par +|\special{tyl tieslur m 2 8 5 (5,10)(7,13);[15,16];(24,17); 28,15 }| \par +\noindent where |2| and |8| are the min and\index{tieslur, thicknesses} +max thicknesses at the endpoints and the middle, respectively. The following +|5| is for the number of control points, and the five pairs of integers +following that are the coordinates of the points. We use a special way of +producing a smooth and gradual thin to thick to thin line-thickness, +but will discuss it in a later chapter.\index{ties, and ttsplines}\par\filbreak + +The last example is the most specialized for the music project: beams\index{beams}. We'll +just look at an example of how they are called and appear, and leave the +details for the next chapter.\par +\noindent\begintyl{3truecm}[2in] +\special{tyl beginfigure "beams" } + \special{tyl beam m 0 3,20; 15,23 } + \special{tyl beam m 0 g 3,10;11,7 } +\special{tyl endfigure }\endtyl\par +\noindent The basic order of the parameters looks something like:\par +|\special{tyl beam m 0 g 3,10;11,7 }|\par +\noindent where |0| (zero) is the ``staff-size,''\index{staff-size} + |g|\index{{\tt G}-marker} indicates a beam size for +``grace'' notes\index{grace-notes} (|r|\index{{\tt R}-marker} +is the default for ``regular'' sized notes), and the +last two pairs are the coordinates of the line-segment that the beam is to be +centered over.\par + +\Makeodd +\chapter{User-Level Details} +\label{user-level} +From the user's point of view\index{user's view} using {\TeX}\index{{\TeX}}, + commands\index{{\TeX} commands}\index{specials} that \TT +interprets will look like the word ``|tyl|'', followed by + the name of the graphic to typeset, then a +list of parameters\index{parameters to {\TT}}\index{{\TT}, parameters} +all enclosed within the curly +braces of a \hbox{|\special{...}|} command. +This use of a |\special| could be produced +by some other program (a graphic editor, for example), +\index{graphic editors} and the text strings merely +inserted into the {\tt .tex} text-file. \par + +As far as the user is concerned, he is pasting in a picture at the current +position\index{current position} on the page where he invokes the |\special|. The user should +think of this picture as being a box just big enough to contain all the +lines of his graphic image, and whose first-quadrant cartesian + origin is the reference\index{origin of quadrant}\index{reference point} +point that will be placed at the current position on the page. Thus, he +might want to make sure that there is enough blank space \index{blank space}around the current +position on the page to contain the +image before he tries to ``paste it in.'' Space can be created by using +\TeX's |\hskip| or |\vskip|, or \LaTeX's |\hspace| and |\vspace| commands, +\index{{\TeX}}\index{{\LaTeX}} or hoping for the best with \LaTeX's +|figure| environment \index{{\LaTeX}, {\tt figure } environment} surrounding +the box created by |\begintyl| and |\endtyl|. +\par + +The kinds of graphic primitives\index{primitives}\index{capabilities} +that \TT knows how to typeset are +uniform-thickness line segments, uniform-thickness splines, +uniform-thickness arcs, variable-thickness +splines, music beams, and music ties/slurs. Line segments are +merely a subset of splines, and so variable-thickness lines are available by +specifying a spline of just two control points with a thickness at one end +point,\index{primitives, built-up} + and another thickness at the other end point. The feature here is to have +several primitives available, and allow for other graphic elements + to be built using them.\par\filbreak + +We'll look at the basic syntax for the primitives, and then discuss what +each parameter really means and how to specify what you want. +The parameters\index{primitives, parameters}\label{parameters} for each +of the graphic types are as follows: literals are +in a {\btt typewriter} face, any required parameters for the primitive are +in \mbox{$\langle$ angle $\rangle$} brackets, + and any {\it optional\/} parameters are within +\mbox{$\lbrack$ square $\rbrack$} +brackets. Please note that the relative ordering of the parameters + {\it is\/} important, even +if you do not use any or all optional parameters. Also, it is does not +matter if you use upper- or lower-case letters for the primitives or markers. +\par\filbreak +\medskip +{\btt\char'134 special\char'173 tyl line} + \Opt{measure} +\Opt{transform} \Prm{thick}\Coma\par +\hfil \Opt{vector}{\leavevmode\hbox{$\>\lbrack${\btt L}$\>\langle style\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\rbrack$}} $ x_{\rm left}\,\Coma\> +y_{\rm bottom}\,\Coma\> +x_{\rm right}\, \Coma\> y_{\rm top}${\btt\char'175} \par + +\noindent draws a line\index{{\bf line}} segment\index{line segments} + from the point $\left( x_{\rm left}\, , \; y_{\rm +bottom}\right)$ to the point +$\left( x_{\rm right}\, ,\; y_{\rm top}\right)$ using a line of +thickness\index{line thickness} +\Prm{thick}.\par\filbreak + +\medskip +{\btt\char'134 special\char'173 tyl spline} + \Opt{measure}\Opt{transform}\Prm{thick}\Coma\par +\hfil \Opt{vector} +{\leavevmode\hbox{$\>\lbrack${\btt L}$\>\langle style\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\rbrack$}} +\Opt{s-type}\Opt{closure}\par +\hfil{\leavevmode\hbox{$\>\lbrack${\btt X}$\>\langle dotsize\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\rbrack$}} +\Prm{numpts}\Coma $x_1\, \Coma\> y_1\, \Coma\> \ldots\>\Coma\> + x_{\rm numpts}\, \Coma\> y_{\rm numpts}$ {\btt \char'175} \par + +\noindent draws a smooth spline\index{{\bf spline}} curve through the integer points + $x_1\, , \; y_1 ,\; \ldots$ \linebreak[4] + $\; x_{\rm numpts}\, ,\; y_{\rm numpts}$ +using a line of thickness \Prm{thick}. If the optional {\btt X} marker +\index{{\tt X}-marker} is specified, dots of diameter \Prm{dotsize} are +placed to mark the positon of the control points specified. This +may be useful for checking your data.\par\filbreak + +\medskip +{\btt\char'134 special\char'173 tyl ttspline} \Opt{measure} +\Opt{transform}\par +\hfil \Opt{vector}\Opt{s-type}\Opt{closure} +{\leavevmode\hbox{$\>\lbrack${\btt L}$\>\langle style\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\rbrack$}} \par +\hfil{\leavevmode\hbox{$\>\lbrack${\btt X}$\>\langle dotsize\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\rbrack$}} +\Prm{numpts}\Coma +$x_1\, \Coma\> y_1\, \Coma\>\ldots\>\Coma\> +x_{\rm numpts}\,\Coma\> y_{\rm numpts}\,\Coma\>$\par +\hfil $thick_1\, \Coma\>\ldots\> +\Coma\> thick_{\rm numpts}$ {\btt \char'175} \par + +\noindent draws a smooth spline through the integer points $x_1 , \; y_1 ,\; +\ldots$ using a\index{{\bf ttspline}} +line of varying thickness defined by $thick_i$ at each control point\index{ttspline, thicknesses} +$\left( x_i,\; y_i\right)$ (ergo {\underbar t}hick-{\underbar t}hin +splines). The {\btt X} marker is also available for marking the positions +of the specified control points. \par\filbreak + +\medskip +{\btt\char'134 special\char'173 tyl arc} \Opt{measure} +\Opt{transform} \Prm{thick}\Coma\par +\hfil \Opt{vector} +{\leavevmode\hbox{$\>\lbrack${\btt L}$\>\langle style\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\rbrack$}}\Prm{radius}\Coma +{\leavevmode\hbox{$\>\lbrack${\btt @}$\>\langle cent_x\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\langle cent_y\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\rbrack$}}\par +\hfil\Prm{$angle_1$}\Coma \Prm{$angle_2$}{\btt \char'175} \par + +\noindent draws an arc\index{{\bf arc}} of radius \Prm{arc-radius} going counter-clockwise +starting from \Prm{$angle_1$} degrees from zero, and \index{arcs, angles} +finishing at \Prm{$angle_2$} degrees around from zero. If the center point is not specified with +the {\btt @} marker\index{{\tt @}-marker}, the arc is assumed to be centered +at $(0,\, 0)$.\index{arcs, centering} + Ellipses\index{ellipses} can be achieved by a simple scaling + of a closed arc\index{oval, {\it see} ellipse} +since scaling and rotational transformations + are about the {\it center\/} of the primitive.\par\filbreak + +\medskip +{\btt\char'134 special\char'173 tyl label} \Opt{measure} +\Prm{face}\Coma $\;x\, \Coma\> y$\Coma {\btt "}\Prm{string}{\btt "} +{\btt\char'175}\par + +\noindent places a simple label\index{{\bf label}} at $(x,\, y)$ using + a font style\index{labels, font style}\index{labels, face} of +\Prm{face} (currently selectable by an integer: e.g., + |1| is amtt10. See page~\pageref{labelfonts} for a better list). +\Prm{String} is a simple sequence of letters and spaces contained +within matching double quotes ({\btt "}).\index{{\tt "}-marker} +Here, the case of the letters of \Prm{string} is taken verbatim, +and it is {\it not} +interpreted; {\TeX} macros or typesetting commands are not +usable here.\index{labels, strings} If you want to typeset fancier +labels, \TT is too late in the game.\par\filbreak + +The optional parameter +\Prm{measure}\index{measurement}\index{units of measure} is any +of {\btt S}\index{{\tt S}-measure}, + {\btt P}\index{{\tt P}-measure}, +or {\btt M}\index{{\tt M}-measure} +denoting that the integer +points, like $x_1,\; y_1,\;\ldots $ are measured in +scaled-points,\index{scaled points} +printer's-points\index{printer's points}, or millimeters\index{millimeters} +respectively. If none is specified, the measurement +of\index{measurement, default} +printer's-points is assumed. Just to refresh how big each of those units is: +\begin{itemize} +\item there are 72.27 printer's points {\it (pp)\/} per inch +\item and 65536 scaled-points {\it (sp)\/} per printer's point +\item and 25.4 millimeters {\it (mm)\/} per inch +\end{itemize}\par + Also remember that the coordinates for the above +control points (like $x_{left}$ or $x_i$) are in {\it first quadrant} +cartesian coordinate-space\index{coordinate space system}. It is useful not to have to remember some +other coordinate systems, and makes things easier for +the user and user programs to interact with \TTN, which takes care +of such details.\par\filbreak + +\Prm{Thick} is the pixel-thickness\index{line thickness} +\index{pixel thickness} of the vector font\index{vector font} to use. Currently +the range is from about 1 to 12 pixels thick (we'll talk more about these +sizes later). Here are some examples of lines having from 2 to 10 ``pixels'' + in even thicknesses.\index{line thickness, example}\par +\noindent\hskip 1in\begintyl{3truecm}[1in] +\special{tyl beg} +\special{tyl line m 2 2 4 11 26} +\special{tyl line m 4 12 23 15 10} +\special{tyl line m 6 15 20 25 13} +\special{tyl line m 8 26 9 31 23} +\special{tyl line m 10 33 2 33 16} +\special{tyl end}\endtyl +\par\filbreak + \Prm{Vector} refers to the {\it +type\/} of vector\index{vector-types}\index{pens} to use, + namely {\btt C}\index{{\tt C}-marker} for vectors that look as if they are + drawn with a {\it circular\/} ``pen,''\index{circular pen} + {\btt H}\index{{\tt H}-marker} for a {\it horizontal\/} +pen,\index{horizontal pen} + and {\btt V}\index{{\tt V}-marker} for +{\it vertical\/} pen appearance\index{vertical pen}. + A circular pen vector-type is the default\index{vector-types, default}. See also +section~\ref{vect-pens} for examples and a better description.\par\filbreak + +\Prm{Style} \index{line style}\index{{\tt L}-marker}is the + line-style to use when drawing. Currently, \TT is able to +provide solid (style |0|), dotted (style |1|), dashed (|2|), and dot-dashed (|3|) +line-styles.\index{line style, dotted}\index{line style, dashed} +\index{line style, solid}\index{line style, dot-dashed} The solid line-style is +the default. Here are some simple examples of the styles:\index{line styles, examples}\par +\begintyl{3truecm}[1in] +\special{tyl beg} +\special{tyl line m 2 L 0 (2 4 11 26)} +\special{tyl line m 2 L 1 (12 23 15 10)} +\special{tyl line m 2 L 2 (15 20 25 13)} +\special{tyl line m 2 L 3 (26 9 31 23)} +\special{tyl end}\endtyl +\par\filbreak + +\Prm{S-type} is the kind of spline-basis\index{splines, types}\index{splines, basis} +to use when interpolating the spline +through the control points. Currently, {\btt B}\index{{\tt B}-marker} + indicates the {\underbar b}-spline basis\index{B-spline basis} +(which interpolates a spline within the convex hull of the control points), +{\btt I}\index{{\tt I}-marker} indicates an + {\underbar i}nterpolating B-spline\index{interpolating B-spline, basis} (goes through the points +specified), {\btt D}\index{{\tt D}-marker} for the Cardinal +basis,\index{Cardinal basis} +and {\btt K}\index{{\tt K}-marker} which +indicates the Catmull-Rom basis\index{Catmull-Rom basis} (which also + interpolates a spline {\it through\/} the control points). The +Catmull basis is the default\index{splines, default basis} spline type in the current +implementation.\par\filbreak + +\Prm{Closure}\index{closure}\index{splines, closure} is used to +indicate whether the spline is a closed \index{closed splines} +curve (the endpoints overlap), or an open curve\index{open spline} (the +default)\index{splines, default closure}. We use +the iconography of {\btt O}\index{{\tt O}-marker} for a closed curve, + and {\btt U}\index{{\tt U}-marker} for an +open-ended curve.\par\filbreak + +Now we come to describe what \Prm{transform} is all about. \TT +allows the user to modify the coordinates of the control points without +having to re-calculate their new positions by himself. +\index{design decisions}I tried to make the specification and modification +of {\it \TeX tyl's\/} primitives as painless and intuitive\index{user intuition} as possible. We +usually think more in terms of connecting dots and placing graphic elements, + and not in terms of slopes, tangents and velocites which are messy at best, +and get more cumbersome from there.\par\filbreak + +Geometric transforms\index{transformations, {\it see } transforms} +\index{geometric transforms} like scaling +(independently in the $X$ and $Y$ directions), rotating about the ``center'' +of the graphic object (a primitive or a figure), and translating in the $X$ and $Y$ directions are +available for most of the primitives. The +format\index{{\bf transform}} for specifying some transformation on +the currently-specified points\index{transforms, parameters, format} +is:\par +\qquad{\btt T}\Coma\Prm{Sx}\Coma\Prm{Sy}\Coma\Prm{Tx}\Coma\Prm{Ty}\Coma\Prm{Rot}\Coma\par +\noindent where \Prm{Tx} and \Prm{Ty} are translations of the object in + the $X$ and $Y$ direction by some signed distance according to the +current units of \Prm{measure}. \Prm{Rot} is a signed integer angle (in +degrees) by which +to rotate the primitive or figure counter-clockwise about its center. + \Prm{Sx} and \Prm{Sy} are\index{transforms, parameters} +{\it integer\/} scale parameters representing the {\it floating-point\/} values of the +transform multiplied by 100 and truncated. +To obtain any transform, {\it all\/} the transform parameters must be +specified\index{transforms, parameters, requirement}.\par\filbreak + +Two other special types of graphics capabilities are meant to be utilized + by a +knowledgeable program, such as the music-typesetting\index{music} system being written at +the Ohio State University. These are:\par +\medskip +{\btt\char'134 special\char'173 tyl tieslur} \Opt{measure} + \Prm{minthick}\Coma \Prm{maxthick}\Coma\par +\hfil \Prm{numpts}\Coma +$ x_1\, \Coma\> y_1\, \Coma\>\ldots\>\Coma\> +x_{\rm numpts}\,\Coma\> y_{\rm numpts}${\btt\char'175}\par + +\noindent which draws a smooth spline curve through the + points\index{{\bf tieslur}}\index{slurs}\index{ties} +$\left(x_i,\;y_i\right)$, +and uses a built-in algorithm to figure out the correct thicknesses of the +tie/slur between \Prm{minthick} and \Prm{maxthick}. These control points + are also in first quadrant cartesian coordinates, and a circular-pen +vector-type is used to draw the +spline.\index{tieslur, pen type}\index{tieslur, thicknesses}\index{tieslur, +vector type}\par\filbreak + +\medskip +{\btt\char'134 special\char'173 tyl beam} \Opt{measure} \Prm{staffsize}\Coma +\Opt{beamtype}\par +\hfil $x_1\, \Coma\> y_1\, \Coma\> x_2\, \Coma\> y_2${\btt\char'175} \par + +\noindent draws a music beam\index{{\bf beam}} from $\left(x_1,\;y_1\right)$ to + $\left(x_2,\;y_2\right)$ (also in first quadrant space) +using a beam of \Prm{beamtype}\index{beam-types} + {\btt G}\index{{\tt G}-marker} for a {\it grace\/}-note sized +beam,\index{beams, sizes} + or {\btt R}\index{{\tt R}-marker}\index{beams, default size} (the default) for +{\it regular} sized beams in the specified +staff-size\index{beams, staff size}. + For a description of staff sizes, see \cite{ross}.\par\filbreak + +Finally, there are two more |\special|s that \TT can +understand. These are used to group any of the above graphic primitives together +into a ``symbol.''\index{symbol, {\it see} figure} The commands are:\par +\medskip +{\btt\char'134 special\char'173 tyl beginfigure} \Opt{measure} +\Opt{transform}\par +\hfil{\leavevmode\hbox{$\>\lbrack${\btt W}$\>\langle width\/\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\langle height\rangle\,\rbrack\,$}} +{\leavevmode\hbox{$\>\lbrack${\btt F}$\>\langle width\/\rangle\, +\raise 2.5pt\hbox{\btt ,}\,\langle height\rangle\,\rbrack\,$}} +{\btt\char'175}\par +\noindent which opens a level of definition\index{{\bf beginfigure}}, +and\par +\medskip +{\btt\char'134 special\char'173 tyl endfigure}{\btt\char'175}\par +\noindent which closes that level of definition\index{{\bf endfigure}}. These are analagous to +{\it push} and {\it pop} kinds of operations, with many levels of +recursive definition available. The optional {\btt F} +marker\index{{\tt F}-marker} specifies the final optimal + width and height of the figure,\index{figures, fitting to size} +in terms of units of \Prm{measure}. This is useful for fitting a figure to a +specific size, so that you do not have to compute the scaling parameters +by yourself. This ability is often desireable if the figure was created by +some program that output the figure at a different scaling factor than you +require on the page. The {\btt W} marker\index{{\tt W}-marker} indicates the +width and height of the figure at the size that it was originally written, +which we assume the figure-making program output along with the definition +of the figure elements.\index{programs making figures}\index{graphic editors} + For most + practical purposes, you can let \TT\ +compute the size of the figure as it was originally created, and then let it +fit the figure to the sizes requested by the {\btt F} marker.\par + +Besides the implicit transform parameters created by using the {\btt F} +and/or {\btt W} markers, an explicit figure-level +tranformations\index{tranforms, figure-level}\index{figures, tranforms} +can be specified using the \Prm{transform} capability using units of +\Prm{measure} (or the default units of printer's +points).\index{measurement,default} + Also, any transforms applied at a level of +definition are additive\index{transforms, additiveness} +over the lower-level definitions\index{figure definitions} and any +transformations that they may have +locally\index{figures, transforms}.\par\filbreak +%\vskip 10pt +%If this were the {\TeX book}, this paragraph would have three ``dangerous +%bend'' signs in front. \TT currently has a temporary +% ability to alter certain internal global +%variables from the |\special| level. This is meant mostly for debugging, +%hacking, and generally limited use. You are on your own with these, and +% I would discourage much use of it (since it may disappear soon). +% The basic call is\par +%{\btt\char'134 special\char'173 tyl param} \Prm{param-num} \Prm{value}{\btt\char'175}\par +%\noindent where \Prm{param-num} is currently one of\index{{\bf param}} +%\begin{itemize} +%\item {\tt 1}: for changing the current minimum number of intervals per +%spline span +%\item {\tt 2}: for changing the minimum number of intervals per arc +%spline-span +%\item {\tt 3}: for debugging the tie/slur clamping mechanism (skip it or not). +%\end{itemize} +% and \Prm{value} is the new value. For example, +%\begin{verbatim} +% \special{tyl param 1 4} +% \special{tyl param 3 = -1} +%\end{verbatim} +%the first sets the minimum number of intervals per spline span to $4$, and the +%second call says to {\it not\/} skip the clamping mechanism (the |=| sign +%is optional, of course). Once these +%variables are set, they are in effect for the rest of the document, or until +%changed with a matching |\special{tyl param...| invocation. +%See later chapters to understand these terms.\par + +\Makeodd +\chapter{When Things Go Wrong} +Despite the best of examples and directions about careful typing of +\hbox{|\special|} strings, there are times when \TT will +get upset and complain about some situation or input. Fortunately, \TT can +continue from most of them (like missing or incorrect parameters), and +just report them in the |.tlog| log-file\index{{\tt .tlog} +file}\index{{\TT}, {\tt .tlog} log-file} +for you.\index{{\TT}, error handling} An example run of \TT might look +like:\filbreak +\begin{verbatim} + >textyl + This is TeXtyl, version ... + DVI-input File Name: myfile.dvi + DVI-output File Name : + (different than input name)[default of myfile.tyl] + [1] [?2] + Output written on myfile.tyl + Log written on myfile.tlog + Some error(s) occurred. Please check Logfile for details. + Assume that the outputfile is incorrect +\end{verbatim}\filbreak +Rather than annoy you at the terminal with long error messages, \TT puts a +|?|\index{{\tt ?} flag} mark to indicate that some error happened. Since it wrote the +|.tyl|\index{{\tt .tyl} file} output file, \TT must have recovered\index{{\TT}, error recovering} +well enough to finish its job, +but the output probably does not look right. The |.tlog| file might look +like\filbreak +\begin{verbatim} +This is TeXtyl, Version blah... +Reading File: myfile.dvi + [1] [ +Error in fig# 1 on page 2 +Arc Thickness not found. Setting to 1 +2] +Output written on myfile.tyl +Log written on myfile.tlog +\end{verbatim}\filbreak +\noindent which was just a missing parameter to the |\special{tyl arc ...}| string. +You will have to re-edit the file and insert the correct thickness. +\index{{\TT}, error messages} +All the error messages that are written to the |.tlog| file try to pin down +the error to the figure number on the error-containing page. These +references to the position of the error +come from the $n^{\rm th}$ figure on the page (the $n$ count is relative to +each page, and starts from 1), and the page number is from {\TeX}'s +|\count0| register that enumerates pages. + Sometimes \TT +cannot always determine the exact figure on the page +(e.g., if we forget to close a figure definition with an +|endfigure|), and so estimates at least the bad page in question. For the most +part, the error is a just missing parameter, + or a bad parameter to a |\special| string being read by \TTN.\par\filbreak + + However, there are a larger number of errors that \TT +found ``surprising'' \index{errors, internal}\index{surprise errors} +and so marks these errors on your screen as |?! |.\index{{\tt ?!} flag} Most +of these internal errors are based on the functionality of {\DVI}type +concerning {\smallrm TFM} information, and the structure and commands +of the {\DVI} file being read. \TTN, like {\DVI}type, will complain, and +possibly roll over and die gracefully.\par\filbreak + +The other ``surprising'' errors that \TT might complain about are really +internal to \TTN, and constitute a bug,\index{{\TT}, simple problem} or just a +compile-time constant that is too small. These easily-fixed surprises are +\begin{itemize} +\item |too many dvistrings|. This page required more {\DVI} bytes than usual. + Have your local maintainer\index{local +maintainer} increase the size of the internal buffer used for storing a +page's {\DVI} bytes. +\item |too many spline segments required|. The spline you tried to set might +be too large/long for the space allocated for a spline's description. +That size is also a compile-time constant. \TT +will reduce the number of control points that it interpolates so that you +can at least get the output, and so that it does not die ungracefully. +\item |figure definition not closed at end of page|. You forgot a +|\special{tyl endfigure}| command in some figure definition on the page. \TT +will not typeset that figure, and will go on to the next page. +\end{itemize}\par\filbreak +There are also some down-deep errors that could potentially (although +doubtfully) show up. These +are probably some error in the vector fonts being referenced by +\TTN.\index{{\TT}, serious problems} +\begin{itemize} +\item |min radius of vector font is zero|. The referenced vector font's +{\smallrm TFM} information reported that the font's radius size +is smaller than it was designed to be. + \TT will make a temporary fix so that it can +continue, but the output figure will be wrong. Have the local maintainer +re-check the vector fonts. +\item |bad dydx|. This is a rare problem. Somewhere, the code to typeset a +diagonal line segment referenced an impossible $dy/dx$ combination, and cannot find +any vector character to fit. \TT will continue, but you may see a +tiny glitch in your figure. +\item |dx is too big/small|, |dy is too big/small|. This is a problem. For +some reason, a distance was referenced that is out of the range of the +32-bit representation of integers. This really should never happen. +\end{itemize} + +For the most part, \TT can recover from errors that it encounters, and give +a brief summary in the |.tlog| file. Other errors have to do with {\smallrm +TFM} file information, and are outside the scope of \TT to handle +gracefully. The most serious ``surprise'' errors are bugs, and you should +report them directly to me with a copy of the |.tex| file, or at least a +detailed printout from {\DVI}type of the |.dvi| file processed by \TTN.\par + +\Makeodd +\chapter{Design Details} + The top-level of \TT is taken directly from the + {\DVI}type\cite{dvitype}\index{DVItype} + program, with a few +modifications. Most of the diagnostic functionality of {\DVI}type is +maintained, but without the user interface (\TT assumes it is supposed to +process all the pages). + A ``hook'' was inserted into +the program to handle the {\TeX} +|\special|s\index{handling specials}\index{specials, handling by {\TT}} +that \TT understands +(hereafter, ``special'' will refer only to those commands that +\TT understands---other |\special|s are ignored, and simply output +to the {\DVI} file without\index{specials} +modification).\index{DVI file} + The {\DVI}type code was used mostly for its keeping\index{DVI +position coordinates} +track of the current {\DVI}\ {\bf h} and {\bf v} position coordinates +on a page, and handling {\smallrm TFM} information\index{TFM information}.\par + +Basically, as \TT slurps in a {\DVI} file, it processes +``normal'' commands +in a normal way (i.e., just keeping track of positions and counters). + When it reads a |\special| string, it tries to interpret the parameters +and expand the special, producing + commands to typeset the graphic using characters from special fonts. + +The result is a transformed {\DVI} file that now contains +``normal'' (i.e., non-special, `put-that-character-there') dvi-commands +as far as \TT can tell, after taking care of new font definitions +and doing any bookkeeping of counters and internal references.\par + +\section{Vectors} +\label{vectors} +Several design decisions\index{design decisions} were made to give \TT the ability to +typeset the graphics of the complexity that we desire. This ability is +intrinsically bound to the fonts to be used, and the way that we use them. +For this project, I had to create a font of short, oriented line segments\index{vector font}. +This was to minimize the amount of information required to typeset a +curve. One could address each pixel of the virtual device to draw the graphic +(putting hundreds of periods from a font), but that is not +device-independent, and the +amount of data is huge in comparison to using line segments. + These line +segments can be connected together rather smoothly to give the appearance of +a continuous line segment or curve.\par + Using this scheme, described by Nelson +and Saxe\index{Nelson{,} Bruce}\index{Saxe{,} James} + at Carnegie-Mellon University\cite{nelson-saxe}, I am able to typeset the correct +character corresponding to the desired length and angle. I modified their +font those +angles cover the first and fourth cartesian quadrant system, +\index{vector font, range of angles} +and whose vectors are from the origin to points clockwise along the perimeters +of semisquares of decreasing radii\label{semisquare}. They use this scheme in order to use the +longest vectors\index{vector font}\index{vectors, typesetting with} + possible for a given distance (thus minimizing the number of +characters to typeset), and also have shorter vectors for use in tightly +curving lines. They use a semisquare (rather than a semicircle) + for a quick line-tangent intersection test in their algorithm to decide the maximum +length vector to use that has a satisfactory variance from the tangent to the +line. +I really must give correct thanks to Dario Giuse\index{Giuse{,} Dario} + at C-MU\cite{dario} for first +implementing the vector-font typesetting code that I subsequently modified +for \TTN.\par + + I modified the vector font for use with +Metafont~79\cite{knuth-mf}, and was able to describe it +in a device-independent manner. Because of the limitations +of\index{Metafont, limitations} +Metafont~79's\index{Metafont}\index{vector font, dimensions} +and {\TeX}'s representation of character heights and depths, I could not accurately +describe the character dimensions in such a way that I could leave the +low-level typesetting details to {\TeX} +through its idea of {\smallrm TFM} information. Thus, \TT has to take +care of the details of calculating the correct dimensions for each character +of each vector font. This calculation is done, + however, only as a particular font is first +required, and the dimensions\index{vector font, computing dimensions} + are computed on-the-fly using the group of +parameters found in the {\smallrm TFM} file that we have defined for our own +use. After this initial parameter calculation, subsequent references to that +font's {\smallrm TFM} information is accessible via a caching scheme. + The fonts contain such information as the measure of the maximum-length +vector of the font, and the height and width of the pen used to draw the +font ({\it all in scaled points}). \par + +Current plans for the vector fonts are for sizes in the range from about 1 +to 12 ``pixels'' for each of the three types of Metafont pens (circular, +flat horizontal, and flat vertical).\index{vector font, sizes}\index{vector +font, types} The fonts are +actually device-independent in size, as our ``pixel'' is measured in +absolute units of 16384 $(2^{14})$ +scaled-points\index{vector font, pixelsize}. However, there is a step within +Metafont~79 that insures that the vector size is an odd-number of +physical pixels computed at the final output-resolution. This is to avoid +some discretization errors and the accompanying aliasing artifacts. + I expect the vectors drawn \index{vector font, pen-types} +with circular pens (the ``cvec'' fonts)\index{vector font, cvec} to be the +most utilized. Their +endpoints are rounded and are positioned to coincide + so that the segments overlap slightly and +meet up gracefully producing a smoother curve. Here are some examples of +circular, horizontal, and vertical pens that can be used for +different effects:\label{vect-pens}\index{vector font, pens, example}\par +\noindent\hskip 1in\begintyl{35mm}[1in] +\special{tyl beginfigure} +\special{tyl line m 10 c 5 5 10 30} +\special{tyl line m 10 h 15 5 27 30} +\special{tyl line m 10 v 30 15 45 23} +\special{tyl endfigure} +\endtyl\par + +\medskip +{\bf Beams}\par +A similar scheme is used for the beam characters found within the music +fonts\index{beam font}\index{music font}. The beam characters are in two types + (those for grace notes, and\index{beam font, types} +those for regular notes) for the staff sizes\index{staff sizes} of music (numbered 0 +down to 8). See also \cite{ross}.\index{beam font, sizes}\label{beam-chars-sizes} + The font is also a set of short line-segments that will be +connected to create a beam (some other program will have to know about the +details of describing how to attach stems from the beams down to the notes). +However, the beam characters are different\index{beam font, difference from vector font} from the vector fonts in that +each staff size of music has one particular size of beam +characters\index{beam font, relation to staff size} +associated with it.\par + + The beams are designed\index{beam font, design} to appear as if they are drawn +with a flat-edged pen held perpendicular to a ruler (at all orientations). +When a vertical pen is drawn along a path, the actual cross sectional +distance of the line segment decreases with the angle (i.e., it is thickest +when drawn along a line at zero degrees from the horizontal, and thinnest as +it is drawn along a line approaching $\pm 90$ degrees). The way to maintain +the appearance of consistent thickness of the line segments at all drawn +angles is to actually {\it increase\/} the ``height'' of the vertical pen as +a function of the angle from the horizontal. This function was geometrically +derived to be the {\it secant\/} of the angle, which yielded in a scaling +factor to apply to the original definition of the vertical pen's height.\par + +Another difference from the vector fonts is that the beam characters do not +have to cover as large a angular range. The angles from the horizontal are +less than 45 degrees on the average,\index{beam font, range of angles} + and the lengths of the beam characters\label{beamsizes} +are no smaller than the width of a quarter note for that staff size. The +current implementation defines the beam characters in four groups per staff +size: regular beams in lengths\index{beam font, lengths} + of 1.0 and 1.5 quarter-note-lengths, and +grace-note beams in lengths of 0.5 and 0.66 grace-note-lengths.\par + + The scheme +of typesetting is similar to that of the vectors, but an added constraint is +resolved. Since the beam characters use a slightly smaller set of fixed angles from +the horizontal,\index{beam font, constraints} +we have to choose the best beam character to use such that we use +the maximum length beam character {\it and\/} try to obtain the least +deviation from the angle requested to fit the beam font. + The dimensions of these beam characters +are computed only as each music font is required, and a caching scheme +is maintained to avoid unnecessary re-loading of font information and +subsequent definition in the {\DVI} file. \par + +\section{Splines} +\label{splines}\index{splines, families}A second decision\index{design decisions} that I made + for the current implementation of this system +was to use Catmull-Rom\cite{cagd} splines as the default instead of B-splines.\index{splines, default type} The +reasons for this are two-fold: (1) Catmull-Rom splines\index{Catmull-Rom splines} are of the same +family as B-splines, but are {\it guaranteed} to produce a smooth curve {\it +through} the control points, whereas B-splines only approximate within the +convex-hull described by the control points. Therefore, Catmull-Rom splines +are a true interpolant; and (2) when dealing with the ties and slurs,\index{ties}\index{slurs} the +user wants the curve to go through the five points that he specifies (left, +middle and right points). With B-splines, he would have to {\it estimate} +the position of the middle control points in order to get the curve to be +in the correct position. Catmull-Rom and Cardinal splines are just +as easy to calculate, and usually achieve the effects that we need.\par + +I have also experimented with operations on the B-splines to achieve true +interpolation. This method was described by Barsky and Greenberg\cite{barsky} + describing how to re-compute B-spline control-points +so\index{B-splines, recomputing points} +that the resulting spline would interpolate through desired points (inverse +interpolation)\index{splines, inversion}\index{splines, interpolation}. + It actually does not require very hairy mathematics. +Arcs and circles are implemented\index{arcs, representation} + using this spline primitive. The arc\index{arcs, control points} +control-points are computed (or pre-computed in the case of circles, +\index{circles, control points} and\index{circles, representation} +ellipses\index{ellipses} which are just scaled circles) +and then are used in the inversion +procedure so that the resulting B-spline passes smoothly {\it through\/} +those original points. We will later describe further this usefulness of +implementing various graphic objects using lower-level primitives.\par + +I also use the Catmull-Rom interpolation when computing the different +thick\-nes\-ses\index{line thickness} along both the tie/slurs and the var\-iable-thick\-ness splines +(``ttsplines'')\index{ttspline}\index{ttspline, line thicknesses}. + I need to interpolate from the current control-point's +thickness along the curve to the next control-point's thickness, and can do +this smoothly by using the interpolation methods available when computing +the splines anyway.\par + +Since we have the ability to draw splines of varying thickness, we can +easily implement ties and slurs\index{slurs} (those long + arcs connecting groups of notes\index{tieslur, implementation} +on a musical score), since they are splines of usually five control points, +having the specified {\it minthick\/} thickness at the left and right, and +{\it maxthick\/} thickness in the middle. \par + +\Makeodd +\chapter{The Implementation} +\section{Overview} +\TT is currently nearly 9000 lines of Pascal code (not {\smallrm WEB}). It is +a prototype, and {\it not} a product. +Testing was simplified by the ability to pre-view\index{DVI file, previewing} the contents of the +{\DVI} file on Sun workstations using the {\smallrm DVISUN} +\index{DVISUN}\cite{dvisun} program. It was written using +Berkeley Unix\footnote{Unix is a trademark of Bell Laboratories}\index{Unix} + Pascal\index{Pascal}, but is not dependent on that operating system +except for +differences in I/O. There are also differences in +efficiency/ease of reading from files---{\tt read}s versus {\tt get}s. I/O +routines for both byte types (signed and unsigned) + are written and available, and have been set up +for easy porting to other machines.\par + +The idea for handling {\DVI} files is to read each byte +into a buffer until we read an {\tt eop} (end-of-page marker), when we will +write that buffer out into a file, and start a fresh buffer with the next +page. If we encounter a |\special| in our reading, we treat it as a +\index{specials, handling}\index{macro-expansion} +macro-expansion---substituting {\it our} byte-string for the byte-string +that represented the invoked special, and put this ``tyled''\index{tyling} string into the +buffer for subsequent output. A nice feature of this slurping is the parser +for the specials. It is simple and extensible enough to easily accommodate +new \TT primitives, and different or additional parameters.\par + +Besides being careful about the expansion of the |\special| string, \TT +has to keep track of any newly-defined fonts for insertion into the +{\tt postamble} in the {\DVI} file, and do some bookkeeping for +{\tt bop} backpointers, and file byte-length.\par + +Most of this chapter discusses the +algorithms and data-structures of \TT at various levels. +We'll start with the high-level and user concepts, and work our way down +into the details of outputting the actual bytes into the {\tt .dvi} file.\par + +\section{Primitives} +The user's interface to \TT is through |.tex| text files.\index{{\tt .tex} +text file} +He types in the |\special| strings for {\TeX},\index{{\TeX}} +and fills in the name of the primitive to typeset +and any parameters to modify the attributes of the +primitive. This |.tex| file is converted by {\TeX} into a |.dvi| file which +is then given to \TTN. +\index{primitives, modifying attributes} +For the most part, all of the graphic primitives\index{primitives} + in \TT have common attributes +of\index{primitives, attributes}\label{prims-attribs} +\begin{itemize} +\item bounding-box\index{bounding box}, +\item line thickness, +\item pen-type (see section~\ref{vect-pens}), +\item line style\index{line style} +\end{itemize} +that describe basic appearances of an item. A ``bounding-box'' +\index{bounding box} describes the +minimum and maximum $X$ and $Y$ values of a minimum-sized +orthogonal rectangle that encloses the primitive. +I'll describe the primitives and +point out their additional or modified attributes to those above. My plan +was to provide a number of primitives that were conceptually built upon +lower-level primitives, and share similar representations wherever possible. +For example, a |tieslur| is clearly built upon the representation\index{tieslur, representation} of a +spline primitive. With this concept, I was able to represent the following +primitives and effectively ``draw'' them by reducing to easier primitives, +\index{primitives, reduction of} down to the vector-font level.\par\filbreak +\medskip +\noindent{\bf Line}\par +The most basic primitive is the |line|, as all other non-figure +primitives\index{line segments}\index{{\tt line}} +reduce to the same routines that produce line-segments. A line has + attributes of bottom-left and upper-right endpoints, +and is drawn from left to right in {\DVI}-space, which is similar to +fourth-quadrant cartesian space, but $y$-values are positive-increasing going down the +y-axis\index{DVI-space}. In section~\ref{vect-setting} I will describe how the line is +``drawn'' on the virtual page using the vector-font characters.\par +\medskip +\noindent{\bf Spline}\par +The spline primitives (|spline| and |ttspline|) have the attributes of a +\index{splines, attributes} +line, and in addition:\index{{\tt spline}}\index{{\tt ttspline}} +\begin{itemize} +\item spline type (see section~\ref{splines}), +\item openness, +\item a count, and a list of control-points. +\end{itemize} +The spline primitives all use the same basic algorithm for interpolation of +its control-points (``knots'') using one of three spline bases: the B-spline +basis, the Cardinal basis, and the Catmull-Rom basis. The difference is mainly +in the choice of basis matrix.\index{splines, basis}\index{splines, B-spline} +\index{splines, Catmull-Rom}\index{splines, Cardinal}\par + +|Ttspline|s have an additional attribute that describes the thickness of the +spline at each control point. \TT uses the same method of +spline\index{{\tt ttspline}} +interpolation for computing the varying thicknesses over the length of the +spline as for computing the position of the line-segment positions over the +spline.\par +\medskip +\noindent{\bf Ties}\par +A |tieslur|\index{{\tt tieslur}} is just a subset of +ttsplines\index{tieslur, relation to ttsplines}. It has exactly $5$ +control-points,\index{tieslur, attributes} +which is sufficient to describe even the longest slur. It needs two +specified line thicknesses: (1) a minimum thickness value at the far end points, +and (2) a maximum thickness in the middle of the slur. \TT uses an internal +algorithm to figure the other thicknesses of the control points. This then +reduces to a ttspline of five control points for interpolation. The only +other difference from a |ttspline| is in the +``clamping'' mechanism\index{splines, clamping}\index{clamping}\index{ttspline, clamping}\index{tieslur, clamping}. + Let me explain: optimally, we would like the smoothest possible transitions +of line thicknesses along a varying thickness spline, but this is still +subject to the aliasing artifacts +(``stair-steps'',\ ``jaggies'')\index{jaggies} of the printing device's +resolution (you can't have 3.3 pixels in black and white). We could have a +vector font for every possible pixel-size of the printer, and thus be able +to achieve as smooth a line as the printer is capable. This could easily +require the printer to use dozens of different fonts per page (imagine a +page of math, text, and a complex figure) which most printers' limited font +memories\index{output device, font memory} cannot handle\par +We are faced with either not being able to print the page (sort of +defeating the whole purpose), or to reduce the number of fonts required to +set that particular figure. This reduction is called ``clamping.'' We make +sure that a requested vector size is in a pre-selected set of fonts, and +then modify that size if it is not in that set. Usually this involves just +adding/subtracting a vector-pixel unit and iterating again through the test-modify +loop until the size fits.\par + +Ties and slurs use the same basic clamping mechanism as |ttspline|s +(described above), but also have a built-in way to select and compute the +thicknesses along the length of the spline. This means that \TT decides the + thicknesses for the tie/slur using its own algorithm based on the user +specifying the maximum and minimum thicknesses.\par + +\medskip +\noindent{\bf Arcs}\par +|Arc|s \index{{\tt arc}} are described\index{arcs, attributes} in terms of a radius, an initial and +final angle, and an optional center coordinate. Internally, this is +transformed into a uniform-thickness spline.\index{arcs, representation} + Closed circles are a special +case\index{circles} of arcs,\index{circles, relation to arcs} +\index{arcs, circles} and so we can pre-compute +the control points of the closed spline\index{arcs, closed splines} to describe the +circle,\index{circles, control points} and then just scale to fit the desired +radius and translate its center to the required coordinate. Ellipses, +\index{arcs, ellipses} \index{ellipses} although not a named primitive, can +be simulated effectively by specifying a closed arc (a.k.a\ circle) and +\index{ellipses, relation to circles} +transform it by scaling as desired in either $X$ and/or $Y$, since circles are a +special case of ellipses.\par + +Open arcs are represented by an open spline\index{arcs, open}\index{arcs, open spline} whose control +points were computed\index{arcs, control points} by sampling along the length +of the arc. We do this sampling in 16 places using the parametric +representation of the arc: +$$x = r \cos\theta \> {,}\>\> y = r \sin\theta \qquad +{\rm\ for\ } \alpha_1 \le \theta \le \alpha_2 $$ and +$\theta$ is a multiple of ${1\over 16} (\alpha_2 - \alpha_1)$. After we obtain +these control points, we can interpolate over the knots and obtain the +spline segments.\par + +In reality, we have to treat arcs with a little more special care +than simple splines. In computing open splines, we have to do some tricks +with the list of control points. We introduce ``phantom'' control +points +which help the endpoints look nicer. See \cite{wu-abel} for a better explanation +of phantoms\index{phantom control points}. The problem with arcs is that the +\index{arcs, phantoming}endpoints would look too ``flat'' if we used the normal phantom-ing method\index{phantoming}. +What I do is to create two extra control points (one before the start of the +actual arc, and one after) so that we preserve roundness by continuing +around the arc with the same parameters to the representation. Then I {\it +lie\/} to \TT 's innards, saying, ``these extra points are not really part +of the arc to typeset. They are the phantoms, so don't compute any for +us.''\index{lies} After that, everything else works pretty much the same as +regular open-splines in ``tyl''-ing\index{tyling}. It should be apparent that splines are +the largest class of primitive types that \TT deals with, since they are +capable of simulating/representing most graphical objects that we ususally +work with.\index{splines, use in simulating}\par +\medskip +\noindent{\bf Beams}\par +The last basic primitive that \TT offers is the |beam|. Beams\index{{\tt beam}} are +graphically equivalent to straight line-segments. The only difference +is\index{beams, difference from lines} +that they have a different font that they use. This font and the particular +characters from it are determined by the beam's two attributes:\index{beams, attributes} staffsize +and beam-type. Staff size refers to the spacing of the staff lines of +a\index{staff sizes}\index{staff lines} +music score, which also determines the size of the music symbols to use. It +is analagous to defining the point size of a character given the interline +spacing measure. See \cite{ross} for examples of each size, also the +discussion of the beam characters on page~\pageref{beam-chars-sizes}. The +beam-type attribute refers to the size of notes that the beam connects: +regular or grace notes. More will be said about beams in +section~\ref{beam-setting}.\par +\medskip +\noindent{\bf Labels}\par +|Label|s\index{{\tt label}} are not really considered primitives, but are included +here for convenience and completeness. They have no correspondence +with any of the other graphic-primitives described above, but may be +included in figure definitions. +Labels have the attributes of starting position, font-style, and +the string-body of the label. They are not transformable at the +local level (but are affected by figure-level transforms), + and are basically pretty simple in nature. {\TeX} macros are not expanded +within the string-body by \TTN; you should use {\TeX} do to any +smarter label-typesetting.\par +Currently, the built-in list of fonts selectable for + use\index{fonts, for labels}\index{labels, font face-styles} in placing +labels is:\label{labelfonts} +\begin{itemize} +\item amtt10 (selectable by specifying face |1|) +\item amb10 (face |2|) +\item amsl10 (|3|) +\item amtt8 (|4|) +\item and amsl8 (|5|) +\end{itemize} +The characters from these fonts are simply set, as \TT does not +worry about kerning or ligatures, and spacing is done with +information found in the parameter section of the |.tfm| file. + This font mapping list is only temporary, and +can be changed within the \TT source program.\par + +\section{Procedural Handling}\label{proc-handling} +After \TT picks apart the |\special| strings\index{special} from the {\DVI} file, +and determines the parameters (both specified and defaulted) for the specified +primitive, \TT makes a note about where in the file the start of the special +occurs, and passes the data to a {\it handler}.\index{handlers} A handler is +a procedure that is specific to each primitive (e.g., there is a +|linehandle|,\index{handlers, linehandle} and a |ttsplinehandle| +procedure\index{handlers, ttsplinehandle}) that knows about the internal +representation of each primitive, and how to ``handle'' the data passed to +it. We'll talk more about the internal representation in the next +section.\par + +The handlers' primary responsibility is to take care of primitive-level +geometric transformations, and then to decide what to do with the data, + depending on the context of\index{handlers, functionality} +the primitive being dealt with. This context is determined by whether the +primitive is contained in a figure, or is by itself. If the primitive is +{\it not} +contained in a figure (i.e., the |\special| string was not within a +|beginfigure| -- |endfigure| pair), the handler +\begin{enumerate} +\item computes the bounding box for the primitive\index{bounding box}, +\item transforms the +coordinates of the primitive into {\DVI}-space\index{DVI-space}, +\item offsets them by the current position on the page, +\item outputs a {\DVI} |push| command,\index{{\tt push}} +\item calls an appropriate procedure to actually typeset the primitive, +\item and finishes with a |pop| command.\index{{\tt pop}} +\end{enumerate} +We need to transform coordinates from our first-quadrant cartesian space +into {\DVI}-space because the lower-level procedures that actually +typeset and output the vector characters assume that they are putting the +characters onto a page of the {\DVI} file.\index{transform to DVI space}\par + +If the primitive's definition is part of an enclosing figure definition, we +delay output of this primitive until the figure is completely defined. The +handler does any simple geometric transformations required, and then + simply packs the data into another structure, and sort of ``stacks'' this +new structure (let's call it an {\it item}\index{item}) onto a list of items +that are contained in this figure. Our reference to ``figure'' +here could also be a sub-figure within an enclosing figure, but for now +we'll just deal with primitives in terms of simple, one-level figures. When +the figure definition is complete, the |figurehandle| +procedure\index{handlers, figurehandle} is called. We will get into figures +more in the next section, but for now, we'll say that this handler +\begin{enumerate} +\item computes the bounding box of all the sub-items of this figure, +taking care of necessary transformations, +\item outputs a |push| command, +\item unpacks each sub-item, and transforms its coordinates into {\smallrm +DVI}-space, +\item calls the item's particular primitive handler with a special flag +that says to simply call the appropriate procedure for immediate typesetting +without doing any further transforms, +\item and finishes with outputting a |pop| command to the {\DVI} +file. +\end{enumerate} +The design of these handlers was to maintain the idea +of\index{handlers, design idea} +``information-hiding'' such that each handler (primitive- or figure-level) +would know only about one level of abstraction below it.\par + +\section{Figures} +Let's look more closely at what we called ``items'' \index{item}in the previous section, +and how we really represent figures. Up to this point, I have been rather +ambiguous when referring to ``primitives.''\index{primitives, definition of} In some cases, it meant +{\it graphic-primitives\/} (like lines and splines); in other cases it meant +{\it the things that we can make pictures with\/} (like figures, sub-figures, +and graphic-primitives). Well, now the ambiguity gets worse. I'll try to be +careful about distinguishing ``graphic-primitives'' when I mean primitives that +are reducible to vector characters, and use ``primitives'' when I mean +graphic-primitives {\it and\/} figures. The reason for +the difference is that since we have the ability to do recursive sub-figure +definitions, a ``figure'' (as denoted by a |beginfigure|--|endfigure| pair) +becomes a building block (just like graphic-primitives) for +that enclosing figure's definition. It is analagous to the programming +language concept of \Prm{block}, where (in BNF notation) +\vspace*{-10pt}\begin{verbatim} + <figure> ::= <primitive> / <primlist> + <primlist> ::= <beginfigure> <primlist> <endfigure> / + <primitive> <primlist> / <empty> +\end{verbatim} +where \Prm{primitive} is what we previously referred + to as an ``item,''\Prm{beginfigure} is + denoted by |\special{tyl beginfigure}|, and +\Prm{endfigure} is denoted by |\special{tyl endfigure}|. Refer back +to page~\pageref{sub-figures} for an example of sub-figures.\par + +\medskip +\noindent{\bf Items}\par +The ``item'' data structure contains the attributes for graphic-primitives, +as outlined in section~\ref{prims-attribs}, and also contains +attributes for a figure like: +\begin{itemize} +\item any figure-level transformation parameters, +\item a ``name,'' +\item and the list of items contained in this figure. +\end{itemize} +As you may surmise, this can yield a linked-list of linked-lists when built +to represent a complex nested figure. In our previous discussion of +handlers, one mode of their operation was to ``pack and stack'' the data +into an item. Packing\index{item, packing} is easy enough to understand, but putting this +structure in the correct place is tricky. When an item is created and filled +with the appropriate parameters in a graphic-primitive's handler, there is a +notion of ``context''\index{figures, context} which refers to the depth of recursion +of sub-figures. A depth of $0$ means that there is no higher-level figure, a +depth of $1$ means that any primitives encountered will belong to an +outermost level figure, etc. When \TT comes across a |beginfigure| special +string, it changes the recursive-definition context, and names that figure +with that depth number. After that, any graphic-primitives that are +encountered belong to that named figure in that context. An |endfigure| +special will decrement the depth of recursion, and thus will change context +back to the previous context. If this new context has a depth of $0$, then +we know we have closed the outermost level of figure definition, and thus +we are ready to typeset the entire figure.\par + +Let's look at how items are inserted\index{item, inserting} onto our data structure so that context +is maintained. \TT uses a procedure called |pushItem| that takes an item and +puts it on the correct list (or sub-list) according to the current figure +context. Roughly, the algorithm is a simple insert, based on a key of +depth-name. +\begin{tabbing} +\hskip 1cm \= Start from the front of the list of this figure\\ + \> while \= the list is not empty\\ +\> \> Look \= at the item\\ +\> \> \> if it is \= a figure of the current context\\ +\> \> \>\> then we are done searching. do an insert\\ +\> \> \> otherwise {\it there must be a sub-figure lower on the +list}\\ +\> \> \> \> look for the next item on the list that is a figure\\ +\> \> \> \> and start the next search from its list +\end{tabbing} +I really simplified the explanation of the +insertion scheme here, but the important idea is that of looking for the +correctly labelled figure-list and inserting the item there.\par + +Once the structure is built, and \TT determines that it is ready to typeset +the entire figure, it traverses\index{item, traversing} the structure to compute and note the +bounding boxes of the sub-figures (and their bounding boxes, too).\index{bounding +box} + We need to do this in case there are any\index{transforms, figure-level} +figure-level scaling or rotations of graphic-primitives which are performed relative +to the center of the bounding box of the primitives contained in the +figure. As we traverse the sub-figures, we do any required sub-figure +transforms, record the dimensions of the bounding box, and pop up a level. +When our traversal has reached the top level, all the figure's primitives +have been transformed according to the recursive definition's specifications +(i.e., the transforms are additive as we descend in recursive +depth).\index{transforms, additiveness} If there are any top-level transforms +to be taken care of,\index{transforms, top-level} we revisit the lists of +primitives, performing the transforms. +Finally, at +this point we are ready to re-traverse the structure, grab each +graphic-primitive, unpack it, transform it into {\DVI}-space, +and give control to its handler for immediate typesetting.\par + +If you really want to get picky, the contents of a figure are not +typeset and output until the last balancing |endfigure|\index{{\tt endfigure}} is encountered. It +is at the current position on the page where this |endfigure| is set that +the origin of our figure is placed. We can get away with this condition +because specials are viewed by {\TeX} as ``boxes'' of zero width, and so a consecutive series of +|\special|s do not change the current position on the page relative to the +first invocation of the list. If, however, the user types in normal +{\TeX}-typesettable text in the middle of a list of |\special|s defining a +figure, the current position will move, and our figure will be shifted down +to the position where the final |endfigure| is invoked. This might make him +unhappy. My advice is to think of the figure/picture as an atomic entity, +whose contents is strictly a list of |\special| strings defining that +figure.\par + + +\section{The Fonts} +The whole basis of this program lies in the ability to typeset graphics with +characters. Thus we have two families of fonts: the vector fonts (originally +designed at C-MU\cite{nelson-saxe} by Bruce Lucas\index{Lucas{,} Bruce}), + and the beam fonts (part of the music +fonts for the {\it MusiCopy\/}\index{MusiCopy} project).\par + +\TT converts the requests for line-drawings into commands to typeset these +characters of line segments. See Appendix~\ref{font-examples} +for examples of these characters. Since Metafont~79\index{Metafont} limits the {\smallrm +TFM} information to 16 heights and depths, we have to do the computations of +the character dimensions ourselves.\index{fonts, computing dimensions of} + This is easy to do as \TT has the +correct dimensions for each character described in Pascal code in such a way +that only a couple parameters from the {\tt .tfm} file need to be accessed +in order for the code to define the exact (internal) dimensions for a font. +In essence, the basic description of the vector and beam fonts are +hard-coded in \TTN , in a manner independent of the actual size of the +pens used to draw them. +This ``on-the-fly'' font calculation is done only as needed, and then the +font information is cached and noted so that future requests for that font +will not require us to re-compute these dimensions.\par + +Within the modified {\DVI} file, +\TT defines these new fonts and begins numbering from 300,\index{fonts, +numbering} as a sort of +``signature.''\index{{\TT}, signatures} So if you look at this new +{\DVI} file with {\smallrm DVI}type, you can tell the parts that are typeset +figures by noting the places in the listing that reference a font numbered +above 300.\par + +\subsection{Vector Setting}\label{vect-setting} The vector fonts themselves, +as described in section~\ref{vectors}, are typeset using the method +described by Nelson\cite{nelson-saxe}, and I'll describe how \TT does it. In +section~\ref{proc-handling}, we made mention that a graphic-primitive's +handler call an ``appropriate procedure to actually typeset the primitive.'' +This typesetting procedure is actually the ``hook''\index{programmer's hook} +for a programmer to get right to the typesetting code. The procedures look +like |Tyl|$x$, where $x$ is a graphic primitive (e.g., |TylSpline|, +|TylArc|, etc.), and take as parameters the information equivalent to the +unpacked representation of an item. The coordinates of any points +used are in {\DVI}-space, \index{DVI-space} and in units of +scaled-points. Refer to the code for the formal parameter +list of each |Tyl|$x$ procedure. These hooks call procedures to ``lay'' +line-segments +on the page, after doing some work of clamping\index{clamping}, and opening +the correct font files for the requested +line-thickness\index{line thickness} (thickness{\underbar es} in the case +of |ttspline|s). These procedures, in turn, call |layline|,\index{{\tt +layline}} a procedure that determines the best way to typeset the +line-segment. |Layline| checks to see if the line is strictly horizonal or +vertical so that it can reduce the line to typsetting a {\TeX} rule, and +then just add endpoints for smooth overlap. However, if the line is more +diagonal, we have to go through more work.\par + +Diagonal lines, and certain cases where we think using {\TeX} rules +inappropriate, require potentially using the full set of vector characters. +The |diagonal| procedure intersects the line-segment with the origin of +the semi-square +of the vector font (see also page~\pageref{semisquare}). In essence, it +implements a greedy method by scaling down the radius of the semi-square to find +the longest possible radius of the vector characters such that the far point +of the line-segment lies just outside that radius.\par +\noindent +\begin{figure}[h]\hskip 4cm\begintyl{8cm}[1in] +\special{tyl beginfigure} +\special{tyl line m 2 0 70 32 70} +\special{tyl line m 2 32 70 32 6} +\special{tyl line m 2 0 6 32 6} +\special{tyl line m 2 0 55 16 55} +\special{tyl line m 2 16 55 16 22} +\special{tyl line m 2 16 22 0 22} +\special{tyl line m 2 0 46 8 46} +\special{tyl line m 2 8 46 8 30} +\special{tyl line m 2 0 30 8 30} +\special{tyl line m 2 0 42 4 42} +\special{tyl line m 2 4 42 4 34} +\special{tyl line m 2 0 34 4 34} +\special{tyl line m 2 0 40 2 40} +\special{tyl line m 2 2 40 2 36} +\special{tyl line m 2 0 36 2 36} +\special{tyl line m 2 0 38 32 38} +\special{tyl line m 8 0 38 25 54} +\special{tyl endfigure}\endtyl +\caption{Semi-squares of the Vector Fonts} +\end{figure} +\noindent Then |diagonal| +determines the $dy$ and $dx$ from the current position to that intersection +point on the line.\footnote{Thus $dx$ and $abs(dy)$ are integer powers of 2 +between 0 and 16 inclusive.} + We use the mapping \index{vector font, mapping function} +function similar to \cite{nelson-saxe} to determine character code corresponding to these +$dy$ and $dx$ values:\goodbreak +\vspace*{-10pt} +$$ code = 160 + dy + dx - 9*{\rm max}\,(dx,\, -dy)\qquad {\rm\ for\ } dy < 0 \> {, +}\>\> dx \geq 0$$ +$$ code = 160 + dy - dx - 7*{\rm max}\,(dx,\, dy)\qquad {\rm\ for\ } dy \geq 0 \> {, +}\>\> dx \geq 0$$ +but this scheme assumes that our font has at least 160 characters (i.e., +256), but most fonts have only 128 characters. We have to re-map this +discontinuous set of codes to fit with a range of $0 \ldots 127$, and in doing so, +we have to lie\index{lies} about two of the characters by pretending that +the two longest vertical vectors do not exist, but each is + to be replaced by {\it two\/} vectors of half that length.\par + +Once we have determined the vector character, all we have to do is move to the +current-position, set the character, increment our position, +and finish setting the rest of this line-segment. The +thickness of the vector theoretically does not matter, as the path followed +by the vector character is invariant over the thickness (at least to the +resolution of the printer).\index{vector font, path invariance}\par + +\subsection{Beam Setting}\label{beam-setting} +The way that \TT typesets beam is similar to typesetting +line-segments.\index{beams, typesetting} + The +|TylBeam| procedure takes care of determining the correct beam character to +use. Recall from section~\ref{beam-chars-sizes} that there are two lengths +for each type of quarternote (i.e., regular notes and grace notes). When \TT +tries to typeset the beam, it uses the beam character whose length is +longest {\it and\/} whose angle is closest to that required.\par + + Given a music font of beam characters with their lengths, heights, depths, +and angles from horizontal computed, we try to set the whole beam at once by +the following method: +\begin{enumerate} +\item Compute the $dy$ and $dx$ of the beam, as well as its length and +actual angle from horizontal +\item compute the fractional number of characters needed to typset the beam +for both sizes of beam characters (this is +${{\rm length}_{\rm beam}\over {{\rm length}_{\rm beamchar}}}$) +\item try to bracket a pair of beam characters whose angles are nearest the +actual angle of the beam +\item use the beam character that has the smallest angular deviation from +that of the actual beam +\item typeset the characters along the line from the left +endpoint of the beam to as close to the right endpoint as possible. Then +typeset the last character such that the right-hand-side of the character +coincides with the right endpoint of the beam. +\end{enumerate} + We only need to select one character to use for typesetting as the +slope of the beam is constant over its length, and the character used has a +``slope'' (angle from horizontal) that is as close as possible to the +beam.\par +This juggling of ``best-length'' versus ``best-slope'' is only necessary +because of the need to keep the set of characters to a reasonable size, and +also because the angles required for beams is not as broad as for the +requirements of the more-general vector line-segments.\par + +\section{Buffering} +As \TT reads in bytes from the {\DVI} file for subsequent interpretation, it + copies them +into an internal buffer. At a simple level, this buffer is used to simply +copy the {\DVI} bytes used on a {\DVI} page (delimited by |bop| and |eop| +bytes). Thus, \TT would act simply as a mechanism that copies its input to +its output, verbatim. At the level that {\it we} are interested in, this +buffer will hold all the bytes up to, and including a |tyl| special string. +On page~\pageref{proc-handling}, we made mention of a ``note about where the +start of the special occurred'' in the {\DVI} file. When we read +a\index{specials}\index{tyling} +|special|, we mark the position of the beginning byte of the special, as +found in our buffer. If we find that the special is ``tyl''-able, we back up +the current place in the buffer to the start of the special, and proceed +with the tyling. \TT will output typesetting command bytes, and effectively +over-write the previous |special| string in the buffer, achieving a kind of +in-line macro-expansion of the special.\index{macro-expansion}\par + +A tricky part of this macro-expansion approach is taking care of defining +new fonts that were used during tyling on a page. As \TT ``tyl''s a figure, +it records the used font names (here, only vector or beam fonts) in a list +of ``fonts-to-be-defined.''\index{fonts, to be defined}\index{fonts, defining} + At the end of a page, we formally define these +as yet undefined fonts within the {\DVI} file, and then mark them as having +been {\DVI}-defined to avoid re-definition before the postamble. Even +this scheme needs cleverness since we do not know all the fonts used to +typeset any primitive until the end of the page, but we have to define the +font within the {\DVI} file before the first actual use of the font to typeset +those graphic primitives.\par + +The way we get around this ``Catch-22''-ish situation is to have an internal +flag (a ``font-flag'')\index{fonts, font flag} +inserted into the buffer before the first commands to typeset a graphic +primitive. Since the {\DVI} format\index{DVI format} allows us to + define fonts\index{defining fonts} between any two +{\DVI} commands in a file, we can define them mid-stream. +As \TT parses a graphic primitive's +|special| string, it backs up in the buffer to the start of the special, +outputs the font-flag and then continues to insert the tyling commands into +the buffer until the next special, or the end of page. At the end of a page, +all the tyl-able |specials| have been expanded, we have buffer full of {\DVI} +commands and font-flags for this page, and a list of fonts ready for initial +definition in the {\DVI} file. We are now ready to write the buffer to the +actual file. As \TT writes each byte of the buffer to the disk file, it +first looks at the byte. If it is ``normal'' (i.e., $0\ldots 255$), it +converts the byte to the proper system-dependent format (if necessary) and +outputs it to the disk file. However, if the byte is our font-flag, it +treats this flag as a macro, too, and writes out to the file the formal {\DVI} +definitions of the new fonts. \TT does this expansion only once per page, +and ignores any other font-flags for the rest of the page (well, it actually +outputs them as |nop|s). After these new fonts have been defined, \TT +continues to output each byte of the page buffer, and when done, starts +processing on the next {\DVI} page for tyling.\par + +\section{Odds 'n Sods} +This section contains down-deep information in \TT that really does not fit nicely +anywhere else.\par +As I discussed before, \TT is built on top of the {\DVI}type\index{DVItype} +program\cite{dvitype} and was modified in following ways: +\begin{itemize} +\item The |specialcases| and |skippages| procedures were modified to call +{\TTN}'s |mainhandlespecials| procedure to handle any |\special| strings, +instead of throwing those bytes out. +\item The |readpostamble| procedure was changed so that we can insert all +the font definitions of the new fonts that we used during any tyling. \TT +simply copies to the internal buffer any font definitons already in the +postamble\index{postamble}, until it reaches a |postpost|. Here \TT backs up one byte (over +the |postpost|), outputs all its new fonts, and then inserts the new +|postpost|. +\item The |main| loop was modified so that at each end-of-page, we write out +the internal buffer, clear it, and reset any internal counters for the page +(like figure-depth context, figure-number, and counts of +fonts-to-be-defined). +\end{itemize}\par +\medskip +\noindent{\bf Other Notes}\par +I have implemented an adaptive sub-division method for determining an +optimal number of vector characters with which to typeset a splines. +\index{splines, typesetting} +The method uses a simple quadrature\index{subdivision of splines} + sub-division on each span of the spline until a linear-distance criterion +is met. If we let the number of sub-divisions be $N$, +we can determine the near-optimum number of +intervals with which to actually sample the spline when we do the +interpolation as $2^N$. + This is ``optimal'' in that we use the fewest vectors for long +spans, and do not under-sample shorter, tighter spans, and achieve a spline +that is very smooth.\par +The names of the primtives\index{primitives, names} within the |\special| +strings need be unique only to the first three letters. Thus +|\special{tyl beg}| is equivalent to +|\special{tyl beginfigure}|. This can make input easier and +shorter.\par + +Also, we can be pretty lenient about how we delimit\index{delimiters} our +keywords\index{keywords} and makers. In most of the examples, commas or +spaces were used to separate the markers and integers. In actuality, we can +use almost anything for keyword and marker delimiting {\it other} than: +\begin{itemize} +\item other alphabetic letters +\item other marker characters (like |@| and |"|)\index{{\tt "}-marker} +\item {\tt\%}, |~|, |\| and those other reserved characters + which might upset {\TeX}, as it +tries to expand macros inside the body of the |special| string before +outputting it to the {\DVI} file. +\end{itemize} +For example, +\hbox{|\special{tyl line *()(]!::4... 3** 4&&12[5}|} +is lexically equivalent to the nicely typed +\hbox{|\special{tyl line m 4 (3,4)(12,5)}|} or the tersely typed +\hbox{|\special{tyl lin m 4 3 4 12 5}|}.\par + +Another ``signature''\index{{\TT}, signatures} of \TT is whenever we output the +commands to typset a line-drawing, we preceed the |push| command with +{\it two} |nop|s. This easily identifies the sections that have been +``tyl''-ed.\par + +\Makeodd +\chapter{Future Extensions} +Given a little time, one could extend\index{extensions} the current set of graphic +primitives in \TTN, such as: +\begin{itemize} +\item simpler-appearing macros, +\item regular polygons (all +easily built upon currently-existing primitives), +\item oriented arrows +\item line-pattern filled figures, +\item a more general method of defining and instancing symbol definitions. +\end{itemize} + I am still experimenting with two +methods of adequately computing the smoothest interpolation of thicknesses +along the length of the slur. When the thickness for a particular segment +of the curve have been determined, we check to see if that thickness is in a +subset of vector-font sizes. If so, we can use it as-is; otherwise, we have +to clamp\index{clamping} that thickness to fit in the subset. The only problem is that +achieving a super-smooth interpolation along the curve's thicknesses might +require a large number of vector fonts to be loaded---sometimes stressing +the printing\index{output device} device's capabilities. I still have to experiment to find a +reasonable subset of these sizes that can be used and still achieve adequate +results.\par + + I wrote this program with the intention of ease +of extensibility for additional ``primitives'' to be built on top of the +functionality provided by \TTN. + I have also interfaced \TT with + Dario Giuse's\index{Giuse{,} Dario} graphic drawing program + {\it DP\/} that he +wrote at C-MU\cite{dario}. It is smart enough to represent its graphics primitives +in files as a list of text-strings, and is now able to output the |\special| +strings, specifying the width and height of the created figure. + Converting the files of the MacDraw program to yield +{\smallrm ASCII} strings is potentially possible, too. +In either case, such strings are be easily converted to +|\special| command strings for \TT to work on.\par +\Makeodd +\appendix +\chapter{{\TeX}tyl Summary} +Let's summarize the abilities and requirements of \TTN . First of all, we +have to put an |\input{textyl}| near the start of the document (at least +before our first invocation of a |\special{tyl ...| command). This loads the +macros that we need to create space for our figure, and to set up the right +environment for \TTN .\par + +Once the macros have been loaded, when we want to set a figure (or even a +single \TT primitive), we must place the primitives within an environment +started by +\hbox{|\begintyl{|\Prm{vertsize}|}[|\Prm{horizsize}|]|} + and finished by |\endtyl|. Here, +the required parameter,\Prm{vertsize}, determines the vertical +size of the box that \TT will create for our figure to be placed in. If we +do not need extra space, we put in |0pt| or some similar zero-length +dimension. The optional parameter,\Prm{horizsize}, will add a non-zero width +to the box that |\begintyl| creates for us. It is {\it crucial\/} that there +is {\it no\/} space between the |}| and |[| characters of the |\begintyl| +invocation if we decide to use the optional horizontal width specification. +Otherwise, things may go awry for this figure. Also, we are responsible for +any offsets that we may need before the figure is placed. We can achieve +this through |\hskip| and |\vskip| calls in \TeX\ , or |\hspace| and +|\vspace| calls in \LaTeX.\index{space} +\index{{\TeX}}\index{{\LaTeX}}\index{{\TeX} commands}\par + +The types of primitives that we may place within the |\begintyl| and +|\endtyl| pair are summarized here, without their surrounding + |\special{tyl | -- |}|, nor any extra delimiting punctuation (like commas). +\begin{verse} +{\tt beginfigure} \sOpt{meas} \sOpt{xfm}\ +{\leavevmode\hbox{$\>\lbrack${\tt W}$\>\langle wid\/\rangle\, +\langle ht\rangle\,\rbrack\,$}} +{\leavevmode\hbox{$\>\lbrack${\tt F}$\>\langle wid\/\rangle\, +\langle ht\rangle\,\rbrack\,$}} \mbox{\it which opens the environment} + +{\tt endfigure}\mbox{\it \ \ which closes the environment} + +{\tt line} \sOpt{meas}\sOpt{xfm} \Prm{thick} +\sOpt{vect}{\leavevmode\hbox{$\>\lbrack${\tt L}$\>\langle style\rangle\,\rbrack$}} + $ x_{\rm l}\> y_{\rm b}\> x_{\rm r}\> y_{\rm t}$ + +{\tt spline} \sOpt{meas}\sOpt{xfm}\Prm{thick} +\sOpt{vect}{\leavevmode\hbox{$\>\lbrack${\tt L}$\>\langle style\rangle\,\rbrack$}} +\sOpt{spltype}\\ +\hspace*{2em}\sOpt{closure} +{\leavevmode\hbox{$\>\lbrack${\tt X}$\>\langle thick\rangle\,\rbrack$}} +\Prm{numpts}\mbox{\it the x-y points} + +{\tt ttspline} \sOpt{meas}\sOpt{xfm} +\sOpt{vect}{\leavevmode\hbox{$\>\lbrack${\tt L}$\>\langle style\rangle\,\rbrack$}} +\sOpt{spltype}\\ +\hspace*{2em}\sOpt{closure} +{\leavevmode\hbox{$\>\lbrack${\tt X}$\>\langle thick\rangle\,\rbrack$}} +\Prm{numpts} \mbox{\it points} \mbox{\it thicknesses} + +{\tt arc} \sOpt{meas}\sOpt{xfm} \Prm{thick}\sOpt{vect} +{\leavevmode\hbox{$\>\lbrack${\tt L}$\>\langle style\rangle\,\rbrack$}}\Prm{radius}\\ +\hspace*{2em}{\leavevmode\hbox{$\>\lbrack${\tt @}$\>\langle cent_x\rangle\, +\langle cent_y\rangle\,\rbrack$}}\Prm{startAng} \Prm{stopAng} + +{\tt label} \sOpt{meas} +\Prm{face}$\;x \> y$ \mbox{{\tt "}\Prm{string}{\tt "}} + +{\tt tieslur} \sOpt{meas} \Prm{minthick}\Prm{maxthick} +\Prm{numpts}\mbox{\it points} + +{\tt beam} \sOpt{meas} \Prm{staffsize} +\sOpt{beamtype} $x_1 \> y_1\> x_2\> y_2$ + +where: +\end{verse} +\begin{description} +\item[meas] specifies units of length for this primitive. One of |S|,|P|, or +|M| indicates scaled-points, printers-points, and millimeters, respectively. +Defaults to printers-points. + +\item[xfm] specifies a transformation to be applied. It is of the form\\ +\mbox{{\tt T}\Prm{sx}\Prm{sy}\Prm{tx}\Prm{ty}\Prm{rot}}, where {\it sx\/} and +{\it sy\/} are for scaling, {\it tx\/} and {\it ty\/} are for translation, +and {\it rot\/} is for counter-clockwise rotation (in degrees). + +\item[thick] is the integer thickness of the line. Usually between 1 and 12. + +\item[vect] is the type of vector font to use. One of |C|, |H|, or |V| +indicates circular, horizontal-flat, or vertical-flat pen type. Defaults to +circular pen. + +\item[style] is the line-style to use. One of |0|, |1|, |2|, or |3| indicates +a solid, dotted, dashed, or dot-dashed line-style. Defaults to solid line. + +\item[spltype] is the kind of spline to use through the control points. One of +|B|, |D|, |K|, or |I| indicates the B-spline, Cardinal, Catmull-Rom, or +Interpolating b-spline basis to use, respectively. Defaults to Catmull-Rom. + +\item[closure] is one of |O| (``oh'') or |U| which indicates that the spline +is closed or open, respectively. Defaults to open. + +\item[numpts] is the integer number of control points for this spline. + +\item[radius] is the length of the radius in units specified by \Prm{meas}. + +\item[centx] and {\bf centy} are the center-point coordinates + of the arc/circle. + +\item[startAng] and {\bf stopAng} are the initial and final angles, +respectively, for the arc as measured in degrees counter-clockwise from the +positive x-axis. If they are the same number, a closed circle is indicated. + +\item[face] refers to the style of typeface for the label. +See page~\pageref{labelfonts} for the list. + +\item[string] is the string-body of the label to typeset at the specified +position. + +\item[staffsize] refers to the staff note-size for beams. It is between 0 +and 8, inclusive. + +\item[beamtype] is the type of beam to use. One of |G| or |R| indicates +grace-note size, or regular size beams, respectively. Defaults to regular. + +\item[wid] and {\bf ht} refer to the width and height of a figure, in units +specified by \Prm{meas}. Mainly used in conjuction with |F| (``Fitting'' +size operator) and |W| (``Written'' size marker). +\end{description} +\Makeodd +\chapter{Font Example}\label{font-examples} +% macros for font tables +\def\oct#1{\hbox{\rm\'{}\kern-.2em\it#1\/\kern.05em}} % octal constant +\def\hex#1{\hbox{\rm\H{}\tt#1}} % hexadecimal constant +\def\oddline#1{\cr + \noalign{\nointerlineskip} + \multispan{19}\hrulefill& + \setbox0=\hbox{\lower 4pt\hbox{\hex{#1x}}}\smash{\box0}\cr%was 2.3pt + \noalign{\nointerlineskip}} +\def\evenline{\cr\noalign{\hrule}} +\def\chartstrut{\lower4.5pt\vbox to20pt{}}%was 14pt +\def\beginchart#1{$$\postdisplaypenalty=-10000 \global\count222=0 #1 + \halign to\hsize\bgroup + \chartstrut##\tabskip0pt plus10pt& + &\hfil##\hfil&\vrule##\cr + \lower6.5pt\null + &&&\oct0&&\oct1&&\oct2&&\oct3&&\oct4&&\oct5&&\oct6&&\oct7&\evenline} +\def\endchart{\raise11.5pt\null&&&\hex 8&&\hex 9&&\hex A&&\hex B& + &\hex C&&\hex D&&\hex E&&\hex F&\cr\egroup$$} +\def\:{\setbox0=\hbox{\char\count222}% + \ifdim\ht0>7.5pt\reposition + \else\ifdim\dp0>2.5pt\reposition\fi\fi + \box0\global\advance\count222 by1 } +\def\reposition{\setbox0=\hbox{$\vcenter{\kern2pt\box0\kern2pt}$}} +\def\normalchart{% + &\oct{00x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\oddline0 + &\oct{01x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&\evenline + &\oct{02x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\oddline1 + &\oct{03x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&\evenline + &\oct{04x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\oddline2 + &\oct{05x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&\evenline + &\oct{06x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\oddline3 + &\oct{07x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&\evenline + &\oct{10x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\oddline4 + &\oct{11x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&\evenline + &\oct{12x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\oddline5 + &\oct{13x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&\evenline + &\oct{14x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\oddline6 + &\oct{15x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&\evenline + &\oct{16x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\oddline7 + &\oct{17x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&\evenline} +\font\cv=cvec3 +\vfill\eject +\centerline{Example of |cvec3|}\par +\beginchart{\cv} +\normalchart +\endchart +%\vfill\eject +%\Makeodd +\chapter{Macros and Extended Examples}\label{secapp} +All of the thumbnail figures in this manual were created using the +|\special{tyl...| strings\index{specials} as described, and were placed within an +environment delimited by |\begintyl| and |\endtyl|.\index{{\tt +begintyl}}\index{{\tt endtyl}} This environment allows +the user to specify a vertical and optional horizontal offset from the +``current-position'' on the page. This determines where the origin of the +user's coordinate system is to be placed. Also, this environment sets +parameters so that the user can use tabbing and spacing to align the +\hbox{|\special|} strings as he desires (e.g., to better show the nesting of +figures and graphic-primitives). The macros\index{macros} used are defined +below: +\vspace*{-20pt} + +\bgroup\footnotesize +\begin{verbatim} + % This is textyl.tex + % + % macros for figures for Tyling + % specify : + % \begintyl{vert_dimen}[optional_horiz_dimen] + % (with NO intervening space between the } and the [ chars) + % then the \special{tyl ...} strings + % then you must finish environment with \endtyl + % +\def\begintyl#1{\begingroup\endlinechar=-1\catcode `\^^I=9 + \dimen120=#1 + \ifhmode\toks0={\futurelet\tyltempb\begHtyl} + \let\endtyl=\endHtyl + \else\toks0={\futurelet\tyltempb\begVtyl} + \let\endtyl=\endVtyl\fi + \the\toks0} +\def\begHtyl{\ifx [\tyltempb \let\tylh=\tylHspace + \else\let\tylh=\tylHnospace\fi\tylh} +% +\def\tylHspace[#1]{\setbox0=\hbox to #1\bgroup + \vbox to \dimen120\bgroup\vss} +\def\tylHnospace{\setbox0=\hbox\bgroup + \vbox to \dimen120\bgroup\vss} +% +\def\begVtyl{\ifx [\tyltempb \let\tylv=\tylVspace + \else\let\tylv=\tylVnospace\fi\tylv} +% +\def\tylVspace[#1]{\setbox0=\vbox to \dimen120\bgroup\vss + \hbox to #1\bgroup} +\def\tylVnospace{\setbox0=\vbox to \dimen120\bgroup\vss + \hbox\bgroup} +% +\def\endHtyl{\egroup\hss\egroup\box0\endgroup} +\def\endVtyl{\hss\egroup\egroup\box0\endgroup} +\end{verbatim} + +\egroup +\par +Let's look at a non-trivial example of frequently-used figures. The +original figure is from \cite{ahu}, page 325. I'll give the diagram, and then +the annotated |\special| commands.\par +\begintyl{9cm} +\special{tyl begin /AHU=fig=9.7/} + \special{tyl arc m 2 6 @ 10 46 10 10 /state=s1/} + \special{tyl label m 5 9 46 "s1"} + \special{tyl arc m 2 6 @ 62 20 10 10 /state=s2/} + \special{tyl lab m 5 61 20 "s2"} + \special{tyl arc m 2 6 @ 62 60 10 10 /state=s3/} + \special{tyl lab m 5 61 60 "s3"} + \special{tyl arc m 2 6 @ 104 34 10 10 /finalstate=s4/} + \special{tyl arc m 2 8 @ 104 34 10 10} + \special{tyl lab m 5 103 34 "s4"} +%now draw the connectors + \special{tyl line m 3 16 48 56 59 /s1-s2/} + \special{tyl lab m 1 30 53 "a"} + \special{tyl line m 3 56 59 53 60}% and the arrow + \special{tyl line m 3 56 59 54 57} + \special{tyl line m 3 53 60 54 57} + + \special{tyl line m 3 15 43 56 23 /s1-s3/} + \special{tyl lab m 1 32 30 "e"} + \special{tyl line m 3 56 23 55 25} + \special{tyl line m 3 56 23 53 23} + \special{tyl line m 3 55 25 53 23} + + \special{tyl spline m 3 4 12 52; 62 76; 90,63; 105,44 /s1-s4/} + \special{tyl lab m 1 70 78 "b"} + \special{tyl line m 3 105,42 106 44} + \special{tyl line m 3 105 42 104 44} + \special{tyl line m 3 104 44 106 44} + + \special{tyl line m 3 62 26 62 54 /s3-s2/} + \special{tyl lab m 1 64 38 "b"} + \special{tyl line m 3 62 54 64 52} + \special{tyl line m 3 62 54 60 52} + \special{tyl line m 3 60 52 64 52} + + \special{tyl spline m 3 3 67 55; 80 42; 96 36 /s3-s4/} + \special{tyl lab m 1 76 40 "e"} + \special{tyl line m 3 96 36 95 38} + \special{tyl line m 3 96 36 95 35} + \special{tyl line m 3 95 35 95 38} + + \special{tyl spline m 3 3 69 61; 86 52; 98 40 /s4-s3/} + \special{tyl lab m 1 89 51 "a"} + \special{tyl line m 3 69 61 71 62} + \special{tyl line m 3 69 61 70 59} + \special{tyl line m 3 70 59 71 62} + + \special{tyl line m 3 69 22 96 32 /s2-s4/} + \special{tyl lab m 1 82 24 "e"} + \special{tyl line m 3 96 32, 94 33} + \special{tyl line m 3 96 32 95 30} + \special{tyl line m 3 94 33 95 30} +\special{tyl endfigure} +\endtyl\par +And the text to produce this is: + +\bgroup\footnotesize +\begin{verbatim} +\begintyl{9cm} +\special{tyl begin /AHU=fig=9.7/} + \special{tyl arc m 2 6 @ 10 46 10 10 /state=s1/} + \special{tyl label m 5 9 46 "s1"} + \special{tyl arc m 2 6 @ 62 20 10 10 /state=s2/} + \special{tyl lab m 5 61 20 "s2"} + \special{tyl arc m 2 6 @ 62 60 10 10 /state=s3/} + \special{tyl lab m 5 61 60 "s3"} + \special{tyl arc m 2 6 @ 104 34 10 10 /finalstate=s4/} + \special{tyl arc m 2 8 @ 104 34 10 10} + \special{tyl lab m 5 103 34 "s4"} +%now draw the connectors + \special{tyl line m 3 16 48 56 59 /s1-s2/} + \special{tyl lab m 1 30 53 "a"} + \special{tyl line m 3 56 59 53 60}% and the arrow + \special{tyl line m 3 56 59 54 57} + \special{tyl line m 3 53 60 54 57} + + \special{tyl line m 3 15 43 56 23 /s1-s3/} + \special{tyl lab m 1 32 30 "e"} + \special{tyl line m 3 56 23 55 25} + \special{tyl line m 3 56 23 53 23} + \special{tyl line m 3 55 25 53 23} + + \special{tyl spline m 3 4 12 52; 62 76; 90,63; 105,44 /s1-s4/} + \special{tyl lab m 1 70 78 "b"} + \special{tyl line m 3 105,42 106 44} + \special{tyl line m 3 105 42 104 44} + \special{tyl line m 3 104 44 106 44} + + \special{tyl line m 3 62 26 62 54 /s3-s2/} + \special{tyl lab m 1 64 38 "b"} + \special{tyl line m 3 62 54 64 52} + \special{tyl line m 3 62 54 60 52} + \special{tyl line m 3 60 52 64 52} + + \special{tyl spline m 3 3 67 55; 80 42; 96 36 /s3-s4/} + \special{tyl lab m 1 76 40 "e"} + \special{tyl line m 3 96 36 95 38} + \special{tyl line m 3 96 36 95 35} + \special{tyl line m 3 95 35 95 38} + + \special{tyl spline m 3 3 69 61; 86 52; 98 40 /s4-s3/} + \special{tyl lab m 1 89 51 "a"} + \special{tyl line m 3 69 61 71 62} + \special{tyl line m 3 69 61 70 59} + \special{tyl line m 3 70 59 71 62} + + \special{tyl line m 3 69 22 96 32 /s2-s4/} + \special{tyl lab m 1 82 24 "e"} + \special{tyl line m 3 96 32, 94 33} + \special{tyl line m 3 96 32 95 30} + \special{tyl line m 3 94 33 95 30} +\special{tyl endfigure} +\endtyl\par +\end{verbatim} + +\egroup +\vfill +\Makeodd +\begin{thebibliography}{99} +\typeout{bib} +\bibitem{adobe}Adobe Systems Inc., {\it PostScript Language Reference Manual.} +Addison-Wesley, Reading, MA, 1985. + +\bibitem{ahu}Alfred V. Aho, John E. Hopcroft, and Jeffrey D. Ullman, {\it +The Design and Analysis of Computer Algorithms.} Addison-Wesley, Reading, +Mass. 1974. + +\bibitem{barsky}Brian A. Barsky, and Donald P. Greenberg, ``Determining a +Set of B-spline Control Vertices to Generate an Interpolating Surface.'' +{\it Computer Graphics and Image Processing.} {\bf 14} 3, (Nov. 1980), pp.203--226. + +\bibitem{cagd}Edwin E. Catmull, and Raphael J. Rom, ``A Class of Local +Interpolating Splines.'' {\it Computer Aided Geometric Design.} +Robert E. Barnhill and Richard F. Riesenfeld, eds. + Academic Press, New York, NY, 1974, pp. 317--326. + +\bibitem{dvitype}David R. Fuchs, Howard Trickey, {\it The DVI$\,$type processor.} Program +documentation, 1983--4. + +\bibitem{dario}Dario Giuse, {\it DP---Format of the drawing files.} +Technical Report. Car\-negie -Mellon University Robotics Institute, 1983. + +\bibitem{gourlay}John S. Gourlay, ``A Language for Music Printing.'' +{\it Communications of the ACM\/} {\bf 29} 5, (May 1986), pp. 388--401. + +\bibitem{dvisun}Norm Hutchinson, et al. {\smallrm DVISUN} Program. 1983. + +\bibitem{knuth-tex82}Donald E. Knuth, {\it The \TeX book.} Addison-Wesley, +Reading, Mass. 1984. + +\bibitem{knuth-mf}Donald E. Knuth, {\it \TeX\ and METAFONT: New Directions in +Typesetting.} Digital Press, Bedford, MA, 1979. + +\bibitem{nelson-saxe}Bruce Nelson, and James Saxe, ``Drawing Splines with a +Vector Font.'' +Unpublished technical report. Carnegie-Mellon University, 1980. + +\bibitem{ross}Ted Ross, {\it The Art of Music Engraving and Processing.} +Hansen Books, 1970. + +\bibitem{updike}Daniel Berkeley Updike, {\it Printing Types: Their History, +Forms, and Use.} Harvard University Press, Cambridge, MA, 1937. + +\bibitem{wu-abel}Sheng-Chuan Wu, John F. Abel, and Donald Greenberg, + ``An Interactive Computer +Graphics Approach to Surface Representation.'' + {\it Communications of the ACM\/} {\bf 20} 10, (Oct. 1977), pp. 703--712. + +\bibitem{vanwyk}Christopher J. Van Wyk, {\it A Language for Typesetting +Graphics.} Ph.D. dissertation. Stanford University, 1980. + +\bibitem{zapf}Hermann Zapf, {\it The Printing Salesman's Herald.} Book 39. +Champion Papers, New York, NY, 1978. +\end{thebibliography} +\Makeodd +\begin{theindex} +\newcommand{\largeletter}[1]{{\pagebreak[2]\Large\hspace{-.5in}\parbox[t]{.5in}{\makebox[.35in][r]{\uppercase{#1}}}\nopagebreak[4]\vspace{-1.5ex}}} +\item {\tt "}-marker 19, 48 +\item {\tt .dvi} file 3 +\item {\tt .tex} text file 1, 3, 34 +\item {\tt .tlog} file 4, 23 +\item {\tt .tyl} file 23 +\item {\tt ?!} flag 24 +\item {\tt ?} flag 23 +\item {\tt @}-marker 8, 19 +\indexspace +\largeletter{a} +\item {\tt arc} 36 +\item {\bf arc} 19 +\item arcs 7 + \subitem angles 8, 19 + \subitem attributes 36 + \subitem center 8 + \subitem centering 8, 19 + \subitem circles 8, 36 + \subitem closed splines 36 + \subitem control points 31, 36 + \subitem ellipses 36 + \subitem example 8 + \subitem open 36 + \subitem open spline 36 + \subitem phantoming 37 + \subitem radius 8 + \subitem representation 31, 36 +\indexspace +\largeletter{b} +\item {\tt B}-marker 6, 14, 20 +\item B-spline basis 6, 20 +\item B-splines + \subitem interpolating-type 6 + \subitem recomputing points 30 +\item {\bf beam} 22 +\item {\tt beam} 37 +\item beam-types 22 +\item beam font 29 + \subitem constraints 30 + \subitem design 29 + \subitem difference from vector font 29 + \subitem lengths 30 + \subitem range of angles 30 + \subitem relation to staff size 29 + \subitem sizes 29 + \subitem types 29 +\item beams 16 + \subitem attributes 37 + \subitem default size 22 + \subitem difference from lines 37 + \subitem sizes 22 + \subitem staff size 22 + \subitem typesetting 45 +\item {\bf beginfigure} 11, 22 +\item {\tt begintyl} 1, 3, 4, 12, 57 +\item bitmaps {\it\romannumeral 6} +\item blank space 17 +\item bounding box 34, 38, 41 +\item boxes 1, 3, 9 +\indexspace +\largeletter{c} +\item {\tt C}-marker 20 +\item capabilities {\it\romannumeral 5}, {\it\romannumeral 6}, 17 +\item Cardinal basis 6, 20 +\item cartesian-space 2 +\item Catmull-Rom basis 20 +\item Catmull-Rom splines 5, 30 +\item circles 7, 8, 36 + \subitem control points 31, 36 + \subitem relation to arcs 36 + \subitem representation 31 +\item circular pen 20 +\item clamping 35, 43, 49 +\item closed splines 14, 20 +\item closure 20 +\item combining primitives 9, 10 +\item coordinates 2 + \subitem origin 2 +\item coordinate space system 19 +\item current position 1, 2, 3, 17 +\item curves 5 +\indexspace +\largeletter{d} +\item {\tt D}-marker 6, 20 +\item defaulting values 5 +\item defining fonts 46 +\item delimiters 6, 48 +\item design decisions 21, 27, 30 +\item design goals {\it\romannumeral 5} +\item DVI {\it\romannumeral 5} +\item DVI-filters 4 +\item DVI-space 35, 38, 43 +\item DVI file 27 + \subitem previewing 33 +\item DVI format 46 +\item DVI position coordinates 27 +\item DVISUN 33 +\item DVItype 27, 47 +\indexspace +\largeletter{e} +\item ellipses 19, 31, 36 + \subitem relation to circles 36 +\item {\tt endfigure} 42 +\item {\bf endfigure} 11, 22 +\item {\tt endtyl} 1, 12, 57 +\item errors + \subitem internal 24 +\item extensions 49 +\indexspace +\largeletter{f} +\item {\tt F}-marker 22 +\item figure definitions 22 +\item figures 10 + \subitem context 41 + \subitem defining 11 + \subitem example 12 + \subitem examples 11 + \subitem fitting to size 22 + \subitem nested symbols 11 + \subitem preparation 2 + \subitem sub-figures 11 + \subitem tranforms 22 + \subitem transforms 10, 22 +\item fonts + \subitem computing dimensions of 42 + \subitem defining 46 + \subitem font flag 46 + \subitem for labels 38 + \subitem numbering 43 + \subitem to be defined 46 +\indexspace +\largeletter{g} +\item {\tt G}-marker 16, 22 +\item geometric transforms 21 +\item Giuse{,} Dario 28, 49 +\item grace-notes 16 +\item graphic editors 17, 22 +\item grid-origin 3 +\indexspace +\largeletter{h} +\item {\tt H}-marker 20 +\item handlers 38 + \subitem design idea 39 + \subitem figurehandle 39 + \subitem functionality 38 + \subitem linehandle 38 + \subitem ttsplinehandle 38 +\item handling specials 27 +\item horizontal pen 20 +\indexspace +\largeletter{i} +\item {\tt I}-marker 6, 20 +\item Ideal {\it\romannumeral 5} +\item {\tt input} 1 +\item interpolating B-spline 6 + \subitem basis 20 +\item item 39, 40 + \subitem inserting 41 + \subitem packing 40 + \subitem traversing 41 +\indexspace +\largeletter{j} +\item jaggies 36 +\indexspace +\largeletter{k} +\item {\tt K}-marker 5, 20 +\item keywords 6, 48 +\item Knuth{,} Donald 1 +\indexspace +\largeletter{l} +\item {\tt L}-marker 20 +\item {\tt label} 37 +\item {\bf label} 19 +\item labels + \subitem face 19 + \subitem font face-styles 38 + \subitem font style 19 + \subitem strings 19 +\item {\LaTeX} 1, 3, 17, 51 + \subitem {\tt figure } environment 17 +\item {\tt layline} 43 +\item leaving no space 3 +\item leaving white space 3 +\item lies 37, 44 +\item {\tt line} 35 +\item {\bf line} 18 +\item line example 1 +\item line segments 18, 35 +\item line style 20, 34 + \subitem dashed 20 + \subitem dot-dashed 20 + \subitem dotted 20 + \subitem solid 20 +\item line styles + \subitem examples 20 +\item line thickness 2, 18, 20, 31, 43 + \subitem example 20 +\item local maintainer 4, 25 +\item Lucas{,} Bruce 42 +\indexspace +\largeletter{m} +\item {\tt M}-marker 5, 6, 10 +\item {\tt M}-measure 19 +\item macro-expansion 33, 46 +\item macros 1, 9, 57 + \subitem {\it see} {\tt begintyl} 1 +\item markers 6 +\item measurement 19 + \subitem default 19 + \subitem default 22 + \subitem units 2 +\item Metafont 28, 42 + \subitem limitations 28 +\item millimeters 19 + \subitem measurement 5 +\item music {\it\romannumeral 5}, 21 +\item music font 29 +\item MusiCopy {\it\romannumeral 5}, 15, 42 +\indexspace +\largeletter{n} +\item Nelson{,} Bruce 28 +\item nested symbols 11 +\indexspace +\largeletter{o} +\item {\tt O}-marker 14, 20 +\item open spline 14, 20 +\item optional values 5 +\item origin 2 +\item origin of quadrant 17 +\item OSU 14 +\item output device 4, 49 + \subitem font memory 36 +\item oval + \subitem {\it see} ellipse 19 +\indexspace +\largeletter{p} +\item {\tt P}-measure 19 +\item parameters to {\TT} 17 +\item Pascal 33 +\item pens 20 +\item phantom control points 37 +\item phantoming 37 +\item pixel thickness 20 +\item {\tt pop} 39 +\item postamble 47 +\item PostScript {\it\romannumeral 6} +\item preamble 1 +\item preparing a figure 2 +\item primitive 2 +\item primitives 17, 34 + \subitem attributes 34 + \subitem built-up 17 + \subitem combining 9, 10 + \subitem definition of 40 + \subitem invoking 9 + \subitem modifying attributes 34 + \subitem names 48 + \subitem parameters 9, 18 + \subitem reduction of 34 + \subitem scaling; rot\-ating; trans\-lating 9 +\item printer's points 19 + \subitem measurement 2 +\item programmer's hook 43 +\item programs making figures 22 +\item {\tt push} 39 +\indexspace +\largeletter{r} +\item {\tt R}-marker 16, 22 +\item reference point 17 +\item rotation 9, 10 + \subitem using degrees measurement 10 +\item running {\TT} 3 +\indexspace +\largeletter{s} +\item {\tt S}-measure 19 +\item Saxe{,} James 28 +\item scaled points 19 +\item scaling 9 +\item slurs 15, 21, 30, 31 + \subitem {\it see also} ties 16 +\item space 1, 3, 51 +\item space macros 1 +\item special 38 +\item {\tt special} 2 +\item specials 2, 17, 27, 46, 57 + \subitem case insensitivity 6 + \subitem handling 33 + \subitem handling by {\TT} 27 + \subitem punctuation 6 + \subitem typing in 6 +\item {\tt spline} 35 +\item {\bf spline} 18 +\item spline + \subitem B-spline 6 + \subitem Cardinal 6 + \subitem Catmull-Rom 5 + \subitem control-points 5 + \subitem coordinates 5 + \subitem default 5 + \subitem example 5 + \subitem Interpolating B-spline 6 + \subitem ttspline 6 +\item spline curves 5 +\item splines + \subitem attributes 35 + \subitem B-spline 35 + \subsubitem example 15 + \subitem basis 20, 35 + \subitem Cardinal 35 + \subsubitem example 14 + \subitem Catmull-Rom 35 + \subsubitem example 14 + \subitem clamping 35 + \subitem closed 14 + \subitem closure 20 + \subitem default basis 20 + \subitem default closure 20 + \subitem default type 30 + \subitem families 30 + \subitem Interpolating B-spline + \subsubitem example 15 + \subitem interpolation 30 + \subitem inversion 30 + \subitem open 14 + \subitem types 20 + \subitem typesetting 47 + \subitem use in simulating 37 +\item staff-size 16 +\item staff lines 37 +\item staff sizes 29, 37 +\item Standard{,} Paul {\it\romannumeral 1} +\item sub-figures 11 +\item subdivision of splines 47 +\item surprise errors 24 +\item symbol + \subitem {\it see} figure 22 +\indexspace +\largeletter{t} +\item {\tt T}-marker 10, 12 +\item {\TeX} {\it\romannumeral 5}, 1, 3, 17, 34, 51 +\item \TeX book 9 +\item {\TeX} commands 17, 51 +\item {\TT} {\it\romannumeral 5} + \subitem {\tt .tlog} log-file 23 + \subitem error handling 23 + \subitem error messages 24 + \subitem error recovering 23 + \subitem how to read manual {\it\romannumeral 6} + \subitem name {\it\romannumeral 5} + \subitem parameters 17 + \subitem serious problems 26 + \subitem signatures 43, 48 + \subitem simple problem 25 +\item {\tt textyl.tex} file 1 +\item TFM information 27 +\item Thick-n-thin spline 6 +\item ties 15, 21, 30 + \subitem and ttsplines 16 + \subitem example 16 + \subitem {\it see also} slurs 16 +\item {\bf tieslur} 21 +\item {\tt tieslur} 35 +\item tieslur + \subitem attributes 35 + \subitem clamping 35 + \subitem example 16 + \subitem implementation 31 + \subitem pen type 21 + \subitem relation to ttsplines 35 + \subitem representation 34 + \subitem thicknesses 16, 21 + \subitem vector type 21 +\item tranforms + \subitem figure-level 22 +\item {\bf transform} 21 +\item transformations + \subitem {\it see } transforms 21 +\item transforms 9 + \subitem additiveness 22, 42 + \subitem concatenation 11 + \subitem example 10 + \subitem figure-level 41 + \subitem mirroring 10 + \subitem no-op 10 + \subitem parameters 10, 21 + \subsubitem format 21 + \subsubitem requirement 21 + \subitem rotating 9 + \subitem scaling 9 + \subitem sub-figures 11 + \subitem top-level 42 + \subitem translation 9 +\item transform to DVI space 39 +\item translating 9 +\item {\tt ttspline} 35 +\item ttspline 6, 31 + \subitem clamping 35 + \subitem defaults 6 + \subitem example 6 + \subitem line thicknesses 31 + \subitem thicknesses 6, 18 +\item {\bf ttspline} 18 +\item tyling {\it\romannumeral 5}, 33, 37, 46 +\item {\tt tyl} name-string 2 +\item typing in special strings 6 +\indexspace +\largeletter{u} +\item {\tt U}-marker 14, 20 +\item units of measure 19 +\item Unix 33 +\item user's view 17 +\item user intuition 21 +\indexspace +\largeletter{v} +\item {\tt V}-marker 20 +\item vector-types 20 + \subitem default 20 +\item vector font 20, 28 + \subitem computing dimensions 28 + \subitem cvec 29 + \subitem dimensions 28 + \subitem mapping function 44 + \subitem path invariance 45 + \subitem pen-types 29 + \subitem pens + \subsubitem example 29 + \subitem pixelsize 29 + \subitem range of angles 28 + \subitem sizes 29 + \subitem types 29 +\item vectors + \subitem typesetting with 28 +\item vertical pen 20 +\indexspace +\largeletter{w} +\item {\tt W}-marker 22 +\indexspace +\largeletter{x} +\item {\tt X}-marker 18 +\indexspace +\largeletter{z} +\item Zapf{,} Hermann {\it\romannumeral 1} +\end{theindex} + +\end{document} diff --git a/macros/latex209/contrib/textyl/doc/tylout.dvi b/macros/latex209/contrib/textyl/doc/tylout.dvi Binary files differnew file mode 100644 index 0000000000..839e64b1f8 --- /dev/null +++ b/macros/latex209/contrib/textyl/doc/tylout.dvi diff --git a/macros/latex209/contrib/textyl/psrc/h00vars.h b/macros/latex209/contrib/textyl/psrc/h00vars.h new file mode 100644 index 0000000000..e24f051139 --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/h00vars.h @@ -0,0 +1,252 @@ +/* Copyright (c) 1979 Regents of the University of California */ + +/* static char sccsid[] = "@(#)vars.h 1.12 1/22/83"; */ + +#include <stdio.h> + +/* + * px - Berkeley Pascal interpreter + * + * Version 4.0, January 1981 + * + * Original version by Ken Thompson + * + * Substantial revisions by Bill Joy and Chuck Haley + * November-December 1976 + * + * Rewritten for VAX 11/780 by Kirk McKusick + * Fall 1978 + * + * Rewritten in ``C'' using libpc by Kirk McKusick + * Winter 1981 + * + * Px is described in detail in the "PX 4.0 Implementation Notes" + * The source code for px is in several major pieces: + * + * int.c C main program which reads in interpreter code + * interp.c Driver including main interpreter loop and + * the interpreter instructions grouped by their + * positions in the interpreter table. + * utilities.c Interpreter exit, backtrace, and runtime statistics. + * + * In addition there are several headers defining mappings for panic + * names into codes, and a definition of the interpreter transfer + * table. These are made by the script make.ed1 in this directory and + * the routine opc.c from ${PASCALDIR}. (see the makefile for details) + */ +#define PXPFILE "pmon.out" +#define BITSPERBYTE 8 +#define BITSPERLONG (BITSPERBYTE * sizeof(long)) +#define HZ 100 +#define NAMSIZ 76 +#define MAXFILES 32 +#define PREDEF 2 +#ifdef ADDR32 +#define STDLVL ((struct iorec *)(0x7ffffff1)) +#define GLVL ((struct iorec *)(0x7ffffff0)) +#endif ADDR32 +#ifdef ADDR16 +#define STDLVL ((struct iorec *)(0xfff1)) +#define GLVL ((struct iorec *)(0xfff0)) +#endif ADDR16 +#define FILNIL ((struct iorec *)(0)) +#define INPUT ((struct iorec *)(&input)) +#define OUTPUT ((struct iorec *)(&output)) +#define ERR ((struct iorec *)(&_err)) +#define PX 0 /* normal run of px */ +#define PIX 1 /* load and go */ +#define PIPE 2 /* bootstrap via a pipe */ +#define PDX 3 /* invoked by the debugger "pdx" */ +#define releq 0 +#define relne 2 +#define rellt 4 +#define relgt 6 +#define relle 8 +#define relge 10 +typedef enum {FALSE, TRUE} bool; + +/* + * interrupt and allocation routines + */ +extern long createtime; +extern char *PALLOC(); +extern char *malloc(); +extern long time(); +extern intr(); +extern memsize(); +extern syserr(); +extern liberr(); + +/* + * stack routines and structures + */ +struct sze8 { + char element[8]; +}; +extern short pop2(); +extern long pop4(); +extern double pop8(); +extern struct sze8 popsze8(); +extern char *pushsp(); + +/* + * emulated pc types + */ +union progcntr { + char *cp; + unsigned char *ucp; + short *sp; + unsigned short *usp; + long *lp; + double *dbp; + struct hdr *hdrp; +}; + +/* + * THE RUNTIME DISPLAY + * + * The entries in the display point to the active static block marks. + * The first entry in the display is for the global variables, + * then the procedure or function at level one, etc. + * Each display entry points to a stack frame as shown: + * + * base of stack frame + * --------------- + * | | + * | block mark | + * | | + * --------------- <-- display entry "stp" points here + * | | <-- display entry "locvars" points here + * | local | + * | variables | + * | | + * --------------- + * | | + * | expression | + * | temporary | + * | storage | + * | | + * - - - - - - - - + * + * The information in the block mark is thus at positive offsets from + * the display.stp pointer entries while the local variables are at negative + * offsets from display.locvars. The block mark actually consists of + * two parts. The first part is created at CALL and the second at entry, + * i.e. BEGIN. Thus: + * + * ------------------------- + * | | + * | Saved lino | + * | Saved lc | + * | Saved dp | + * | | + * ------------------------- + * | | + * | Saved (dp) | + * | | + * | Pointer to current | + * | routine header info | + * | | + * | Saved value of | + * | "curfile" | + * | | + * | Empty tos value | + * | | + * ------------------------- + */ + +/* + * program variables + */ +extern union display _display; /* runtime display */ +extern struct dispsave *_dp; /* ptr to active frame */ +extern long _lino; /* current line number */ +extern int _argc; /* number of passed args */ +extern char **_argv; /* values of passed args */ +extern bool _nodump; /* TRUE => no post mortum dump */ +extern long _runtst; /* TRUE => runtime tests */ +extern long _mode; /* execl by PX, PIPE, or PIX */ +extern long _stlim; /* statement limit */ +extern long _stcnt; /* statement count */ +extern long _seed; /* random number seed */ +extern char *_maxptr; /* maximum valid pointer */ +extern char *_minptr; /* minimum valid pointer */ +extern long *_pcpcount; /* pointer to pxp buffer */ +extern long _cntrs; /* number of counters */ +extern long _rtns; /* number of routine cntrs */ + +/* + * The file i/o routines maintain a notion of a "current file". + * A pointer to this file structure is kept in "curfile". + * + * file structures + */ +struct iorechd { + char *fileptr; /* ptr to file window */ + long lcount; /* number of lines printed */ + long llimit; /* maximum number of text lines */ + FILE *fbuf; /* FILE ptr */ + struct iorec *fchain; /* chain to next file */ + struct iorec *flev; /* ptr to associated file variable */ + char *pfname; /* ptr to name of file */ + short funit; /* file status flags */ + short fblk; /* index into active file table */ + long fsize; /* size of elements in the file */ + char fname[NAMSIZ]; /* name of associated UNIX file */ +}; + +struct iorec { + char *fileptr; /* ptr to file window */ + long lcount; /* number of lines printed */ + long llimit; /* maximum number of text lines */ + FILE *fbuf; /* FILE ptr */ + struct iorec *fchain; /* chain to next file */ + struct iorec *flev; /* ptr to associated file variable */ + char *pfname; /* ptr to name of file */ + short funit; /* file status flags */ + short fblk; /* index into active file table */ + long fsize; /* size of elements in the file */ + char fname[NAMSIZ]; /* name of associated UNIX file */ + char buf[BUFSIZ]; /* I/O buffer */ + char window[1]; /* file window element */ +}; + +/* + * unit flags + */ +#define FDEF 0x80 /* 1 => reserved file name */ +#define FTEXT 0x40 /* 1 => text file, process EOLN */ +#define FWRITE 0x20 /* 1 => open for writing */ +#define FREAD 0x10 /* 1 => open for reading */ +#define TEMP 0x08 /* 1 => temporary file */ +#define SYNC 0x04 /* 1 => window is out of sync */ +#define EOLN 0x02 /* 1 => at end of line */ +#define EOFF 0x01 /* 1 => at end of file */ + +/* + * file routines + */ +extern struct iorec *GETNAME(); +extern char *MKTEMP(); + +/* + * file record variables + */ +extern struct iorechd _fchain; /* head of active file chain */ +extern struct iorec *_actfile[]; /* table of active files */ +extern long _filefre; /* last used entry in _actfile */ + +/* + * standard files + */ +extern struct iorechd input; +extern struct iorechd output; +extern struct iorechd _err; + +/* + * Px execution profile array + */ +#ifdef PROFILE +#define NUMOPS 256 +extern long _profcnts[NUMOPS]; +#endif PROFILE diff --git a/macros/latex209/contrib/textyl/psrc/makefile b/macros/latex209/contrib/textyl/psrc/makefile new file mode 100644 index 0000000000..3d8c3a4f25 --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/makefile @@ -0,0 +1,23 @@ +# Makefile for TeXtyl +# Tue May 26 1987 John S. Renner +# be sure to edit texpaths.h to reflect local directory conventions +# before compiling +textyl: textyl.pas tylext.o tylext.h + /lib/cpp -P textyl.pas textyl.p + pc -w -c textyl.p + rm -f textyl.p + pc -o textyl textyl.o tylext.o + +SRCS = textyl.pas.aa textyl.pas.ab textyl.pas.ac \ + textyl.pas.ad textyl.pas.ae textyl.pas.af \ + textyl.pas.ag textyl.pas.ah + +textyl.pas: $(SRCS) + cat $(SRCS) > textyl.pas + +tylext.o: tylext.c texpaths.h h00vars.h + cc -c tylext.c + +clean: + /bin/rm -f *.o textyl.p + diff --git a/macros/latex209/contrib/textyl/psrc/texpaths.h b/macros/latex209/contrib/textyl/psrc/texpaths.h new file mode 100644 index 0000000000..17c3a01e2c --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/texpaths.h @@ -0,0 +1,32 @@ +/* + * This file defines the default paths that will be used for TeX software. + * (These paths are used if the user's environment doesn't specify paths.) + * + * Paths should be colon-separated and no longer than MAXINPATHCHARS-1 + * (for defaultinputpath) or MAXOTHPATHCHARS (for other default paths). + */ + +#define MAXINPATHCHARS 700 /* maximum number of chars in an input path */ + +#define defaultinputpath ".:/usr/lib/tex/macros" + /* this should always start with "." */ + +#define MAXOTHPATHCHARS 100 /* other paths should be much shorter */ + +#define defaultfontpath "/usr/lib/tex/fonts" + /* it is probably best not to include "." here to prevent confusion + by spooled device drivers that think they know where the fonts + really are */ +#define defaultformatpath ".:/usr/lib/tex/ctex/macros" +#define defaultpoolpath ".:/usr/lib/tex" + +/*--------------------------------------------------------- + The following is for TeXtyl: the default directory where + the .tfm files for the vector fonts can be found. + it needs the trailing slash , and must be *single* + quoted since Pascal delimits strings that way. +*/ + +#define TYLPATH '/usr/lib/tex/fonts/' + /* The length of the above TYLPATH string */ +#define TYLPATHLEN 19 diff --git a/macros/latex209/contrib/textyl/psrc/textyl.pas b/macros/latex209/contrib/textyl/psrc/textyl.pas new file mode 100644 index 0000000000..ec97c687f6 --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/textyl.pas @@ -0,0 +1,7873 @@ + +(*$b0*) + +program tyldvidvi(input,output); +(* ---------------------------------------------------------- + TeXtyl line-drawing interface for TeX. + copyright (c) 1987 John S. Renner + All rights reserved. + +ABSTRACT: TeXtyl reads in a DVI file, and processes 'specials' + that refer to graphics capabilities that it knows about, + like line, spline, ThickThinSpline, and musical + beams and slurs. TeXtyl then outputs a new DVI file, + with the special-macros expanded and converted to + DVI-commands for character setting. + +DEPENDENCIES: Few assumptions about Pascal are assumed. All + identifiers are unique to eight characters. There are + notes to indicate system-dependencies. + I assume the standard definition of "READ(fil, x)" to be + equivalent to "x := fil^; GET(fil)" , and + "WRITE(fil, x)" == "fil^ := x; PUT(fil)" . + Arrays are passed by reference (VAR) for efficiency. + See also the "sysdependent" procedure; + Problem areas, or areas for expansion are marked with ### + +-------------------------------------------------------------*) +(* Revision History: + Jun. 1986 v1.0 Basic version of TeXtyl + Dec. 1986 v1.1 Added adaptive subdivision for spline + interpolation. Added Cardinal basis. + Mar. 1987 v1.2 Added F and W flags for beginfigure + to allow required and/or actual dimensions + to interface with files output by the + DP drawing program from Carnegie-Mellon + also various fixes + Apr. 1987 v1.3 Added linestyles (dotted, dashed, dotdashed) + +*) + +label + 666, 30; +(*=====================CONST============================*) +#include "tylext.h" +#include "texpaths.h" + +const + TylVersion = 'This is TeXtyl, Version 1.30'; + (* for dvi-commands *) + PUT1 = 133; + SET1 = 128; + PUTRULE = 137; + NOP = 138; + PUSH = 141; + POP = 142; + RIGHTLEFT = 143; + DOWNUP = 157; + FONTDEF = 244; + USEFONT = 236; + OURFONTFLAG = 256; (* our special 'byte' value flag *) + + USESTDAREA = 0; (* flag to use the 'standard' area to find .tfm files *) + + (* some conversions and numbers *) + SPPERPT = 65536; (* scaled points per printers point *) + SPPERMM = 186468; (* scaled pts per millimetre *) + + RADTODEG = 57.29577952; (* degrees per radian *) + DEGTORAD = 0.0174532925; (* radians per degree *) + PI = 3.141592654; + + TWO16 = 65536; (* 2 ^ 16 *) + TWO20 = 1048576; (* 2 ^ 20 *) + TWO23 = 8388608; + TWO24 = 16777216; + TWO27 = 134217728; + TWO31 = 2147483647; (* 2^31 - 1 *) + + BIGREAL = 1.0e30; + MAXVECLENsp = 262144; (* Normal maximum length of longest + * vector-font character in scaled points + *) + (* Music Font dependent constants *) + DOTCHAR = 127; (* ascii number of char that is a dot *) + QNOTEGHUS = 18.0; (* MF: Global Horizontal Units for a Quarternote *) + QNOTEGVUS = 16.0; (* MF: Global Vertical units for a quarternote *) + GBMGHUS = 12.0; (* MF: horizontal units for a grace beam *) + GBMGVUS = 9.0; + + BMSTART = 0; BMEND = 69; (* indices for start/end of the beam chars *) + LOBM1 = 0; (* indices for the regular beam chars that *) + HIBM1 = 34; (* are 1 quarternote long, and *) + LOBM1p5 = 35; (* for those that are 1.5 quarternotes long *) + HIBM1p5 = 69; + + GBMSTART = 70; GBMEND = 105; (* indices for the grace beams *) + LOGBMp5 = 70; (* indices for grace beam chars that *) + HIGBMp5 = 87; (* are 0.5 grace quarternote long, and *) + LOGBMp66 = 88; (* 0.66 grace quarternotes long *) + HIGBMp66 = 105; + + LoVThick = 1; (* Bounds for Vector char thicknesses *) + HiVThick = 13; + + SizVFontTable = 39; (* size of the Vector Font Table *) { 3*HiVThick } + SizMFontTable = 18;(* size of the Music Font Table *) + MAXLABELFONTS = 5; + SizLFontTable = MAXLABELFONTS; (* size of the Label Font Table *) + + MAXCTLPTS = 63; (* max number of control points *) + MAXCTLPTSp3 = 66; (* max control points + 3 *) + ARRLIMIT = 100; (* limit for strings and other arrays *) + MAXSPLINESEGS = 480; (* max number of spline segments *) + MAXOLEN = 128; (* max length of Ostring that holds bytes of dvi cmds *) + MAXTBDs = 50; (* max number of Fonts-to-be-Defined *) + + MAXDVISTRINGS = 600; (* max number of DVI Ostrings per page *) + TFMSIZE = 8000; (* size of TFM array to hold .tfm file info *) + + (* Numeric names for the TeXtyl primitives *) + Aline = 1; (* should be first *) + Aspline = 2; + Attspline = 3; + Abeam = 4; + Atieslur = 5; + Aarc = 6; + Alabel = 7; + Afigure = 8; (* should be last one *) + + MAXFONTS = 60; (* number of TeX fonts to keep track of *) + STACKSIZE = 50; (* size of stack for pushes and pops *) + AREALENGTH = TYLPATHLEN; (* see also "sysdependent" proc for this value*) + + CR = 13; (* numbers of certain ascii characters *) + LF = 10; + HT = 9; + FF = 12; + ERRSIGNAL = '?'; + ERRNOTBAD = 0; + ERRBAD = 1; + ERRREALBAD = 2; + + + READACCESS = 4; + WRITEACCESS = 2; + NOPATH = 0; + FONTPATH = 3; + + + +(*===========================TYPES=============================*) +type + (* ---- Bytes ---- *) + + Inbyt = -128 .. 127; + + OctByt = 0 .. 256; (* DVI commands are 0..255, but we need + one more for an internal flag *) + bytefile = packed file of Inbyt; + + (* ---- Strings ---- *) + asciicode = 32 .. 126; + charstring = packed array [1 .. ARRLIMIT] of char; + ascstring = packed array [1 .. ARRLIMIT] of asciicode; + (* rep for character strings *) + strng = record + len: 0 .. ARRLIMIT; + str:charstring; + end; + (* rep for ascii strings *) + astrng = record + len: 0 .. ARRLIMIT; + str: ascstring; + end; + (* byte strings *) + pOstring = ^Ostring; + Ostring = packed array[1 .. MAXOLEN] of OctByt; + + (* ---- PUBLIC types ---- *) + VThickness = LoVThick .. HiVThick; + VectKind = (VKCirc, VKVert, VKHort); + BeamKind = (regular, grace); + SplineKind = (BSPL, INTBSPL, CATROM, CARD); + LineStyle = (solid, dotted, dashed, dotdash); + ScaledPts = integer; + MusIndex = integer; + VecIndex = integer; + + ThickAryType = array[0 .. MAXSPLINESEGS] of VThickness; + SplineSegments = array[1 .. MAXSPLINESEGS, 1 .. 2] of ScaledPts; + ControlPoints = array [0 .. MAXCTLPTSp3, 1 .. 2] of ScaledPts; + + + (* ----- Private Types ---- *) + FontInfRec = record + Cht, Cdp, Cwd : ScaledPts; + Angle : real; + end; + + pVectFontInfRec = ^VectFontInfRec; (* vector font info *) + VectFontInfRec = record + vkind : VectKind; + DesSize : ScaledPts; + PenSize : ScaledPts; + psize : VThickness; + MaxVectLen : ScaledPts; + FontName : strng; + Cksum : integer; + Isdefined : boolean; + DVIFontNum: integer; + FontInfo : array [0 .. 127] of FontInfRec; + end; + + pMusFontInfRec = ^MusFontInfRec; (* music font info *) + MusFontInfRec = record + DesSize : ScaledPts; + Family : integer; + FontName : strng; + Cksum : integer; + Isdefined : boolean; + DVIFontNum: integer; + Staffsize : integer; + ghu : ScaledPts; + gvu : ScaledPts; + FontInfo : array [0 .. 127] of FontInfRec; + end; + + pLabFontInfRec = ^LabFontInfRec; (* label fonts info *) + LabFontInfRec = record + DesSize : ScaledPts; + FontName : strng; + Cksum : integer; + Isdefined : boolean; + DVIFontNum : integer; + internalnumber : integer; + spacewidth : ScaledPts; + end; + + + (* list of dvi-strings *) + dvistary = array[1 .. MAXDVISTRINGS] of pOstring; + + DVIBuftype = record + TotByteLen : integer; + Numstrings : integer; + curstrindex : integer; + Dstrings : dvistary; + end; + + (* representation of list of fonts that have to be defined + * before we output the BOP of the page we + * just scanned + *) + ToBeDefinedRec = record + which : char; + indx : integer; + end; + + stackrec = record + sh, sv, sw, sx, sy, sz: integer; + end; + + Stacktype = array [0 .. STACKSIZE] of stackrec; + + Oneby4Vector = array[1 .. 4] of real; + Fourby4Matrix = array[1 .. 4, 1 .. 4] of real; + Oneby5Vector = array[1 .. 5] of real; + + Primitive = Aline .. Afigure; + + pItem = ^Item; + figptr = ^Figure; + + Item = packed record + nextitem : pItem; + BBlx, BBby, BBrx, BBty : ScaledPts; (* Bounding box *) + itemthick : VThickness; + itemvec : VectKind; + itempatt : LineStyle; + case kind : Primitive of + Aline : ( lx1, ly1, lx2, ly2 : ScaledPts; + ); + Aspline : ( spltype : SplineKind; + sclosed : boolean; + dosmarks : integer; + nsplknots : integer; + spts : ControlPoints; + ); + Attspline : ( tspltype : SplineKind; + tclosed : boolean; + dottmarks : integer; + nttknots : integer; + ttpts : ControlPoints; + ttarry : ThickAryType; + ); + Abeam : ( bx1, by1, bx2, by2 : ScaledPts; + staf : integer; + bkind : BeamKind; + ); + Atieslur : ( ntknots : integer; + minth, maxth : VThickness; + tspts : ControlPoints; + ); + Aarc : ( acentx, acenty : ScaledPts; + aradius : ScaledPts; + firstang, lastang : integer; + narcknots : integer; + arcpts : ControlPoints; + ); + Alabel : ( labx, laby : ScaledPts; + fontstyle : integer; + labeltext : strng; + ); + Afigure : ( figtheta : real; + fsx, fsy : real; + fdx, fdy : ScaledPts; + preWid, preHt : ScaledPts; + postWid, postHt : ScaledPts; + depthnumber : integer; + body : figptr; + ); + end; + + + Figure = record + things : pItem; + end; + + +(*==============================VARS============================*) +var + (* ----- Private vars *) + catrommtx : Fourby4Matrix; (* basis matrix for catmul-rom splines*) + bsplmtx : Fourby4Matrix; (* basis matrix for B-splines *) + cardmtx : Fourby4Matrix; (* Cardinal spline matrix *) + lastPoint : integer; (* num of output points *) + intervals : integer; (* count of spline interval we are on *) + ourxpos, (* internal x-position on page *) + ourypos, (* internal y-position on page *) + ourfontnum : integer; (* internal number of TeX font currently in use*) + ourpushdepth : integer; (* depth of internal pushes *) + origTexfont : integer; (* number of TeX font in use before tyling *) + + GDVIBuf : DVIBuftype; (* Global DVI buffer that contains a list of + * dvi commands for this page. All dvi-cmds + * parsed are put here and possibly modified + * before being written to the output file + *) + + VFontTable : array [1 .. SizVFontTable] of pVectFontInfRec; + MFontTable : array [1 .. SizMFontTable] of pMusFontInfRec; + LFontTable : array [1 .. SizLFontTable] of pLabFontInfRec; + (* the font tables, and the number of fonts defined in each *) + VFontsDefd, + MFontsDefd, + LFontsDefd : integer; + + GDVIFN : integer; (* dvi font number currently in use *) + + (* table of fonts yet To-Be-Defined *) + TBD : array[1 .. MAXTBDs] of ToBeDefinedRec; + FTBDs : integer; (* number of fonts to be defined for current page *) + + pageitems : pItem; (* list of primitives in current use in the current + * figure on the current page + *) + + TotBytesWritten : integer; + ourq : integer; (* the 'q' for the postpost *) + specstart: integer; (* the place in the DVI buffer where the + * start of the special begins. + * this is so that we know how far to back up + * and over-write the old \special macro string + * with the cmds of our 'macro-expansion' + *) + + multifigure : integer; (* depth of definition recursion of figures *) + didnewfonts : boolean; (* did we define the new fonts for this page? *) + prevfont : integer; (* to keep track of prev font before the + * PUSH and expansion of the special + *) + + pgfigurenum : integer; (* figure number for this page *) + currpagenum : integer; (* number of page we are on *) + skiptsclamp : boolean; (* DEBUG: should we skip post-clamping ties *) + dviBBlx, dviBBrx, (* Bounding box of figure in DVI space *) + dviBBby, dviBBty : ScaledPts; + ErrorOccurred : boolean; (* global flag in case some error happened *) + + + thefilename, realnameoffile : charstring; (* used externally *) + + (* ----- End private vars *) + + + tfmbyte : Inbyt; + + vaxbyt : Inbyt; + + tfm: array[-100 .. TFMSIZE] of OctByt; + + xord: array [char] of asciicode; + xchr: array [0 .. 255] of char; + outname: strng; (* name of output file *) + tfmname : strng; (* name of a .tfm file *) + dvifname : strng; (* name of the input dvi file *) + logfilnam: strng; (* name of the log file *) + + dvifile: bytefile; + tfmfile: bytefile; + outputfil: bytefile; + logfile : text; + + curfont: integer; + s : 0 .. STACKSIZE; + h, v, w, x, y, z: integer; + stack: Stacktype; + + font: array [0 .. MAXFONTS] of + record + num: integer; + name: astrng; + checksum: integer; + scaledsize: integer; + designsize: integer; + space: integer; + bc: integer; + ec: integer; + widths: array [0 .. 127] of ScaledPts + end; + nf : 0 .. MAXFONTS; + + MINREAL : real; (* a system-dependent 'constant' *) + b0, b1, b2, b3: OctByt; + inwidth: array [0 .. 255] of integer; + tfmchecksum: integer; + conv: real; + trueconv: real; + numerator, + denominator: integer; + defaultdirectory: strng; + mag, + magfactor: real; + maxv, maxh, maxs : integer; + maxpages, + totalpages : integer; + resolution: real; + inpostamble : boolean; + newbackptr, + oldbackptr : integer; + p, k : integer; + waste : integer; + + +(* ==================forward declarations============================ *) + +{ These hooks assume that the parameters are filled "correctly", + and are already transformed into 4th Quadrant DVI-space } + + +procedure TylTieSlur (var KnotArray: ControlPoints; + numknots: integer; + minthick, maxthick: VThickness); forward; + +procedure TylThickThinSpline (thetype : SplineKind; + isclosed : boolean; + var KnotArray: ControlPoints; + var ThikThinAry: ThickAryType; + numknots: integer; + vec: VectKind; + patt: LineStyle; + domarks : integer); forward; + +procedure TylSpline (thetype : SplineKind; + isclosed : boolean; + var KnotArray: ControlPoints; + numknots: integer; + thick: VThickness; + vec: VectKind; + patt: LineStyle; + domarks : integer); forward; + +procedure TylLine (xl, yb, xr, yt: ScaledPts; + thickness: VThickness; + vec: VectKind; + patt: LineStyle); forward; + +procedure TylBeam (fromx, fromy, tox, toy: ScaledPts; + staffsize : integer; + kind : BeamKind); forward; + +procedure TylArc (radius : ScaledPts; + centx, centy : ScaledPts; + firstangle, secondangle : integer; + thick : VThickness; + vec : VectKind; + patt: LineStyle); forward; + +procedure TylLabel (xpos, ypos : ScaledPts; + fontstyle : integer; + phrase : charstring; + phraselen : integer); forward; + +(* private procedures *) +procedure definebeams (var M : pMusFontInfRec); forward; +procedure definevectors (var Vec: pVectFontInfRec); forward; +procedure defineNewfonts; forward; +procedure doTylArc (iscircle : boolean; var apts : ControlPoints; + numknots : integer; thick : VThickness; + vec : VectKind; patt : LineStyle); forward; +procedure strcopy (src : charstring; var dest : charstring; + len : integer); forward; +procedure writestrng (s :strng; tologfile : boolean); forward; +(* end private procs *) + +{------------------------------------------------------} +procedure jumpout; +begin + goto 666; (* global label *) +end; + + +(*-------------- System Dependent stuff ----------------------*) +(* the default-directory should be where the .tfm files are + * to be found. the string len should reflect this name. + * Check with the local site maintainer about any necessary + * additions to the reset and rewrite procedures for opening + * 8-bit binary files. + *) + + + + + +procedure sysdependent; + begin + + + setpaths; + + defaultdirectory.str := TYLPATH; + defaultdirectory.len := TYLPATHLEN; (* AREALENGTH const should be this, too *) + writeln(TylVersion,' for Berkeley Unix'); + + resolution := 300.0; (* just a number *) + MINREAL := 1.0e-20; (* so that we avoid some underflows *) + end; + +{------------------------------------------------------------} +procedure complain (severity :integer); +begin + writeln(logfile,'Error in fig#',pgfigurenum:0,' on page ',currpagenum:0); + case severity of + ERRNOTBAD : begin + write (ERRSIGNAL); + end; + ERRBAD : begin + write (ERRSIGNAL); + ErrorOccurred := true; + end; + ERRREALBAD : begin + write (ERRSIGNAL,'! '); + ErrorOccurred := true; + end; + + end; (* case *) +end; + +function opendvifile : boolean; +begin + + strcopy (dvifname.str, thefilename, dvifname.len); + thefilename[dvifname.len + 1] := ' '; + if (testaccess (READACCESS, NOPATH)) then + begin + reset (dvifile, realnameoffile); + opendvifile := true; + end + else + begin + writestrng(dvifname, false); + writeln(' : DVI file not found/readable '); + opendvifile := false; + end; + +end; + +function opentfmfile : boolean; +begin + + strcopy (tfmname.str, thefilename, tfmname.len); + thefilename[tfmname.len + 1] := ' '; + if (testaccess (READACCESS, FONTPATH)) then + begin + reset(tfmfile, realnameoffile); + opentfmfile := true; + end + else + begin + writestrng(tfmname, false); + writeln(' : TFM file not fount/readable '); + opentfmfile := false; + end; + +end; + +procedure openoutputfile; +begin + + strcopy (outname.str, thefilename, outname.len); + thefilename[outname.len + 1] := ' '; + if (testaccess (WRITEACCESS, NOPATH)) then + rewrite (outputfil, realnameoffile) + else + begin + writestrng(outname, false); + writeln(' : Output file not writable'); + jumpout; + end; + +end; + +procedure openlogfile; +begin + + strcopy (logfilnam.str, thefilename, logfilnam.len); + thefilename[logfilnam.len + 1] := ' '; + if (testaccess (WRITEACCESS, NOPATH)) then + rewrite (logfile, realnameoffile) + else + begin + writestrng(logfilnam, false); + writeln(' : Log file not writable'); + jumpout; + end; + +end; + + +(* &&Module Tylsupport *) + + +{---------------------------------------------------} +procedure ClearBufString (var s : pOstring); +(* clear a DVI buffer string to contain no-ops*) +var i : integer; +begin + for i := 1 to MAXOLEN do + s^[i] := NOP; +end; + +{---------------------------------------------------} +function NewBufString : pOstring; +var s : pOstring; +begin + new (s); + ClearBufString (s); + NewBufString := s; +end; + + + +(* NOTATION:: + * All procedures that put a dvi-command into the + * temporary buffer are prefixed with "cmd"... + * Functions that deal with reading .tfm files are prefixed + * with "T" or have "tfm" in their names. + * Functions that deal with reading DVI files are + * prefixed with a "D". + *) + +{--------------------------------------------} +procedure cmd1byte (cmd : OctByt); +begin + with GDVIBuf do + begin + if (Numstrings > MAXDVISTRINGS) then (* buffer full *) + begin + complain (ERRREALBAD); + writeln (logfile,'error: too many dvistrings. Totbytes = ',TotByteLen); + jumpout; + end; + if (curstrindex > MAXOLEN) then (* current string full *) + begin + Numstrings := Numstrings + 1; + if (Dstrings[Numstrings] <> nil) then + dispose (Dstrings[Numstrings]); + Dstrings[Numstrings] := NewBufString; + ClearBufString(Dstrings[Numstrings]); + curstrindex := 1; + end; + Dstrings[Numstrings]^[curstrindex] := cmd; (* insert command byte *) + TotByteLen := TotByteLen + 1; + curstrindex := curstrindex + 1; + end; +end; + + +{---------------------------------------------------} +procedure cmd2byte (cmd : integer); +begin + cmd1byte (cmd div 256); + cmd1byte (cmd mod 256); +end; + +{---------------------------------------------------} +procedure cmd3byte (cmd : integer); +begin + cmd1byte (cmd div TWO16); + cmd1byte ((cmd div 256) mod 256); + cmd1byte (cmd mod 256); +end; + +{---------------------------------------------------} +procedure cmd4byte (cmd : integer); +var tmp : integer; +begin + tmp := cmd; + if (tmp >= 0) then + begin + cmd1byte (tmp div TWO24); + end + else + begin + tmp := tmp + TWO31 + 1; (* need the +1 *) + cmd1byte (tmp div TWO24 + 128); + end; + tmp := tmp mod TWO24; + cmd1byte (tmp div TWO16); + tmp := tmp mod TWO16; + cmd1byte (tmp div 256); + cmd1byte (tmp mod 256); +end; + +{---------------------------------------------------} +(* ### may be system dependent as integers are assumed + to be signed 32-bits *) + +procedure cmdSigned (i : integer; numbytes: integer); +var tmp : integer; +begin + if (numbytes = 4) then + cmd4byte (i) + else + begin (* <= 3 bytes *) + tmp := i; + if (numbytes = 3) then + begin + if (tmp < 0) then + tmp := tmp + TWO24; + cmd1byte (tmp div TWO16); + tmp := tmp mod TWO16; + cmd1byte (tmp div 256); + end; + if (numbytes = 2) then + begin + if (tmp < 0) then + tmp := tmp + TWO16; + cmd1byte (tmp div 256); + end; + if (numbytes = 1) then + begin + if (tmp < 0) then + tmp := tmp + 256; + end; + cmd1byte (tmp mod 256); (* for all *) + end; +end; + + + +{---------------------------------------------------} +function Tgetvaxbyte : OctByt; +label 9999; +begin + tfmbyte := tfmfile^; + if (tfmbyte < 0) then + Tgetvaxbyte := tfmbyte + 256 + else + Tgetvaxbyte := tfmbyte; + if (eof (tfmfile)) then + begin + complain (ERRREALBAD); + writeln (logfile,' early EOF of tfm file! '); + goto 9999; + end; + get (tfmfile); +9999: +end; + + +{---------------------------------------------------} +procedure readtfmword; + +begin + + b0 := Tgetvaxbyte; + b1 := Tgetvaxbyte; + b2 := Tgetvaxbyte; + b3 := Tgetvaxbyte; + +end; + + +{---------------------------------------------------} +function DVaxByte : OctByt; +label 99; +begin + vaxbyt := dvifile^; + if (eof (dvifile)) then + begin + DVaxByte := 0; + goto 99; + end; + if (vaxbyt < 0) then + DVaxByte := vaxbyt + 256 + else + DVaxByte := vaxbyt; + get (dvifile); +99: +end; + + + +{---------------------------------------------------} +(* get a byte from the DVI file, but do not copy it into the DVIbuffer *) +function Dgrabbyte : integer; +var + b: OctByt; +begin + if eof(dvifile) then + Dgrabbyte := 0 + else + begin + + b := DVaxByte; + + Dgrabbyte := b; + end; +end; + + +{---------------------------------------------------} +function Dget1byte : integer; +var + b: OctByt; +begin + if eof(dvifile) then + Dget1byte := 0 + else + begin + + b := DVaxByte; + + Dget1byte := b + end; + cmd1byte(b); +end; + +{---------------------------------------------------} +function Dsign1byte : integer; +var + b: OctByt; +begin + + b := DVaxByte; + + if b < 128 then + Dsign1byte := b + else + Dsign1byte := b - 256; + cmd1byte(b); +end; + +{---------------------------------------------------} +function Dget2byte : integer; +var + a, b: OctByt; +begin + + a := DVaxByte; + b := DVaxByte; + + Dget2byte := a * 256 + b; + cmd1byte(a); + cmd1byte(b); +end; + +{---------------------------------------------------} +function Dsign2byte : integer; +var + a, b: OctByt; +begin + + a := DVaxByte; + b := DVaxByte; + + if a < 128 then + Dsign2byte := a * 256 + b + else + Dsign2byte := (a - 256) * 256 + b; + cmd1byte(a); + cmd1byte(b); +end; + +{---------------------------------------------------} +function Dget3byte : integer; +var + a, b, c: OctByt; +begin + + a := DVaxByte; + b := DVaxByte; + c := DVaxByte; + + Dget3byte := (a * 256 + b) * 256 + c; + cmd1byte(a); + cmd1byte(b); + cmd1byte(c); +end; + +{---------------------------------------------------} +function Dsign3byte : integer; +var + a, b, c: OctByt; +begin + + a := DVaxByte; + b := DVaxByte; + c := DVaxByte; + + if a < 128 then + Dsign3byte := (a * 256 + b) * 256 + c + else + Dsign3byte := ((a - 256) * 256 + b) * 256 + c; + cmd1byte(a); + cmd1byte(b); + cmd1byte(c); +end; + +{---------------------------------------------------} +function Dsign4byte : integer; +var + a, b, c, d: OctByt; +begin + + a := DVaxByte; + b := DVaxByte; + c := DVaxByte; + d := DVaxByte; + + if a < 128 then + Dsign4byte := ((a * 256 + b) * 256 + c) * 256 + d + else + Dsign4byte := (((a - 256) * 256 + b) * 256 + c) * 256 + d; + cmd1byte(a); + cmd1byte(b); + cmd1byte(c); + cmd1byte(d); +end; + + +{---------------------------------------------------} +(* write a byte out to the ouput file, but if we + * encounter the font flag, define the new fonts, and + * continue + *) +procedure OutputByte (b : OctByt); +var x : Inbyt; + n : integer; +begin + n := b; + if (n = OURFONTFLAG) then + begin (* our special macro-flag *) + n := NOP; (* nullify it *) + if (not didnewfonts) then + begin + didnewfonts := true; + defineNewfonts; (* expand the defns in the outfile itself *) + end; + end; (* if *) + + if (n > 127) then + begin + x := n - 256; + end + else + x := n; + outputfil^ := x; + put (outputfil); + + TotBytesWritten := TotBytesWritten + 1; (* keep count of all bytes *) +end; + +{---------------------------------------------------} +procedure Output2Byte (i : integer); +begin + OutputByte (i div 256); + OutputByte (i mod 256); +end; + +{---------------------------------------------------} +procedure Output4Byte (i : integer); +var tmp : integer; +begin + tmp := i; + if (tmp >= 0) then + begin + OutputByte (tmp div TWO24); + end + else + begin + tmp := tmp + TWO31 + 1; (* need the +1 *) + OutputByte (tmp div TWO24 + 128); + end; + tmp := tmp mod TWO24; + OutputByte (tmp div TWO16); + tmp := tmp mod TWO16; + OutputByte (tmp div 256); + OutputByte (tmp mod 256); +end; + + +{---------------------------------------------------} + +function rtan (ang : real) : real; +var rads : real; + cosrads : real; +begin + rads := ang * DEGTORAD; + cosrads := cos (rads); + if (cosrads = 0.0) then { this happens at 90 and 270 } + cosrads := cos ((ang - 0.01) * DEGTORAD); + rtan := (sin (rads)) / (cosrads); +end; + +{---------------------------------------------------} +function float (i : integer) : real; +begin + float := i + 0.00; +end; + + +{---------------------------------------------------} +function tolowercase (let: char) : char; +const Diff = 32; (* xord['a'] - xord['A'] *) +var olet : integer; +begin + olet := xord[let]; + if (olet >= xord['A']) then + begin + if (olet <= xord['Z']) then + begin + let := xchr[olet + Diff]; + end; + end; + tolowercase := let; +end; + +{---------------------------------------------------} +(* decide if the first string is the same as the second -- + * at least the first 'len' characters + * We need this since most Pascal impls. are brain-dead + * when it comes to string comparisons + *) +function streq (a, b : charstring; len : integer) : boolean; +label 1; +var i : integer; + same : boolean; +begin + same := true; + for i := 1 to len do + begin + if (a[i] <> b[i]) then + begin + same := false; + goto 1; + end; (* if *) + end; (* for *) +1: + streq := same; +end; (* streq *) + +{-------------------------------------------------------} +procedure strcopy (* src : charstring; var dest : charstring; len : integer *); +var i : integer; + begin + for i := 1 to len do + dest[i] := src[i]; + end; + +{-------------------------------------------------------} +procedure writestrng (* s :strng; tologfile : boolean *); +var i : integer; +begin +if (tologfile) then + begin + for i := 1 to s.len do + write (logfile, s.str[i]); + end +else + begin + for i := 1 to s.len do + write (s.str[i]); + end; +end; + + +{---------------------------------------------------} +(* Move the current DVI position to posx, posy by + * moving relatively from our current position + * and store the new position + *) + +procedure isetpos (posx, posy : integer); +var dy, dx: ScaledPts; + numbytes : integer; +begin + dx := posx - ourxpos; + dy := posy - ourypos; + + numbytes := 1; + if ((dx < 128) and (dx >= -128)) then + numbytes := 1 + else if ((dx < 32768) and (dx >= -32768)) then + numbytes := 2 + else if ((dx < TWO23) and (dx >= - TWO23))then + numbytes := 3 + else if ((dx < TWO31) and (dx >= - TWO31))then + numbytes := 4 + else + begin + complain (ERRREALBAD); + writeln('Panic: dx is too big/small in isetpos: ',dx); + writeln(logfile,'Panic: dx is too big/small in isetpos: ',dx); + end; + + cmd1byte (RIGHTLEFT + numbytes -1); (* number of bytes in its arg list *) + cmdSigned (dx, numbytes); + + numbytes := 1; + if ((dy < 128) and (dy >= -128)) then + numbytes := 1 + else if ((dy < 32768) and (dy >= -32768)) then + numbytes := 2 + else if ((dy < TWO23) and (dy >= - TWO23))then + numbytes := 3 + else if ((dy < TWO31) and (dy >= - TWO31))then + numbytes := 4 + else + begin + complain (ERRREALBAD); + writeln('Panic: dy is too big/small in isetpos: ',dy); + writeln(logfile,'Panic: dy is too big/small in isetpos: ',dy); + end; + + cmd1byte (DOWNUP + numbytes -1); + + cmdSigned (dy, numbytes); + + ourxpos := posx; + ourypos := posy; +end; + +{---------------------------------------------------} +(* put out a character *) +procedure iputchar (charno : OctByt); +begin + cmd1byte (PUT1); + cmd1byte (charno); +end; + + +{---------------------------------------------------} +(* set the font number, but only if it is different than + * the last one we accessed. + *) +procedure isetfont (DVINum : integer); +begin + if (ourfontnum <> DVINum) then + begin + cmd1byte (USEFONT); + cmd2byte (DVINum); + ourfontnum := DVINum; + end; +end; + + +procedure IPUSH; +begin + if (ourpushdepth = 0) then + begin (* first push --> start tyling *) + origTexfont := font[curfont].num; + end + else + begin + prevfont := ourfontnum; (* store the internal font number in use at this time *) + end; + cmd1byte (NOP); + cmd1byte (NOP); (* our greeting *) + cmd1byte (PUSH); + ourpushdepth := ourpushdepth + 1; +end; + +procedure IPOP; +begin + cmd1byte (POP); + cmd1byte(NOP); + cmd1byte(NOP); (* our signature *) + ourpushdepth := ourpushdepth - 1; + if (ourpushdepth < 0) then + begin + complain (ERRREALBAD); + writeln(logfile,'Error: too many internal pops'); + end; + if (ourpushdepth = 0) then + begin (* we are totally done with tyling for now *) + if (nf > 0) then + isetfont (origTexfont); (* only if it is valid *) + end + else + begin + if (prevfont >= 0) then + isetfont(prevfont); (* restore that internal font previously in use *) + end; +end; + +{---------------------------------------------------} +(* Assumes that the correct font is currently set *) +procedure Tyldot (dotx, doty : ScaledPts); +begin + if (dotx <> 0) and (doty <> 0) then + isetpos (dotx, doty); + iputchar (DOTCHAR); +end; + +{---------------------------------------------------} +procedure InitDVIBuf; +var i: integer; +begin + with GDVIBuf do + begin + TotByteLen := 0; + Numstrings := 0; + for i := 1 to MAXDVISTRINGS do + Dstrings[i] := nil; + curstrindex := MAXOLEN + 1; + end; +end; + +{---------------------------------------------------} +procedure ClearDVIBuf; +var i : integer; +begin + with GDVIBuf do + begin + for i := 1 to Numstrings do + begin + dispose (Dstrings[i]); + Dstrings[i] := nil; + end; + TotByteLen := 0; + Numstrings := 0; + curstrindex := MAXOLEN + 1; + end; +end; + +{---------------------------------------------------} +procedure WriteDVIBuf; +var i: integer; + curstr: integer; + b : OctByt; +begin + curstr := 1; + with GDVIBuf do + begin + while (curstr < Numstrings) do + begin + for i := 1 to MAXOLEN do + begin + b := Dstrings[curstr]^[i]; + OutputByte (b); + end; + curstr := curstr + 1; + end; (* while *) + +(* now do the last string *) + for i := 1 to (curstrindex - 1) do + begin + b := Dstrings[Numstrings]^[i]; + OutputByte(b); + end; (* for *) + end; (* with *) + ClearDVIBuf; +end; + +{---------------------------------------------------} +procedure BackupInBuf (nbytes : integer); +var nstrs, rem : integer; +begin + with GDVIBuf do + begin + nstrs := (TotByteLen - nbytes) div MAXOLEN; + rem := (TotByteLen - nbytes) mod MAXOLEN; + Numstrings := nstrs + 1; + curstrindex := rem + 1; (* points to position to-be-filled *) + if (curstrindex = 0) then + curstrindex := MAXOLEN; + TotByteLen := TotByteLen - nbytes; + end; +end; + +{-----------------------------------------------------} +function DVIMark : integer; +begin + DVIMark := GDVIBuf.TotByteLen; +end; + + + +{---------------------------------------------} +function NewItem (what : Primitive): pItem; +var i : pItem; + f : figptr; +begin + + new (i); + with i^ do + begin + nextitem := nil; + BBlx := 0; + BBby := 0; + BBrx := 0; + BBty := 0; + itemthick := LoVThick; + itemvec := VKCirc; + itempatt := solid; + kind := what; + case (what) of (* give defaults *) + Aline : ; + Aspline: begin + nsplknots := 0; + dosmarks := 0; + sclosed := false; + spltype := BSPL; + end; + Attspline: begin + nttknots := 0; + dottmarks := 0; + tspltype := BSPL; + tclosed := false; + end; + Abeam : ; + Atieslur: begin + ntknots := 0; + end; + Aarc: begin + narcknots := 0; + end; + Alabel: begin + fontstyle := -1; (* undefined *) + labeltext.len := 0; + end; + Afigure: begin + figtheta := 0.0; + fsx := 1.0; fsy := 1.0; + fdx := 0; fdy := 0; + preWid := 0; preHt := 0; + postWid := 0; postHt := 0; + depthnumber := 0; (* for now *) + new (f); (* a new figure *) + body := f; + body^.things := nil; + end; + end; (*case *) + end; (* with *) + NewItem := i; +end; (* NewItem *) + +{ ### Note: "pageitems" could be extended to be a list +{ of macrodefinitions which contain primitives , and +{ then could be instanced. E.g., a library of common +{ figures callable from \special level } + + +{------------------------------------------------------} +procedure pushItem (depth : integer; newthing : pItem); +label 101; +var i, p : pItem; + dun : boolean; +begin + if (pageitems = nil) then + begin + if (newthing^.kind = Afigure) then + begin + pageitems := newthing; + goto 101; + end + else + begin + pageitems := NewItem (Afigure); + pageitems^.depthnumber := depth; + end; + end; + + (* Assume that pageitems points to Afigure *) + + (* traverse the list *) + i := pageitems; (* point to front of list for now *) + p := i^.body^.things; + dun := false; + while ((p <> nil) and not dun) do + begin + if (depth = i^.depthnumber) then + begin (* simple push *) + dun := true; + (* Note: this is the case when pushing another figure item + onto an already-existing list. We push the newfigure + with a depth of (fig^.depthnumber - 1) because it + really is part of the higer-level figure + *) + end + else if (depth > i^.depthnumber) then + begin + (* there MUST be a figure with a higher number deeper *) + while ((p^.kind <> Afigure) and (p^.nextitem <> nil)) do + begin + p := p^.nextitem; + end; + + if (p^.kind = Afigure) then + begin + i := p; + p := i^.body^.things; + end + else + begin + complain (ERRREALBAD); + writeln(logfile,'OOPS p^.kind isnt a figure. It must be near endoflist'); + end; + end; + end; (* while *) + + (* we have the correct front of list-list, + and i points to Afigure item *) + newthing^.nextitem := p; + i^.body^.things := newthing; +101: +end; (* pushItem *) + + + +{---------------------------------------------} +function Tgetfixword (k: integer) : real; +var a : 0 .. 4096; + f : integer; +begin + a := (tfm[k] * 16) + (tfm[k + 1] div 16); + f := ((((tfm[k + 1] mod 16) * 256) + + tfm[k + 2]) * 256) + + tfm[k + 3]; + if (a > 2047) then + begin + a := 4096 - a; + if (f > 0) then + begin + f := TWO20 - f; + a := a - 1; + end; + end; + Tgetfixword := a + f / TWO20; +end; + +{-----------------------------------------------------} +function TgetSigned (k: integer): integer; +var i: integer; +begin + i := tfm[k]; + if (i < 128) then + i := i - 256; + TgetSigned := (((((i * 256) + tfm[k + 1]) * 256) + + tfm[k + 2]) * 256) + tfm[k + 3]; +end; + + + +{-----------------------------------------------------------} +(* open a .tfm file and return the parameters in it. + * Used only in conjuction with the vector and music fonts + *) +procedure gettfm (tfmfilnam: strng; + var dessize, p1, p2, p3, p4, p5, p6, p7 : ScaledPts; + var cksum : integer); +label 9999; +var tfmptr: integer; + lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np: integer; + charbase, widthbase, heightbase, depthbase, + italicbase, ligkernbase, kernbase, extenbase, + parambase : integer; + tempdesignsize : ScaledPts; +begin + p1 := 0; p2 := 0; p3 := 0; p4 := 0; + p5 := 0; p6 := 0; p7 := 0; + cksum := -1; + + strcopy(tfmfilnam.str, tfmname.str, tfmfilnam.len); + tfmname.len := tfmfilnam.len; + + tfmname.str[tfmname.len + 1] := chr(32); + + if (not opentfmfile) then + begin + complain (ERRREALBAD); + writestrng(tfmname,true); + writeln(logfile,'---not loaded, TFM file can''t be opened!'); + writestrng(tfmname,false); + writeln(' cannot be opened. Aborting'); + jumpout; + end; + + + tfm[0] := Tgetvaxbyte; + tfm[1] := Tgetvaxbyte; + + + lf := (tfm[0] * 256) + tfm[1]; + if ((4 * lf - 1) > TFMSIZE) then + begin + complain (ERRREALBAD); + write(logfile,'The tfm file:'); + writestrng(tfmfilnam, true); + writeln(logfile,' is bigger than I can handle!'); + goto 9999; + end; + + for tfmptr := 2 to (4 * lf) - 1 do + begin + + tfm[tfmptr] := Tgetvaxbyte; + + end; (* for *) + + tfmptr := 2; + lh := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + bc := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + ec := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + nw := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + nh := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + nd := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + ni := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + nl := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + nk := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + ne := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + np := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + if (lf <> (6 + lh + ((ec - bc) + 1) + nw + nh + + nd + ni + nl + nk + ne + np)) then + begin + complain (ERRREALBAD); + writestrng(tfmfilnam, true); + writeln(logfile,': subfile sizes don''t add up to the stated total!'); + writeln(logfile,'Sorry, but I can''t go on; are you sure this is a TFM?'); + goto 9999 + end; + if (bc > (ec + 1)) or (ec > 255) then + begin + complain (ERRREALBAD); + writeln(logfile,'The character code range ', bc: 1, '..', ec: 1, 'is illegal!'); + writeln(logfile,'Sorry, but I can''t go on; are you sure this is a TFM?'); + goto 9999; + end; + charbase := (6 + lh) - bc; + widthbase := (charbase + ec) + 1; + heightbase := widthbase + nw; + depthbase := heightbase + nh; + italicbase := depthbase + nd; + ligkernbase := italicbase + ni; + kernbase := ligkernbase + nl; + extenbase := kernbase + nk; + parambase := (extenbase + ne) - 1; + + dessize := round (Tgetfixword (28) * SPPERPT); (* now in ScaledPts *) + tempdesignsize := round (dessize * magfactor); + cksum := TgetSigned (24); + (* return the special 7 parameters for the font *) + p1 := round (Tgetfixword (4 * (parambase + 1)) * tempdesignsize); + p2 := round (Tgetfixword (4 * (parambase + 2)) * tempdesignsize); + p3 := round (Tgetfixword (4 * (parambase + 3)) * tempdesignsize); + p4 := round (Tgetfixword (4 * (parambase + 4)) * tempdesignsize); + p5 := round (Tgetfixword (4 * (parambase + 5)) * tempdesignsize); + p6 := round (Tgetfixword (4 * (parambase + 6)) * tempdesignsize); + p7 := round (Tgetfixword (4 * (parambase + 7)) * tempdesignsize); + +9999: +end; + + +{---------------------------------------------------} +procedure initVnMnLtables; +var i: integer; +begin + for i := 1 to SizVFontTable do + VFontTable[i] := nil; + for i := 1 to SizMFontTable do + MFontTable[i] := nil; + for i := 1 to SizLFontTable do + LFontTable[i] := nil; + VFontsDefd := 0; + MFontsDefd := 0; + LFontsDefd := 0; + GDVIFN := 300; (* starting number for any new fonts that we define *) +end; + + +{-------------------------------------------------------} +procedure fonttobedefined (kind : char; findex : integer); +begin + FTBDs := FTBDs + 1; +(* reset this to zero after outputting + 1. fontdefs + 2. bop + 3. contents of dvi page + 4. eop +*) + TBD[FTBDs].which := kind; + TBD[FTBDs].indx := findex; +end; + + +{-----------------------------------------------------} +procedure enterfont (fontnum : integer; ck : integer; + scalefact, dessiz : ScaledPts; + nam : strng); +var n: integer; + len : integer; +begin + cmd1byte(FONTDEF); + cmd2byte(fontnum); + cmd4byte(ck); + cmd4byte(scalefact); + cmd4byte(dessiz); + cmd1byte(USESTDAREA); + + len := nam.len; + + + cmd1byte(len - 4); (* skip the length of the .tfm suffix *) + + + for n := 1 to (nam.len - 4) do + + begin (* skip the .tfm suffix *) + cmd1byte (xord [ nam.str[n] ]); + end; +end; + + +{-----------------------------------------------------} +procedure Outputfont (fontnum : integer; ck : integer; + scalefact, dessiz : ScaledPts; + nam : strng); +var n: integer; + len : integer; +begin + OutputByte(FONTDEF); + Output2Byte(fontnum); + Output4Byte(ck); + Output4Byte(scalefact); + Output4Byte(dessiz); + OutputByte(USESTDAREA); + + len := nam.len; + + + OutputByte(len - 4); + + + for n := 1 to (nam.len - 4) do + + begin (* dont output the default dir prefix, nor the .tfm suffix *) + OutputByte(xord [ nam.str[n] ]); + end; +end; + +{-----------------------------------------------------} +procedure defineNewfonts; +(* this needs to be done before first access to a font on a page + later someone else will have to re-define all of them in the postamble *) +label 99; +var i, n : integer; + f : integer; +begin + for i := 1 to FTBDs do + begin + if (TBD[i].which = 'V') then + begin + f := TBD[i].indx; + with VFontTable[f]^ do + begin + if (Isdefined) then + goto 99; + Outputfont (DVIFontNum, Cksum, DesSize, DesSize, + FontName); + Isdefined := true; + end; (*with *) + end (* if *) + else if (TBD[i].which = 'M') then + begin (* music font *) + f := TBD[i].indx; + with MFontTable[f]^ do + begin + if (Isdefined) then + goto 99; + Outputfont (DVIFontNum, Cksum, DesSize, DesSize, + FontName); + Isdefined := true; + end; (* with *) + end (* else *) + else if (TBD[i].which = 'L') then + begin (* label font *) + f := TBD[i].indx; + with LFontTable[f]^ do + begin + if (Isdefined) then + goto 99; + Outputfont (DVIFontNum, Cksum, DesSize, DesSize, {### is this right?} + FontName); + Isdefined := true; + end; (* with *) + end + else + begin + complain (ERRREALBAD); + writeln(logfile,'Unknown type of font to be defined:"',TBD[i].which,'"'); + end; (* else *) +99: + end; (* for *) +end; + + +{---------------------------------------------------} +function GetMusFont (stfsiz, fam : integer) : MusIndex; +label 20, 99; +var mustfmnam : strng; + found, i : MusIndex; + design, p1, p2, p3, p4, linesp, gwidth, p7 : ScaledPts; + cksm, r, k : integer; +begin + (* see if it already exists *) + found := 0; + for i := 1 to MFontsDefd do (* loop through since there are few *) + with MFontTable[i]^ do + begin + if (Staffsize = stfsiz) and + (Family = fam) then + begin + found := i; + goto 20; + end; + end; (* with *) + +20: if (found <> 0) then + begin + GetMusFont := found; + goto 99; + end; + + (* Not here already--go get it *) + for k := 1 to ARRLIMIT do + mustfmnam.str[k] := ' '; + + r := 0; + + mustfmnam.str[r+1] := 'm'; + mustfmnam.str[r+2] := 'u'; + mustfmnam.str[r+3] := 's'; + mustfmnam.str[r+4] := xchr[stfsiz + xord['0']]; + mustfmnam.str[r+5] := xchr[fam + xord['0']]; + mustfmnam.str[r+6] := '.'; + mustfmnam.str[r+7] := 't'; + mustfmnam.str[r+8] := 'f'; + mustfmnam.str[r+9] := 'm'; + + mustfmnam.str[r+10] := chr(32); + + mustfmnam.len := 9 + r; + gettfm (mustfmnam, design, p1, p2, p3, p4, linesp, gwidth, p7, cksm); + + MFontsDefd := MFontsDefd + 1; + if (MFontsDefd > SizMFontTable) then + begin + complain (ERRREALBAD); + writestrng(mustfmnam, true); + writeln(logfile,'---not loadable. Size of Music Font table too small'); + writestrng(mustfmnam,false); + writeln(' cannot be loaded. Too many music fonts. Table too small.'); + jumpout; + end; + + i := MFontsDefd; + new (MFontTable[i]); + with MFontTable[i]^ do + begin + Staffsize := stfsiz; + Family := fam; + DesSize := design; + strcopy (mustfmnam.str, FontName.str, mustfmnam.len); + FontName.len := mustfmnam.len; + Cksum := cksm; + ghu := round (gwidth / QNOTEGHUS); + gvu := round (linesp / QNOTEGVUS); + DVIFontNum := GDVIFN + 1; + Isdefined := false; + end; + + GDVIFN := GDVIFN + 1; +(* call someone to do the defns of cdp, cht, cwd foreach beam *) + definebeams (MFontTable[i]); + fonttobedefined ('M', i); + GetMusFont := i; +99: +end; + + +{---------------------------------------------------} +function GetVectFont (size : VThickness; vk : VectKind) : VecIndex; +label 20, 99; +var vectfmnam : strng; + found, i : VecIndex; + design, p1, p2, w0, w1, maxveclen, p6, p7 : ScaledPts; + cksm, r, k : integer; +begin + (* see if it already exists *) + found := 0; + + for i := 1 to VFontsDefd do + with VFontTable[i]^ do + begin + if ((psize = size) and + (vkind = vk)) then + begin + found := i; + goto 20; + end; + end; (* with *) + +20: + if (found <> 0) then + begin + GetVectFont := found; + goto 99; + end; + + (* Not here--go get it *) + for k := 1 to ARRLIMIT do + vectfmnam.str[k] := ' '; + + r := 0; + + case (vk) of + VKCirc : vectfmnam.str[r+1] := 'c'; + VKVert : vectfmnam.str[r+1] := 'v'; + VKHort : vectfmnam.str[r+1] := 'h'; + end; (*case *) + vectfmnam.str[r+2] := 'v'; + vectfmnam.str[r+3] := 'e'; + vectfmnam.str[r+4] := 'c'; + if (size <= 9) then + begin + vectfmnam.str[r+5] := xchr[size + xord['0']]; + vectfmnam.str[r+6] := '.'; + vectfmnam.str[r+7] := 't'; + vectfmnam.str[r+8] := 'f'; + vectfmnam.str[r+9] := 'm'; + + vectfmnam.str[r+10] := chr(32); + + vectfmnam.len := 9 + r; + end + else + begin + vectfmnam.str[r+5] := xchr[(size div 10) + xord['0']]; + vectfmnam.str[r+6] := xchr[(size - ((size div 10)*10)) + xord['0']]; + vectfmnam.str[r+7] := '.'; + vectfmnam.str[r+8] := 't'; + vectfmnam.str[r+9] := 'f'; + vectfmnam.str[r+10] := 'm'; + + vectfmnam.str[r+11] := chr(32); + + vectfmnam.len := 10 + r; + end; + + gettfm (vectfmnam, design, p1, p2, w0, w1, maxveclen, p6, p7, cksm); + VFontsDefd := VFontsDefd + 1; + if (VFontsDefd > SizVFontTable) then + begin + complain (ERRREALBAD); + writestrng(vectfmnam, true); + writeln(logfile,'---not loadable. Size of Vector Font table too small'); + writestrng(vectfmnam,false); + writeln(' cannot be loaded. Too many vector fonts. Table too small.'); + jumpout; + end; + + i := VFontsDefd; + new (VFontTable[i]); + with VFontTable[i]^ do + begin + vkind := vk; + psize := size; + DesSize := design; + if (vk = VKVert) then + PenSize := w1 + else + PenSize := w0; + PenSize := round (size * (MAXVECLENsp / 16.0)); + MaxVectLen := maxveclen; + strcopy (vectfmnam.str, FontName.str, vectfmnam.len); + FontName.len := vectfmnam.len; + Cksum := cksm; + Isdefined := false; + DVIFontNum := GDVIFN + 1; + end; + + GDVIFN := GDVIFN + 1; + + definevectors (VFontTable[i]); +(* someone asked for it, so they must want it, and we should fntdef it *) + fonttobedefined ('V', i); + GetVectFont := i; +99: +end; + +{----------------------------------------------------------} +function GetLabFont (style : integer) : integer; +label 30, 99; +var labtfmnam : strng; + found, i : integer; + design, p1, space, p3, p4, p5, p6, p7 : ScaledPts; + cksm, r, k : integer; +begin +if (style > MAXLABELFONTS) then + style := 1; + found := 0; + for i := 1 to LFontsDefd do + with LFontTable[i]^ do + begin + if (internalnumber = style) then + begin + found := i; + goto 30; + end; + end; +30: + if (found <> 0) then + begin + GetLabFont := found; + goto 99; + end; + for k := 1 to ARRLIMIT do + labtfmnam.str[k] := ' '; + + r := 0; + + labtfmnam.str[r + 1] := 'c'; + labtfmnam.str[r + 2] := 'm'; + case style of + 1: begin (* cmtt10 *) + labtfmnam.str[r + 3] := 't'; + labtfmnam.str[r + 4] := 't'; + labtfmnam.str[r + 5] := '1'; + labtfmnam.str[r + 6] := '0'; + k := r + 6; + end; + 2: begin (* cmb10 *) + labtfmnam.str[r + 3] := 'b'; + labtfmnam.str[r + 4] := '1'; + labtfmnam.str[r + 5] := '0'; + k := r + 5; + end; + 3: begin (* cmsl10 *) + labtfmnam.str[r + 3] := 's'; + labtfmnam.str[r + 4] := 'l'; + labtfmnam.str[r + 5] := '1'; + labtfmnam.str[r + 6] := '0'; + k := r + 6; + end; + 4: begin (* cmtt8 *) + labtfmnam.str[r + 3] := 't'; + labtfmnam.str[r + 4] := 't'; + labtfmnam.str[r + 5] := '8'; + k := r + 5; + end; + 5: begin (* cmsl8 *) + labtfmnam.str[r + 3] := 's'; + labtfmnam.str[r + 4] := 'l'; + labtfmnam.str[r + 5] := '8'; + k := r + 5; + end; + end; (* case *) + labtfmnam.str[k + 1] := '.'; + labtfmnam.str[k + 2] := 't'; + labtfmnam.str[k + 3] := 'f'; + labtfmnam.str[k + 4] := 'm'; + + labtfmnam.str[k+5] := chr(32); + + labtfmnam.len := k + 4; + + gettfm (labtfmnam, design, p1, space, p3, p4, p5, p6, p7, cksm); + + LFontsDefd := LFontsDefd + 1; + + if (LFontsDefd > SizLFontTable) then + begin + complain (ERRREALBAD); + writestrng(labtfmnam, true); + writeln(logfile,'---not loadable. Size of Label Font table too small'); + writestrng(labtfmnam,false); + writeln(' cannot be loaded. Too many label fonts. Table too small.'); + jumpout; + end; + + i := LFontsDefd; + new (LFontTable[i]); + with LFontTable[i]^ do + begin + strcopy (labtfmnam.str, FontName.str, labtfmnam.len); + FontName.len := labtfmnam.len; + Cksum := cksm; + DesSize := design; + internalnumber := style; + spacewidth := space; + DVIFontNum := GDVIFN +1; + Isdefined := false; + end; (* with *) + + GDVIFN := GDVIFN + 1; + fonttobedefined ('L', i); + GetLabFont := i; +99: +end; + + +{------------------------------------------------} +function vectangle (dx, dy : integer) :real; +begin + if (dx <> 0) then + vectangle := arctan (dy / (dx * 1.0)) * RADTODEG + else + begin + if (dy > 0) then + vectangle := 90.0 + else + vectangle := -90.0; + end; +end; + + +{-----------------------------------------------------------} +procedure definevectors (* var Vec: pVectFontInfRec *); +var units : real; +begin + units := Vec^.MaxVectLen / 16.0; +with Vec^.FontInfo[ 0] do begin + Cht := round( 15.9688 * units); + Cdp := 0; + Cwd := round( 0.9981 * units); + Angle := 86.4237; +end; + +with Vec^.FontInfo[ 1] do begin + Cht := round( 15.8764 * units); + Cdp := 0; + Cwd := round( 1.9846 * units); + Angle := 82.8750; +end; + +with Vec^.FontInfo[ 2] do begin + Cht := round( 15.7260 * units); + Cdp := 0; + Cwd := round( 2.9486 * units); + Angle := 79.3803; +end; + +with Vec^.FontInfo[ 3] do begin + Cht := round( 15.5223 * units); + Cdp := 0; + Cwd := round( 3.8806 * units); + Angle := 75.9638; +end; + +with Vec^.FontInfo[ 4] do begin + Cht := round( 15.2717 * units); + Cdp := 0; + Cwd := round( 4.7724 * units); + Angle := 72.6460; +end; + +with Vec^.FontInfo[ 5] do begin + Cht := round( 14.9813 * units); + Cdp := 0; + Cwd := round( 5.6180 * units); + Angle := 69.4440; +end; + +with Vec^.FontInfo[ 6] do begin + Cht := round( 14.6585 * units); + Cdp := 0; + Cwd := round( 6.4131 * units); + Angle := 66.3706; +end; + +with Vec^.FontInfo[ 7] do begin + Cht := round( 14.3108 * units); + Cdp := 0; + Cwd := round( 7.1554 * units); + Angle := 63.4349; +end; + +with Vec^.FontInfo[ 8] do begin + Cht := round( 13.9452 * units); + Cdp := 0; + Cwd := round( 7.8442 * units); + Angle := 60.6422; +end; + +with Vec^.FontInfo[ 9] do begin + Cht := round( 13.5680 * units); + Cdp := 0; + Cwd := round( 8.4800 * units); + Angle := 57.9946; +end; + +with Vec^.FontInfo[ 10] do begin + Cht := round( 13.1847 * units); + Cdp := 0; + Cwd := round( 9.0645 * units); + Angle := 55.4915; +end; + +with Vec^.FontInfo[ 11] do begin + Cht := round( 12.8000 * units); + Cdp := 0; + Cwd := round( 9.6000 * units); + Angle := 53.1301; +end; + +with Vec^.FontInfo[ 12] do begin + Cht := round( 12.4178 * units); + Cdp := 0; + Cwd := round( 10.0895 * units); + Angle := 50.9061; +end; + +with Vec^.FontInfo[ 13] do begin + Cht := round( 12.0412 * units); + Cdp := 0; + Cwd := round( 10.5361 * units); + Angle := 48.8141; +end; + +with Vec^.FontInfo[ 14] do begin + Cht := round( 11.6726 * units); + Cdp := 0; + Cwd := round( 10.9431 * units); + Angle := 46.8476; +end; + +with Vec^.FontInfo[ 15] do begin + Cht := round( 11.3137 * units); + Cdp := 0; + Cwd := round( 11.3137 * units); + Angle := 45.0000; +end; + +with Vec^.FontInfo[ 16] do begin + Cht := round( 10.9431 * units); + Cdp := 0; + Cwd := round( 11.6726 * units); + Angle := 43.1524; +end; + +with Vec^.FontInfo[ 17] do begin + Cht := round( 10.5361 * units); + Cdp := 0; + Cwd := round( 12.0412 * units); + Angle := 41.1859; +end; + +with Vec^.FontInfo[ 18] do begin + Cht := round( 10.0895 * units); + Cdp := 0; + Cwd := round( 12.4178 * units); + Angle := 39.0939; +end; + +with Vec^.FontInfo[ 19] do begin + Cht := round( 9.6000 * units); + Cdp := 0; + Cwd := round( 12.8000 * units); + Angle := 36.8699; +end; + +with Vec^.FontInfo[ 20] do begin + Cht := round( 9.0645 * units); + Cdp := 0; + Cwd := round( 13.1847 * units); + Angle := 34.5085; +end; + +with Vec^.FontInfo[ 21] do begin + Cht := round( 8.4800 * units); + Cdp := 0; + Cwd := round( 13.5680 * units); + Angle := 32.0054; +end; + +with Vec^.FontInfo[ 22] do begin + Cht := round( 7.8442 * units); + Cdp := 0; + Cwd := round( 13.9452 * units); + Angle := 29.3578; +end; + +with Vec^.FontInfo[ 23] do begin + Cht := round( 7.1554 * units); + Cdp := 0; + Cwd := round( 14.3108 * units); + Angle := 26.5651; +end; + +with Vec^.FontInfo[ 24] do begin + Cht := round( 6.4131 * units); + Cdp := 0; + Cwd := round( 14.6585 * units); + Angle := 23.6294; +end; + +with Vec^.FontInfo[ 25] do begin + Cht := round( 5.6180 * units); + Cdp := 0; + Cwd := round( 14.9813 * units); + Angle := 20.5560; +end; + +with Vec^.FontInfo[ 26] do begin + Cht := round( 4.7724 * units); + Cdp := 0; + Cwd := round( 15.2717 * units); + Angle := 17.3540; +end; + +with Vec^.FontInfo[ 27] do begin + Cht := round( 3.8806 * units); + Cdp := 0; + Cwd := round( 15.5223 * units); + Angle := 14.0362; +end; + +with Vec^.FontInfo[ 28] do begin + Cht := round( 2.9486 * units); + Cdp := 0; + Cwd := round( 15.7260 * units); + Angle := 10.6197; +end; + +with Vec^.FontInfo[ 29] do begin + Cht := round( 1.9846 * units); + Cdp := 0; + Cwd := round( 15.8764 * units); + Angle := 7.1250; +end; + +with Vec^.FontInfo[ 30] do begin + Cht := round( 0.9981 * units); + Cdp := 0; + Cwd := round( 15.9688 * units); + Angle := 3.5763; +end; + +with Vec^.FontInfo[ 31] do begin + Cht := 0; + Cdp := 0; + Cwd := round( 16.0000 * units); + Angle := 0.0000; +end; + +with Vec^.FontInfo[ 32] do begin + Cdp := round( 0.9981 * units); + Cht := 0; + Cwd := round( 15.9688 * units); + Angle := -3.5763; +end; + +with Vec^.FontInfo[ 33] do begin + Cdp := round( 1.9846 * units); + Cht := 0; + Cwd := round( 15.8764 * units); + Angle := -7.1250; +end; + +with Vec^.FontInfo[ 34] do begin + Cdp := round( 2.9486 * units); + Cht := 0; + Cwd := round( 15.7260 * units); + Angle := -10.6197; +end; + +with Vec^.FontInfo[ 35] do begin + Cdp := round( 3.8806 * units); + Cht := 0; + Cwd := round( 15.5223 * units); + Angle := -14.0362; +end; + +with Vec^.FontInfo[ 36] do begin + Cdp := round( 4.7724 * units); + Cht := 0; + Cwd := round( 15.2717 * units); + Angle := -17.3540; +end; + +with Vec^.FontInfo[ 37] do begin + Cdp := round( 5.6180 * units); + Cht := 0; + Cwd := round( 14.9813 * units); + Angle := -20.5560; +end; + +with Vec^.FontInfo[ 38] do begin + Cdp := round( 6.4131 * units); + Cht := 0; + Cwd := round( 14.6585 * units); + Angle := -23.6294; +end; + +with Vec^.FontInfo[ 39] do begin + Cdp := round( 7.1554 * units); + Cht := 0; + Cwd := round( 14.3108 * units); + Angle := -26.5651; +end; + +with Vec^.FontInfo[ 40] do begin + Cdp := round( 7.8442 * units); + Cht := 0; + Cwd := round( 13.9452 * units); + Angle := -29.3578; +end; + +with Vec^.FontInfo[ 41] do begin + Cdp := round( 8.4800 * units); + Cht := 0; + Cwd := round( 13.5680 * units); + Angle := -32.0054; +end; + +with Vec^.FontInfo[ 42] do begin + Cdp := round( 9.0645 * units); + Cht := 0; + Cwd := round( 13.1847 * units); + Angle := -34.5085; +end; + +with Vec^.FontInfo[ 43] do begin + Cdp := round( 9.6000 * units); + Cht := 0; + Cwd := round( 12.8000 * units); + Angle := -36.8699; +end; + +with Vec^.FontInfo[ 44] do begin + Cdp := round( 10.0895 * units); + Cht := 0; + Cwd := round( 12.4178 * units); + Angle := -39.0939; +end; + +with Vec^.FontInfo[ 45] do begin + Cdp := round( 10.5361 * units); + Cht := 0; + Cwd := round( 12.0412 * units); + Angle := -41.1859; +end; + +with Vec^.FontInfo[ 46] do begin + Cdp := round( 10.9431 * units); + Cht := 0; + Cwd := round( 11.6726 * units); + Angle := -43.1524; +end; + +with Vec^.FontInfo[ 47] do begin + Cdp := round( 11.3137 * units); + Cht := 0; + Cwd := round( 11.3137 * units); + Angle := -45.0000; +end; + +with Vec^.FontInfo[ 48] do begin + Cdp := round ( 11.6726 * units); + Cht := 0; + Cwd := round( 10.9431 * units); + Angle := -46.8476; +end; + +with Vec^.FontInfo[ 49] do begin + Cdp := round ( 12.0412 * units); + Cht := 0; + Cwd := round( 10.5361 * units); + Angle := -48.8141; +end; + +with Vec^.FontInfo[ 50] do begin + Cdp := round ( 12.4178 * units); + Cht := 0; + Cwd := round( 10.0895 * units); + Angle := -50.9061; +end; + +with Vec^.FontInfo[ 51] do begin + Cdp := round ( 12.8000 * units); + Cht := 0; + Cwd := round( 9.6000 * units); + Angle := -53.1301; +end; + +with Vec^.FontInfo[ 52] do begin + Cdp := round ( 13.1847 * units); + Cht := 0; + Cwd := round( 9.0645 * units); + Angle := -55.4915; +end; + +with Vec^.FontInfo[ 53] do begin + Cdp := round ( 13.5680 * units); + Cht := 0; + Cwd := round( 8.4800 * units); + Angle := -57.9946; +end; + +with Vec^.FontInfo[ 54] do begin + Cdp := round ( 13.9452 * units); + Cht := 0; + Cwd := round( 7.8442 * units); + Angle := -60.6422; +end; + +with Vec^.FontInfo[ 55] do begin + Cdp := round ( 14.3108 * units); + Cht := 0; + Cwd := round( 7.1554 * units); + Angle := -63.4349; +end; + +with Vec^.FontInfo[ 56] do begin + Cdp := round ( 14.6585 * units); + Cht := 0; + Cwd := round( 6.4131 * units); + Angle := -66.3706; +end; + +with Vec^.FontInfo[ 57] do begin + Cdp := round ( 14.9813 * units); + Cht := 0; + Cwd := round( 5.6180 * units); + Angle := -69.4440; +end; + +with Vec^.FontInfo[ 58] do begin + Cdp := round ( 15.2717 * units); + Cht := 0; + Cwd := round( 4.7724 * units); + Angle := -72.6460; +end; + +with Vec^.FontInfo[ 59] do begin + Cdp := round ( 15.5223 * units); + Cht := 0; + Cwd := round( 3.8806 * units); + Angle := -75.9638; +end; + +with Vec^.FontInfo[ 60] do begin + Cdp := round ( 15.7260 * units); + Cht := 0; + Cwd := round( 2.9486 * units); + Angle := -79.3803; +end; + +with Vec^.FontInfo[ 61] do begin + Cdp := round ( 15.8764 * units); + Cht := 0; + Cwd := round( 1.9846 * units); + Angle := -82.8750; +end; + +with Vec^.FontInfo[ 62] do begin + Cdp := round ( 15.9688 * units); + Cht := 0; + Cwd := round( 0.9981 * units); + Angle := -86.4237; +end; + +with Vec^.FontInfo[ 63] do begin + Cht := round( 8.0000 * units); + Cdp := 0; + Cwd := 0; + Angle := 90.0000; +end; + +with Vec^.FontInfo[ 64] do begin + Cht := round( 7.9382 * units); + Cdp := 0; + Cwd := round( 0.9923 * units); + Angle := 82.8750; +end; + +with Vec^.FontInfo[ 65] do begin + Cht := round( 7.7611 * units); + Cdp := 0; + Cwd := round( 1.9403 * units); + Angle := 75.9638; +end; + +with Vec^.FontInfo[ 66] do begin + Cht := round( 7.4906 * units); + Cdp := 0; + Cwd := round( 2.8090 * units); + Angle := 69.4440; +end; + +with Vec^.FontInfo[ 67] do begin + Cht := round( 7.1554 * units); + Cdp := 0; + Cwd := round( 3.5777 * units); + Angle := 63.4349; +end; + +with Vec^.FontInfo[ 68] do begin + Cht := round( 6.7840 * units); + Cdp := 0; + Cwd := round( 4.2400 * units); + Angle := 57.9946; +end; + +with Vec^.FontInfo[ 69] do begin + Cht := round( 6.4000 * units); + Cdp := 0; + Cwd := round( 4.8000 * units); + Angle := 53.1301; +end; + +with Vec^.FontInfo[ 70] do begin + Cht := round( 6.0206 * units); + Cdp := 0; + Cwd := round( 5.2680 * units); + Angle := 48.8141; +end; + +with Vec^.FontInfo[ 71] do begin + Cht := round( 5.6569 * units); + Cdp := 0; + Cwd := round( 5.6569 * units); + Angle := 45.0000; +end; + +with Vec^.FontInfo[ 72] do begin + Cht := round( 5.2680 * units); + Cdp := 0; + Cwd := round( 6.0206 * units); + Angle := 41.1859; +end; + +with Vec^.FontInfo[ 73] do begin + Cht := round( 4.8000 * units); + Cdp := 0; + Cwd := round( 6.4000 * units); + Angle := 36.8699; +end; + +with Vec^.FontInfo[ 74] do begin + Cht := round( 4.2400 * units); + Cdp := 0; + Cwd := round( 6.7840 * units); + Angle := 32.0054; +end; + +with Vec^.FontInfo[ 75] do begin + Cht := round( 3.5777 * units); + Cdp := 0; + Cwd := round( 7.1554 * units); + Angle := 26.5651; +end; + +with Vec^.FontInfo[ 76] do begin + Cht := round( 2.8090 * units); + Cdp := 0; + Cwd := round( 7.4906 * units); + Angle := 20.5560; +end; + +with Vec^.FontInfo[ 77] do begin + Cht := round( 1.9403 * units); + Cdp := 0; + Cwd := round( 7.7611 * units); + Angle := 14.0362; +end; + +with Vec^.FontInfo[ 78] do begin + Cht := round( 0.9923 * units); + Cdp := 0; + Cwd := round( 7.9382 * units); + Angle := 7.1250; +end; + +with Vec^.FontInfo[ 79] do begin + Cht := 0; + Cdp := 0; + Cwd := round( 8.0000 * units); + Angle := 0.0000; +end; + +with Vec^.FontInfo[ 80] do begin + Cdp := round( 0.9923 * units); + Cht := 0; + Cwd := round( 7.9382 * units); + Angle := -7.1250; +end; + +with Vec^.FontInfo[ 81] do begin + Cdp := round( 1.9403 * units); + Cht := 0; + Cwd := round( 7.7611 * units); + Angle := -14.0362; +end; + +with Vec^.FontInfo[ 82] do begin + Cdp := round( 2.8090 * units); + Cht := 0; + Cwd := round( 7.4906 * units); + Angle := -20.5560; +end; + +with Vec^.FontInfo[ 83] do begin + Cdp := round( 3.5777 * units); + Cht := 0; + Cwd := round( 7.1554 * units); + Angle := -26.5651; +end; + +with Vec^.FontInfo[ 84] do begin + Cdp := round( 4.2400 * units); + Cht := 0; + Cwd := round( 6.7840 * units); + Angle := -32.0054; +end; + +with Vec^.FontInfo[ 85] do begin + Cdp := round( 4.8000 * units); + Cht := 0; + Cwd := round( 6.4000 * units); + Angle := -36.8699; +end; + +with Vec^.FontInfo[ 86] do begin + Cdp := round( 5.2680 * units); + Cht := 0; + Cwd := round( 6.0206 * units); + Angle := -41.1859; +end; + +with Vec^.FontInfo[ 87] do begin + Cdp := round( 5.6569 * units); + Cht := 0; + Cwd := round( 5.6569 * units); + Angle := -45.0000; +end; + +with Vec^.FontInfo[ 88] do begin + Cdp := round ( 6.0206 * units); + Cht := 0; + Cwd := round( 5.2680 * units); + Angle := -48.8141; +end; + +with Vec^.FontInfo[ 89] do begin + Cdp := round ( 6.4000 * units); + Cht := 0; + Cwd := round( 4.8000 * units); + Angle := -53.1301; +end; + +with Vec^.FontInfo[ 90] do begin + Cdp := round ( 6.7840 * units); + Cht := 0; + Cwd := round( 4.2400 * units); + Angle := -57.9946; +end; + +with Vec^.FontInfo[ 91] do begin + Cdp := round ( 7.1554 * units); + Cht := 0; + Cwd := round( 3.5777 * units); + Angle := -63.4349; +end; + +with Vec^.FontInfo[ 92] do begin + Cdp := round ( 7.4906 * units); + Cht := 0; + Cwd := round( 2.8090 * units); + Angle := -69.4440; +end; + +with Vec^.FontInfo[ 93] do begin + Cdp := round ( 7.7611 * units); + Cht := 0; + Cwd := round( 1.9403 * units); + Angle := -75.9638; +end; + +with Vec^.FontInfo[ 94] do begin + Cdp := round ( 7.9382 * units); + Cht := 0; + Cwd := round( 0.9923 * units); + Angle := -82.8750; +end; + +with Vec^.FontInfo[ 95] do begin + Cdp := round ( 8.0000 * units); + Cht := 0; + Cwd := 0; + Angle := -90.0000; +end; + +with Vec^.FontInfo[ 96] do begin + Cht := round( 4.0000 * units); + Cdp := 0; + Cwd := 0; + Angle := 90.0000; +end; + +with Vec^.FontInfo[ 97] do begin + Cht := round( 3.8806 * units); + Cdp := 0; + Cwd := round( 0.9701 * units); + Angle := 75.9638; +end; + +with Vec^.FontInfo[ 98] do begin + Cht := round( 3.5777 * units); + Cdp := 0; + Cwd := round( 1.7889 * units); + Angle := 63.4349; +end; + +with Vec^.FontInfo[ 99] do begin + Cht := round( 3.2000 * units); + Cdp := 0; + Cwd := round( 2.4000 * units); + Angle := 53.1301; +end; + +with Vec^.FontInfo[100] do begin + Cht := round( 2.8284 * units); + Cdp := 0; + Cwd := round( 2.8284 * units); + Angle := 45.0000; +end; + +with Vec^.FontInfo[101] do begin + Cht := round( 2.4000 * units); + Cdp := 0; + Cwd := round( 3.2000 * units); + Angle := 36.8699; +end; + +with Vec^.FontInfo[102] do begin + Cht := round( 1.7889 * units); + Cdp := 0; + Cwd := round( 3.5777 * units); + Angle := 26.5651; +end; + +with Vec^.FontInfo[103] do begin + Cht := round( 0.9701 * units); + Cdp := 0; + Cwd := round( 3.8806 * units); + Angle := 14.0362; +end; + +with Vec^.FontInfo[104] do begin + Cht := 0; + Cdp := 0; + Cwd := round( 4.0000 * units); + Angle := 0.0000; +end; + +with Vec^.FontInfo[105] do begin + Cdp := round( 0.9701 * units); + Cht := 0; + Cwd := round( 3.8806 * units); + Angle := -14.0362; +end; + +with Vec^.FontInfo[106] do begin + Cdp := round( 1.7889 * units); + Cht := 0; + Cwd := round( 3.5777 * units); + Angle := -26.5651; +end; + +with Vec^.FontInfo[107] do begin + Cdp := round( 2.4000 * units); + Cht := 0; + Cwd := round( 3.2000 * units); + Angle := -36.8699; +end; + +with Vec^.FontInfo[108] do begin + Cdp := round( 2.8284 * units); + Cht := 0; + Cwd := round( 2.8284 * units); + Angle := -45.0000; +end; + +with Vec^.FontInfo[109] do begin + Cdp := round ( 3.2000 * units); + Cht := 0; + Cwd := round( 2.4000 * units); + Angle := -53.1301; +end; + +with Vec^.FontInfo[110] do begin + Cdp := round ( 3.5777 * units); + Cht := 0; + Cwd := round( 1.7889 * units); + Angle := -63.4349; +end; + +with Vec^.FontInfo[111] do begin + Cdp := round ( 3.8806 * units); + Cht := 0; + Cwd := round( 0.9701 * units); + Angle := -75.9638; +end; + +with Vec^.FontInfo[112] do begin + Cdp := round ( 4.0000 * units); + Cht := 0; + Cwd := 0; + Angle := -90.0000; +end; + +with Vec^.FontInfo[113] do begin + Cht := round( 2.0000 * units); + Cdp := 0; + Cwd := 0; + Angle := 90.0000; +end; + +with Vec^.FontInfo[114] do begin + Cht := round( 1.7889 * units); + Cdp := 0; + Cwd := round( 0.8944 * units); + Angle := 63.4349; +end; + +with Vec^.FontInfo[115] do begin + Cht := round( 1.4142 * units); + Cdp := 0; + Cwd := round( 1.4142 * units); + Angle := 45.0000; +end; + +with Vec^.FontInfo[116] do begin + Cht := round( 0.8944 * units); + Cdp := 0; + Cwd := round( 1.7889 * units); + Angle := 26.5651; +end; + +with Vec^.FontInfo[117] do begin + Cht := 0; + Cdp := 0; + Cwd := round( 2.0000 * units); + Angle := 0.0000; +end; + +with Vec^.FontInfo[118] do begin + Cdp := round( 0.8944 * units); + Cht := 0; + Cwd := round( 1.7889 * units); + Angle := -26.5651; +end; + +with Vec^.FontInfo[119] do begin + Cdp := round( 1.4142 * units); + Cht := 0; + Cwd := round( 1.4142 * units); + Angle := -45.0000; +end; + +with Vec^.FontInfo[120] do begin + Cdp := round ( 1.7889 * units); + Cht := 0; + Cwd := round( 0.8944 * units); + Angle := -63.4349; +end; + +with Vec^.FontInfo[121] do begin + Cdp := round ( 2.0000 * units); + Cht := 0; + Cwd := 0; + Angle := -90.0000; +end; + +with Vec^.FontInfo[122] do begin + Cht := round( 1.0000 * units); + Cdp := 0; + Cwd := 0; + Angle := 90.0000; +end; + +with Vec^.FontInfo[123] do begin + Cht := round( 0.7071 * units); + Cdp := 0; + Cwd := round( 0.7071 * units); + Angle := 45.0000; +end; + +with Vec^.FontInfo[124] do begin + Cht := 0; + Cdp := 0; + Cwd := round( 1.0000 * units); + Angle := 0.0000; +end; + +with Vec^.FontInfo[125] do begin + Cdp := round( 0.7071 * units); + Cht := 0; + Cwd := round( 0.7071 * units); + Angle := -45.0000; +end; + +with Vec^.FontInfo[126] do begin + Cdp := round ( 1.0000 * units); + Cht := 0; + Cwd := 0; + Angle := -90.0000; +end; + +with Vec^.FontInfo[127] do begin + Cht := 0; + Cdp := 0; + Cwd := 0; + Angle := -90.0000; +end; + +end; (* define vectors *) + + + + +{-------------------------------------------------} +(* If, for some reason, you do not want to deal with + music capabilities, replace the body of this procedure + with just a begin end; pair and also the TylBeam proc. +*) +procedure definebeams (* var M : pMusFontInfRec *); +var i : integer; + begin + +end; + +{----------------------------------------------------------} +(* use pre-calculated coordinates of a circle that has a + * given unit-radius. Scale those points to fit the desired radius + *) +procedure defineCircleCpts (rad : ScaledPts; centx, centy : ScaledPts; + var CircleCpt : ControlPoints; + var numpts : integer); +const UnitRadius = 16777216; (* TWO24 scaledpts *) +var ratio : real; +begin + if (rad = 0) then + begin + complain (ERRBAD); + writeln(logfile,'Error in fig#',pgfigurenum:0,' on page ',currpagenum:0); + writeln(logfile,'Zero length radius for circle! Setting to 1 sp'); + rad := 1; + end; + ratio := float(rad) / float(UnitRadius); + numpts := 16; + CircleCpt[1,1] := round (ratio * 16777216.00000) + centx; + CircleCpt[1,2] := 0 + centy; {round (ratio * 0.00000)} + CircleCpt[2,1] := round (ratio * 15500126.47492) + centx; + CircleCpt[2,2] := round (ratio * 6420362.60441) + centy; + CircleCpt[3,1] := round (ratio * 11863283.20303) + centx; + CircleCpt[3,2] := round (ratio * 11863283.20303) + centy; + CircleCpt[4,1] := round (ratio * 6420362.60441) + centx; + CircleCpt[4,2] := round (ratio * 15500126.47492) + centy; + CircleCpt[5,1] := 0 + centx; {round (ratio * -0.00000) } + CircleCpt[5,2] := round (ratio * 16777216.00000) + centy; + CircleCpt[6,1] := round (ratio * -6420362.60441) + centx; + CircleCpt[6,2] := round (ratio * 15500126.47492) + centy; + CircleCpt[7,1] := round (ratio * -11863283.20303) + centx; + CircleCpt[7,2] := round (ratio * 11863283.20303) + centy; + CircleCpt[8,1] := round (ratio * -15500126.47492) + centx; + CircleCpt[8,2] := round (ratio * 6420362.60441) + centy; + CircleCpt[9,1] := round (ratio * -16777216.00000) + centx; + CircleCpt[9,2] := 0 + centy; {round (ratio * -0.00000)} + CircleCpt[10,1] := round (ratio * -15500126.47492) + centx; + CircleCpt[10,2] := round (ratio * -6420362.60441) + centy; + CircleCpt[11,1] := round (ratio * -11863283.20303) + centx; + CircleCpt[11,2] := round (ratio * -11863283.20303) + centy; + CircleCpt[12,1] := round (ratio * -6420362.60441) + centx; + CircleCpt[12,2] := round (ratio * -15500126.47492) + centy; + CircleCpt[13,1] := 0 + centx; {round (ratio * 0.00000) } + CircleCpt[13,2] := round (ratio * -16777216.00000) + centy; + CircleCpt[14,1] := round (ratio * 6420362.60441) + centx; + CircleCpt[14,2] := round (ratio * -15500126.47492) + centy; + CircleCpt[15,1] := round (ratio * 11863283.20303) + centx; + CircleCpt[15,2] := round (ratio * -11863283.20303) + centy; + CircleCpt[16,1] := round (ratio * 15500126.47492) + centx; + CircleCpt[16,2] := round (ratio * -6420362.60441) + centy; + (* create the pre-list phantom *) + CircleCpt[0,1] := CircleCpt[16,1]; + CircleCpt[0,2] := CircleCpt[16,2]; +end; + + +{---------------------------------------------------------------} +(* compute control points for an arc going from startangle to + * stopangle, centered at (centx, centy) + *) +procedure definearcpts (rad : ScaledPts; centx, centy : ScaledPts; + startang, stopang : integer; + var cpts : ControlPoints; + var nknots : integer); +var n : integer; + a, b, curr, delta: real; + i : integer; +begin + a := startang * DEGTORAD; + b := stopang * DEGTORAD; + n := 16; + + if (a > b) then + begin + a := a - (2 * PI); + end; + + delta := abs(b - a) / n; + + if (a = b) then + begin + complain (ERRNOTBAD); + writeln(logfile,'Error in compute arc points:: should be a circle'); + end; + curr := a; + i := 1; + while ((curr <= b)) do + begin (* make arc about (centx,centy) *) + cpts[i,1] := round (rad * cos (curr)) + centx; + cpts[i,2] := round (rad * sin (curr)) + centy; + i := i + 1; + curr := curr + delta; + end; (* while *) + +(* go one point beyond -- + * around the arc so that we can have good smoothness + * for this phantom point + *) + + cpts[i,1] := round (rad * cos (b + delta)) + centx; + cpts[i,2] := round (rad * sin (b + delta)) + centy; + +(* and one phantom point before the list *) + cpts[0,1] := round (rad * cos (a - delta)) + centx; + cpts[0,2] := round (rad * sin (a - delta)) + centy; + + + nknots := i-1; +end; + + + +(* &&Module spline.p *) +(* + Procedures below may make free use of the global variables + arrayXY [list of control points] + pointmatrix [list of spline segments] + knot [list of spline knots] + catrommtx [matrix for Catmull-Rom splines] + bsplmtx [matrix for B-splines] + lastPoint, intervals +*) + + +{-----------------------------------------------------} +function max (a, b: integer):integer; +begin + if (a > b) then + max := a + else + max := b; +end; + +{-----------------------------------------------------} +function min (a, b: integer):integer; +begin + if (a < b) then + min := a + else + min := b; +end; + +{---------------------------------------------------------------------} +(* initialize the Catmull-Rom basis matrix *) + +procedure initcrmatrix; +begin + catrommtx[1,1] := -0.5; catrommtx[1,2] := 1.5; + catrommtx[1,3] := -1.5; catrommtx[1,4] := 0.5; + catrommtx[2,1] := 1.0; catrommtx[2,2] := -2.5; + catrommtx[2,3] := 2.0; catrommtx[2,4] := -0.5; + catrommtx[3,1] := -0.5; catrommtx[3,2] := 0.0; + catrommtx[3,3] := 0.5; catrommtx[3,4] := 0.0; + catrommtx[4,1] := 0.0; catrommtx[4,2] := 1.0; + catrommtx[4,3] := 0.0; catrommtx[4,4] := 0.0; +end; + +{-----------------------------------------------------} +procedure initbsplmatrix; +begin + bsplmtx[1,1] := -1.0/6.0; bsplmtx[1,2] := 0.5; + bsplmtx[1,3] := -0.5; bsplmtx[1,4] := 1.0/6.0; + bsplmtx[2,1] := 0.5; bsplmtx[2,2] := -1.0; + bsplmtx[2,3] := 0.5; bsplmtx[2,4] := 0.0; + bsplmtx[3,1] := -0.5; bsplmtx[3,2] := 0.0; + bsplmtx[3,3] := 0.5; bsplmtx[3,4] := 0.0; + bsplmtx[4,1] := 1.0/6.0; bsplmtx[4,2] := 2.0/3.0; + bsplmtx[4,3] := 1.0/6.0; bsplmtx[4,4] := 0.0; +end; + +{--------------------------------------------------------} +(* init the Cardinal Spline Matrix *) +procedure initcardmatrix; +begin + cardmtx[1,1] := -1.0; cardmtx[1,2] := 1.0; + cardmtx[1,3] := -1.0; cardmtx[1,4] := 1.0; + cardmtx[2,1] := 2.0; cardmtx[2,2] := -2.0; + cardmtx[2,3] := 1.0; cardmtx[2,4] := -1.0; + cardmtx[3,1] := -1.0; cardmtx[3,2] := 0.0; + cardmtx[3,3] := 1.0; cardmtx[3,4] := 0.0; + cardmtx[4,1] := 0.0; cardmtx[4,2] := 1.0; + cardmtx[4,3] := 0.0; cardmtx[4,4] := 0.0; +end; + +{--------------------------------------------------------} +procedure initallspline; + begin + initcrmatrix; + initbsplmatrix; + initcardmatrix; + end; + + +{-----------------------------------------------------} +procedure matXvector (var m: Fourby4Matrix; (* IN *) + var v: Oneby4Vector; (* IN *) + var result: Oneby4Vector); (* OUT *) +var t: Oneby4Vector; +begin + t[1] := v[1]*m[1,1] + v[2]*m[1,2] + v[3]*m[1,3] + v[4]*m[1,4]; + t[2] := v[1]*m[2,1] + v[2]*m[2,2] + v[3]*m[2,3] + v[4]*m[2,4]; + t[3] := v[1]*m[3,1] + v[2]*m[3,2] + v[3]*m[3,3] + v[4]*m[3,4]; + t[4] := v[1]*m[4,1] + v[2]*m[4,2] + v[3]*m[4,3] + v[4]*m[4,4]; + result[1] := t[1]; result[2] := t[2]; + result[3] := t[3]; result[4] := t[4]; +end; + +{-----------------------------------------------------} +(* actually the dot-product *) +function vecXvec (var v1, v2: Oneby4Vector) : real; +begin + vecXvec := v1[1]*v2[1] + v1[2]*v2[2] + v1[3]*v2[3] + v1[4]*v2[4]; +end; + + +{------------------------------------------------------} +(* basXctl is the pre-computed BasisMatrix times the control-point vector *) + +function splinePosition (var basXctl : Oneby4Vector; (* IN *) + t : real ) : real; +var tvect : Oneby4Vector; { vector of t values for spline matrix} +begin + tvect[4] := 1.0; + tvect[3] := t; + tvect[2] := t * t; + if (tvect[2] <= MINREAL) then + begin (* avoid underflow problems *) + tvect[2] := 0.0; + end; + tvect[1] := t * tvect[2]; (* t^3 *) + splinePosition := vecXvec (tvect, basXctl); +end; + +{-------------------------------------------------} +function TwoToThe (n : integer) : integer; +label 78; +var i : integer; + tmp : integer; +begin +tmp := 1; +if (n <= 0) then + goto 78; +if (n < 6) then + begin + case n of + 1 : tmp := 2; + 2 : tmp := 4; + 3 : tmp := 8; + 4 : tmp := 16; + 5 : tmp := 32; + end; (* case *) + end (* if *) +else + begin + tmp := 32; + for i := 6 to n do + tmp := tmp * 2; + end; +78: + TwoToThe := tmp; +end; + +{------------------------------------------------------} +function distance (x0, y0, x1, y1 : real) : real; +var res : real; +begin + res := sqrt ( (x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0)); + distance := res; +end; + + +{------------------------------------------------------} +(* compute the number of subdivisions for this span. + We do this by a quadrature method and a simple linear-distance + metric. This is not optimal in the number of subdivisions actually + required, but is computationally efficient and accurate to the + nearest power of 2 . + *) +function numsubdivisions (var XtimesBas, YtimesBas : Oneby4Vector; + resolution : ScaledPts): integer; +var n : integer; + d : integer; + t : real; + x0, y0, xt, yt : real; +begin + x0 := splinePosition (XtimesBas, 0.0); + y0 := splinePosition (YtimesBas, 0.0); + + t := 1.0; + n := 0; + xt := splinePosition (XtimesBas, t); + yt := splinePosition (YtimesBas, t); + + while ((round (distance (x0, y0, xt, yt)) > resolution) or + (n < 1)) do + begin + t := t / 2.0; (* perform the quadrature *) + n := n + 1; + xt := splinePosition (XtimesBas, t); + yt := splinePosition (YtimesBas, t); + end; (* while *) + numsubdivisions := TwoToThe (n); +end; + +{------------------------------------------------------------------------} +(* compute new control vertices such that the resulting spline + * will interpolate through the old control points. + * This will work as long as the actual arc length + * between consecutive nodes does not vary from span to span. + * The method is noted in Wu and Abel's CACM 20(10) Oct 77 paper + * but the actual working method is from + * Barsky and Greenberg's paper in + * CG&IP 14(3) Nov 1980 pp.203-226 + *) +procedure invertsplvertices (numpts : integer; + isclosed : boolean; + var xys : ControlPoints); (* INOUT *) +var i : integer; + beta, Xrprime, Yrprime : array[0..MAXCTLPTS] of real; + tempxys : ControlPoints; +begin + (* compute the values of beta *) + beta[1] := 0.25; + for i := 2 to numpts + 1 do + beta[i] := 1.0 / (4.0 - beta[i - 1]); + + (* and the r primes from the original vertices *) + Xrprime[1] := beta[1] * xys[1,1] * 5.0; + Yrprime[1] := beta[1] * xys[1,2] * 5.0; + for i := 2 to numpts -1 do + begin + Xrprime[i] := beta[i] * (6.0 * xys[i,1] - Xrprime[i - 1]); + Yrprime[i] := beta[i] * (6.0 * xys[i,2] - Yrprime[i - 1]); + end; (* for *) + Xrprime[numpts] := beta[numpts] * (5.0 * xys[numpts,1] - Xrprime[numpts - 1]); + Yrprime[numpts] := beta[numpts] * (5.0 * xys[numpts,2] - Yrprime[numpts - 1]); + +(* Now perform the back-substitution from the bottom up *) + tempxys[numpts,1] := round (Xrprime[numpts]); + tempxys[numpts,2] := round (Yrprime[numpts]); + for i := numpts - 1 downto 1 do + begin + tempxys[i,1] := round (Xrprime[i] - beta[i] * tempxys[i + 1, 1]); + tempxys[i,2] := round (Yrprime[i] - beta[i] * tempxys[i + 1, 2]); + end; + +if (isclosed) then + begin + (* at this point, we've probably been through one control-point + * adjustment, so let's not muck it up + *) + tempxys[numpts+1,1] := tempxys[1,1]; + tempxys[numpts+1,2] := tempxys[1,2]; + tempxys[numpts+2,1] := tempxys[2,1]; + tempxys[numpts+2,2] := tempxys[2,2]; + tempxys[0,1] := tempxys[numpts,1]; + tempxys[0,2] := tempxys[numpts,2]; + (* copy them back *) + for i := 0 to (numpts+2) do + begin + xys[i,1] := tempxys[i,1]; + xys[i,2] := tempxys[i,2]; + end; + end (* closed *) +else + begin + (* copy back *) + for i := 2 to numpts -1 do + begin + xys[i,1] := tempxys[i,1]; + xys[i,2] := tempxys[i,2]; + end; + end; (* open*) +end; + + +{-----------------------------------------------------} +(* adjust the list of control points so that we can use + * it for B-spline interpolation. + * Add any "phantom" vertices necessary so that the end + * conditions will be correct for interpolation + *) +procedure Bctlptadjust (isclosed : boolean; isarc : boolean; + var n: integer; (* INOUT *) + var xys: ControlPoints; (* INOUT *) + var thx: ThickAryType); (* INOUT *) +var j : integer; + tmp : ControlPoints; + tmpthx : ThickAryType; +begin (* ctlpt adjust*) + +if (isclosed) then + begin +(* here, we have to supply the last 'real' point for the user, + and add three phantoms-- one before, and two after *) + + if (n = 2) then + begin + complain (ERRBAD); + writeln(logfile,'A closed spline requires more than 2 control points '); + writeln(logfile,'making a temporary fix in order to continue...'); + xys[3,1] := xys[1,1]; + xys[3,2] := xys[1,2]; + end; + + for j := 1 to (n) do + begin + tmp[j, 1] := xys[j, 1]; + tmp[j, 2] := xys[j, 2]; + tmpthx[j] := thx[j]; + end; + (* Now take care of the 'phantom' vertices *) + tmp[n+1, 1] := xys[1, 1]; + tmp[n+1, 2] := xys[1, 2]; + tmpthx[n+1] := thx[1]; + tmp[n+2, 1] := xys[2, 1]; + tmp[n+2, 2] := xys[2, 2]; + tmpthx[n+2] := thx[2]; + tmp[n+3, 1] := xys[3, 1]; + tmp[n+3, 2] := xys[3, 2]; + tmpthx[n+3] := thx[3]; + + if (not isarc) then + begin + tmp[0,1] := xys[n, 1]; (* wrap around to the real last point *) + tmp[0,2] := xys[n, 2]; + tmpthx[0] := thx[n]; + end + else + begin + tmp[0,1] := xys[0,1]; + tmp[0,2] := xys[0,2]; + tmpthx[0] := thx[0]; + end; + + n := n + 1; (* we supplied the 'last' point for the user *) + + for j := 0 to n+2 do + begin + xys[j,1] := tmp[j,1]; + xys[j,2] := tmp[j,2]; + thx[j] := tmpthx[j]; + end; (* for *) + end (* if closed *) +else + begin (* OPEN SPLINE *) + if (not isarc) then + begin + tmp[0,1] := 2 * xys[1, 1] - xys[2,1]; + tmp[0,2] := 2 * xys[1, 2] - xys[2,2]; + end + else + begin + tmp[0,1] := xys[0,1]; + tmp[0,2] := xys[0,2]; + end; + tmpthx[0] := thx[1]; + + for j := 1 to (n) do + begin + tmp[j, 1] := xys[j, 1]; + tmp[j, 2] := xys[j, 2]; + tmpthx[j] := thx[j]; + end; + + tmp[n+1, 1] := 2 * xys[n, 1] - xys[n-1,1]; + tmp[n+1, 2] := 2 * xys[n, 2] - xys[n-1,2]; + tmpthx[n+1] := thx[n]; + + tmp[n+2, 1] := tmp[n+1, 1]; + tmp[n+2, 2] := tmp[n+1, 2]; + tmpthx[n+2] := thx[n]; + + for j := 0 to n+2 do + begin + xys[j,1] := tmp[j,1]; + xys[j,2] := tmp[j,2]; + thx[j] := tmpthx[j]; + end; (* for *) + end; (* if open *) + +end; + + + +{-----------------------------------------------------} +(* adjust the list of control points so that we can use + * it for simple Catmull-Rom spline interpolation. + * Add any "phantom" vertices necessary so that the end + * conditions will be correct for interpolation + *) +procedure CRctlptadjust (isclosed : boolean; isarc : boolean; + var n: integer; (* INOUT *) + var xys: ControlPoints; (* INOUT *) + var thx: ThickAryType); (* INOUT *) +var j : integer; + tmp : ControlPoints; + tmpthx : ThickAryType; +begin (* ctlpt adjust*) +if (isclosed) then + begin +(* here, we have to supply the last 'real' point for the user, + and add three phantoms-- one before, and two after *) + + if (n = 2) then + begin + complain (ERRBAD); + writeln(logfile,'A closed spline requires more than 2 control points '); + writeln(logfile,'making a temporary fix in order to continue...'); + xys[3,1] := xys[1,1]; + xys[3,2] := xys[1,2]; + end; + + + for j := 1 to (n) do + begin + tmp[j, 1] := xys[j, 1]; + tmp[j, 2] := xys[j, 2]; + tmpthx[j] := thx[j]; + end; + (* the phantom vertices *) + tmp[n+1, 1] := xys[1, 1]; + tmp[n+1, 2] := xys[1, 2]; + tmpthx[n+1] := thx[1]; + tmp[n+2, 1] := xys[2, 1]; + tmp[n+2, 2] := xys[2, 2]; + tmpthx[n+2] := thx[2]; + tmp[n+3, 1] := xys[3, 1]; + tmp[n+3, 2] := xys[3, 2]; + tmpthx[n+3] := thx[3]; + + if (not isarc) then + begin + tmp[0,1] := xys[n, 1]; (* wrap around to the real last point *) + tmp[0,2] := xys[n, 2]; + tmpthx[0] := thx[n]; + end + else + begin + tmp[0,1] := xys[0,1]; + tmp[0,2] := xys[0,2]; + tmpthx[0] := thx[0]; + end; + n := n + 1; (* we supplied the 'last' point for the user *) + + for j := 0 to n+2 do + begin + xys[j,1] := tmp[j,1]; + xys[j,2] := tmp[j,2]; + thx[j] := tmpthx[j]; + end; (* for *) + end (* if closed *) +else + begin (* OPEN SPLINE *) + if (not isarc) then + begin + tmp[0,1] := xys[1, 1]; (* double the first point *) + tmp[0,2] := xys[1, 2]; + end + else + begin + tmp[0,1] := xys[0,1]; + tmp[0,2] := xys[0,2]; + end; + tmpthx[0] := thx[1]; + + for j := 1 to (n) do + begin + tmp[j, 1] := xys[j, 1]; + tmp[j, 2] := xys[j, 2]; + tmpthx[j] := thx[j]; + end; + + tmp[n+1, 1] := xys[n, 1]; (* and triple the last *) + tmp[n+1, 2] := xys[n, 2]; + tmpthx[n+1] := thx[n]; + tmp[n+2, 1] := xys[n, 1]; + tmp[n+2, 2] := xys[n, 2]; + tmpthx[n+2] := thx[n]; + + for j := 0 to n+2 do + begin + xys[j,1] := tmp[j,1]; + xys[j,2] := tmp[j,2]; + thx[j] := tmpthx[j]; + end; (* for *) + end; (* if open *) +end; (* ctlpt adjust *) + + + +{----------------------------------------------------------} + +procedure interpsplines (splinetype: SplineKind; + isclosed: boolean; + isanArc: boolean; + linepatt : LineStyle; + var basismatrix : Fourby4Matrix; (* IN *) + numctls: integer; + var arrayXY: ControlPoints; (* IN *) + var pointmatrix: SplineSegments; (* OUT *) + varythicks: boolean; + var thickmatrix: ThickAryType; (* IN *) + var TTmatrix: ThickAryType); (* OUT *) +label 32; +var xctl, yctl, { vectors of x, y posits of control points} + wctl : Oneby4Vector; {vector of thicknesses at each ctl pt} + t, incr: real; + Pi: integer; { P sub i } + i, currpt : integer; + theresolution : ScaledPts; + +begin (* interp splines*) + if ((not isclosed) and (isanArc)) then + numctls := numctls + 1; (* lie a little *) + + case (splinetype) of + + BSPL: Bctlptadjust (isclosed, isanArc, numctls, arrayXY, thickmatrix); + + CARD, + CATROM: CRctlptadjust (isclosed, isanArc, numctls, arrayXY, thickmatrix); + + INTBSPL: begin + if (isclosed) then + begin + Bctlptadjust (true, isanArc, numctls, arrayXY, thickmatrix); + invertsplvertices (numctls, true, arrayXY); + end + else + begin + invertsplvertices (numctls, false, arrayXY); + Bctlptadjust (false, isanArc, numctls, arrayXY, thickmatrix); + end; (* else *) + end; (* Interpolating Bsplines *) + end; + + if ((not isclosed) and (isanArc)) then + numctls := numctls - 1; (* UN-lie a little *) + + +(* this is the scheme: + * val := t-vector * Basis matrix * point matrix + * [t^3 t^2 t 1] * [[Ms]] * [Pi-1 Pi Pi+1 Pi+2] + * where "Pi-1" is "P sub (i-1)", etc. + * + * But we do this in a round about way: + * Point matrix * basis + * then * t-vector will yield the single value + * + * there are certainly faster ways to do this, + * but this is the easiest to understand + *) + + currpt := 1; + case linepatt of + solid : theresolution := MAXVECLENsp; + dotted, + dashed, + dotdash : theresolution := 3 * MAXVECLENsp; {###} + end; + + for Pi := 1 to (numctls - 1) do + begin + xctl[1] := float(arrayXY[Pi-1, 1]); + xctl[2] := float(arrayXY[Pi, 1]); + xctl[3] := float(arrayXY[Pi+1, 1]); + xctl[4] := float(arrayXY[Pi+2, 1]); + yctl[1] := float(arrayXY[Pi-1, 2]); + yctl[2] := float(arrayXY[Pi, 2]); + yctl[3] := float(arrayXY[Pi+1, 2]); + yctl[4] := float(arrayXY[Pi+2, 2]); + matXvector (basismatrix, xctl, xctl); + matXvector (basismatrix, yctl, yctl); + + (* compute the delta-t increment for this segment + based on a metric for subdivision *) + intervals := numsubdivisions (xctl, yctl, theresolution); + if ((linepatt = solid) and (intervals <= 2)) then + intervals := intervals * 2; + incr := 1.0 / intervals; + + (* avoid over-flowing the "pointmatrix" *) + if ((currpt + intervals - 1) >= MAXSPLINESEGS) then + begin + complain (ERRREALBAD); + writeln (logfile,'error: Too many spline segments required.'); + writeln (logfile,' Reducing the number of control points to get output.'); + goto 32; + end; + + t := 0.0; + while (t < 0.999999999) do + begin + pointmatrix[currpt, 1] := round (splinePosition (xctl, t)); + pointmatrix[currpt, 2] := round (splinePosition (yctl, t)); + + if (varythicks) then + begin + wctl[1] := float(thickmatrix[Pi-1]); + wctl[2] := float(thickmatrix[Pi ]); + wctl[3] := float(thickmatrix[Pi+1]); + wctl[4] := float(thickmatrix[Pi+2]); + matXvector (catrommtx, wctl, wctl); (* requires using Catmull-Rom *) + TTmatrix[currpt] := round (splinePosition (wctl, t)); + end; + + t := t + incr; + currpt := currpt + 1; + end; (* while loop *) + + + end; (* for loop *) + +32: + (* the END-condtion *) + pointmatrix[currpt, 1] := round (splinePosition (xctl, 1.0)); + pointmatrix[currpt, 2] := round (splinePosition (yctl, 1.0)); + if (varythicks) then + begin + wctl[1] := thickmatrix[numctls-2]; + wctl[2] := thickmatrix[numctls-1]; + wctl[3] := thickmatrix[numctls]; + wctl[4] := thickmatrix[numctls+1]; + matXvector (catrommtx, wctl, wctl); (* requires using Catmull-Rom *) + TTmatrix[currpt] := round (splinePosition (wctl, 1.0)); + end; + + lastPoint := currpt; + +end; (* interpsplines *) + + +{----------------------------------------------------------------} +procedure drawSpline (splinetype : SplineKind; + isclosed: boolean; + isanArc: boolean; + patt : LineStyle; + numctls: integer; + var arrayXY: ControlPoints; (* IN *) + var pointmatrix: SplineSegments; (* OUT *) + varythicks: boolean; + var thickmatrix: ThickAryType; (* IN *) + var TTmatrix: ThickAryType); (* OUT *) +begin + lastPoint := 0; + + + case (splinetype) of + CATROM : interpsplines (splinetype, isclosed, isanArc, patt, catrommtx, + numctls, arrayXY, pointmatrix, + varythicks, thickmatrix, TTmatrix); + + CARD : interpsplines (splinetype, isclosed, isanArc, patt, cardmtx, + numctls, arrayXY, pointmatrix, + varythicks, thickmatrix, TTmatrix); + + BSPL : interpsplines (splinetype, isclosed, isanArc, patt, bsplmtx, + numctls, arrayXY, pointmatrix, + varythicks, thickmatrix, TTmatrix); + + INTBSPL : interpsplines (splinetype, isclosed, isanArc, patt, bsplmtx, + numctls, arrayXY, pointmatrix, + varythicks, thickmatrix, TTmatrix); + end; (*Case *) +end; + + +(* &&module TeXtyl *) +{----------------------------------------------------------------} +(* rotate a (x,y) point about mx, my *) +procedure ptrotate (var x, y : integer; + mx, my: integer; + angle : real); +var tmpx, tmpy : integer; + cosa, sina : real; +begin + tmpx := x - mx; + tmpy := y - my; + cosa := cos(angle * DEGTORAD); + sina := sin(angle * DEGTORAD); + x := round(tmpx * cosa - tmpy * sina) + mx; + y := round(tmpx * sina + tmpy * cosa) + my; +end; + +{----------------------------------------------------------------} +(* transform two line points: scale, rotate and translate +*) +procedure xfmlinepts (var x1, y1, x2, y2 : ScaledPts; + offh, offv : ScaledPts; + midx, midy : ScaledPts; + scalefact : real; + theta : real; + dx, dy : ScaledPts; + sx, sy : real); +begin + if ((sx = 0.0) or (sy = 0.0)) then + begin + complain (ERRBAD); + writeln(logfile,'?? Some scale factor is Zero... continuing anyway'); + end; + (* scale about center of item*) + if ((sx <> 1.0) or (sy <> 1.0)) then + begin + x1 := round((x1 - midx) * sx) + midx; + x2 := round((x2 - midx) * sx) + midx; + y1 := round((y1 - midy) * sy) + midy; + y2 := round((y2 - midy) * sy) + midy; + end; + (* rotate if necessary *) + if (theta <> 0.0) then + begin (* rotate about the midpoint *) + ptrotate(x1, y1, midx, midy, theta); + ptrotate(x2, y2, midx, midy, theta); + end; + (* translate *) + x1 := (x1 + round(dx * scalefact) + offh); + x2 := (x2 + round(dx * scalefact) + offh); + y1 := (y1 + round(dy * scalefact) + offv); + y2 := (y2 + round(dy * scalefact) + offv); +end; (* xfmlinepts *) + +{----------------------------------------------------------------} +procedure xfmcontpts (var xpts : ControlPoints; xknots : integer; + offh, offv : ScaledPts; midx, midy : ScaledPts; + scalefact : real; + theta : real; dx, dy : ScaledPts; sx, sy : real); +var i : integer; +begin + (* scale about center of item *) + if ((sx <> 1.0) or (sy <> 1.0)) then + for i := 0 to xknots do + begin + xpts[i,1] := round((xpts[i,1] - midx) * sx) + midx; + xpts[i,2] := round((xpts[i,2] - midy) * sy) + midy; + end; + + if (theta <> 0.0) then + begin (* rotate about center *) + for i := 0 to xknots do + begin + ptrotate (xpts[i,1], xpts[i,2], midx, midy, theta); + end; + end; + (* translate *) + for i := 0 to xknots do + begin + xpts[i,1] := (xpts[i,1] + round(dx * scalefact) + offh); + xpts[i,2] := (xpts[i,2] + round(dy * scalefact) + offv); + end; +end; (* xfmcontpts *) + + +{----------------------------------------------------------------} +(* convert into DVI space and offset by H & V *) +procedure dvilinepts (var x1, y1, x2, y2 : ScaledPts; + offh, offv : ScaledPts); +begin + x1 := (x1 + offh); + x2 := (x2 + offh); + y1 := (y1 * (-1) + offv); + y2 := (y2 * (-1) + offv); +end; + +{----------------------------------------------------------------} +(* convert into DVI space and offset by H & V *) +procedure dvicontpts (var xpts : ControlPoints; xknots : integer; + offh, offv : ScaledPts); +var i : integer; +begin + for i := 0 to xknots do + begin + xpts[i,1] := (xpts[i,1] + offh); + xpts[i,2] := (xpts[i,2] * (-1) + offv); + end; +end; + +{----------------------------------------------------------------} +(* transform all the figure's elements according to the + top-level tranformation requirements in 1st Quadrant space. + then reset the toplevel's xfms. +*) +procedure toplevelxfm (toplev, curfig : pItem; recurlevel : integer); +var pi : pItem; + null1, null2 : ScaledPts; + old1, old2 : ScaledPts; + midx, midy : ScaledPts; +begin + with toplev^ do + begin + midy := (BBty - BBby) div 2; + midx := (BBrx - BBlx) div 2; + end; + pi := curfig^.body^.things; { if recur==0, this is same as toplev } + while (pi <> nil) do + begin + with pi^ do + begin + case (kind) of + Aline : begin + xfmlinepts (lx1, ly1, lx2, ly2, 0, 0, midx, midy, 1.0, + toplev^.figtheta, toplev^.fdx, toplev^.fdy, + toplev^.fsx, toplev^.fsy); + end; + Aspline : begin + xfmcontpts (spts, nsplknots, 0, 0, midx, midy, 1.0, + toplev^.figtheta, toplev^.fdx, toplev^.fdy, + toplev^.fsx, toplev^.fsy); + end; + Attspline : begin + xfmcontpts (ttpts, nttknots, 0, 0, midx, midy, 1.0, + toplev^.figtheta, toplev^.fdx, toplev^.fdy, + toplev^.fsx, toplev^.fsy); + end; + Aarc : begin + null1 := 0; null2 := 0; + old1 := acentx; old2 := acenty; + xfmlinepts (acentx, acenty, null1, null2, 0,0, midx, midy, 1.0, + toplev^.figtheta, toplev^.fdx, toplev^.fdy, + toplev^.fsx, toplev^.fsy); + + xfmcontpts (arcpts, narcknots + 1, 0, 0, old1, old2, 1.0, + toplev^.figtheta, + toplev^.fdx + (acentx - old1), + toplev^.fdy + (acenty - old2), + toplev^.fsx, toplev^.fsy); + end; + Alabel : begin + null1 := 0; null2 := 0; + xfmlinepts (labx, laby, null1, null2, 0, 0, midx, midy, 1.0, + toplev^.figtheta, toplev^.fdx, toplev^.fdy, + toplev^.fsx, toplev^.fsy); + end; + Abeam : ; (* not transformable *) + + Atieslur: ; (* not transformable *) + + Afigure : begin + toplevelxfm (toplev, pi, recurlevel + 1); + end; + end; (* case *) + end; (* with *) + pi := pi^.nextitem; + end; (* while *) + if (recurlevel = 0) then + begin (* reset the toplevel's xfms *) + with toplev^ do + begin + figtheta := 0.0; + fsx := 1.0; fsy := 1.0; + fdx := 0; fdy := 0; + end; + end; +end; + + +{----------------------------------------------------------------} +function scalefitfactor (actualwid, actualht, + goalwid, goalht: ScaledPts): real; +var sx, sy : real; +begin + sx := goalwid/actualwid; + sy := goalht/actualht; + if (sx < sy) then + scalefitfactor := sx + else + scalefitfactor := sy; +end; + + + +(* ---- The handlers for each primitive ---- + * The result of calling each handler is either immediate + * output to the buffer of the commands to produce the + * primitive, OR the primitive gets pushed onto a stack/list + * that defines a current 'figure' (set of prims) for + * output at a later time + * + * Look at linehandle for a basic idea of how the handlers + * work. the others follow pretty closely. + *) + + +{------------------------------------------------------------} +procedure linehandle (figdepth : integer; scalefact: real; + x1, y1, x2, y2 : ScaledPts; + dvih, dviv : ScaledPts; (* possible dvi-offsets *) + thk : VThickness; vk : VectKind; + patt : LineStyle; + minx, maxx, miny, maxy : ScaledPts; + tx, ty: ScaledPts; sx, sy, r : real); +var midx, midy : ScaledPts; + lineitem : pItem; +begin + midx := (minx + maxx) div 2; + midy := (miny + maxy) div 2; + + (* do local primitive -level transformations *) + xfmlinepts (x1, y1, x2, y2, dvih, dviv, + midx, midy, scalefact, r, tx, ty, sx, sy); + + if (figdepth = 0) then + begin (* ---- do the primitive by itself *) + (* re-transform it to the 4th Quadrant *) + dvilinepts (x1, y1, x2, y2, h, v); (* global h and v posit *) + IPUSH; + TylLine (x1, y1, x2, y2, thk, vk, patt); + IPOP; + end + else if (figdepth > 0) then + begin (* ---- Pack it and stack it *) + lineitem := NewItem (Aline); + with lineitem^ do + begin + BBlx := minx; BBby := miny; + BBrx := maxx; BBty := maxy; + lx1 := x1; ly1 := y1; + lx2 := x2; ly2 := y2; + itemthick := thk; + itemvec := vk; + itempatt := patt; + end; + pushItem (figdepth, lineitem); + end + else if (figdepth < 0) then + begin (* ---- just do it right away without any PUSH/POP pair *) + (* this is the case when we are unpacking a figure for + * immediate output + *) + TylLine (x1, y1, x2, y2, thk, vk, patt); + end; +end; (* linehandle *) + + +(* --- Simple Splines -----*) +{-----------------------------------------------------} +procedure splinehandle (figdepth : integer; scalefact : real; + thetype : SplineKind; isclosed : boolean; + markdiam : integer; + var contpts : ControlPoints; + nknots : integer; + dvih, dviv : ScaledPts; (* possible dvi-offsets *) + thk : VThickness; vec : VectKind; + patt : LineStyle; + minx, maxx, miny, maxy : ScaledPts; + tx, ty : ScaledPts; sx, sy, r : real); +var midx, midy : ScaledPts; + splineitem : pItem; + i : integer; +begin + midx := (minx + maxx) div 2; + midy := (miny + maxy) div 2; + + xfmcontpts (contpts, nknots, dvih, dviv, midx, midy, + scalefact, r, tx, ty, sx, sy); + + if (figdepth = 0) then + begin (* ---- do the primitive *) + (* transform to 4th quad *) + dvicontpts (contpts, nknots, h, v); + IPUSH; + TylSpline (thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam); + IPOP; + end + else if (figdepth > 0) then + begin + splineitem := NewItem (Aspline); + with splineitem^ do + begin + BBlx := minx; BBby := miny; + BBrx := maxx; BBty := maxy; + itemthick := thk; + itemvec := vec; + itempatt := patt; + nsplknots := nknots; + spltype := thetype; + sclosed := isclosed; + dosmarks := markdiam; + for i := 1 to nknots do + begin + spts[i,1] := contpts[i,1]; + spts[i,2] := contpts[i,2]; + end; + end; + pushItem (figdepth, splineitem); + end + else if (figdepth < 0) then + begin + TylSpline (thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam); + end; +end; (* splinehandle *) + + +(* --- Variable thickness splines ----- *) +{-----------------------------------------------------} +procedure ttsplhandle (figdepth : integer; scalefact : real; + thetype : SplineKind; isclosed : boolean; + markdiam : integer; + contpts : ControlPoints; + ttks : ThickAryType; + nknots : integer; + dvih, dviv : ScaledPts; (* possible dvi-offsets *) + vec : VectKind; + patt : LineStyle; + minx, maxx, miny, maxy : ScaledPts; + tx, ty : ScaledPts; sx, sy, r : real); +var midx, midy : ScaledPts; + ttsplitem : pItem; + i : integer; +begin + midx := (minx + maxx) div 2; + midy := (miny + maxy) div 2; + + xfmcontpts (contpts, nknots, dvih, dviv, midx, midy, + scalefact, r, tx, ty, sx, sy); + + if (figdepth = 0) then + begin + (* transform to 4th quad *) + dvicontpts (contpts, nknots, h, v); + IPUSH; + TylThickThinSpline (thetype, isclosed, contpts, ttks, nknots, vec, patt, markdiam); + IPOP; + end + else if (figdepth > 0) then + begin + ttsplitem := NewItem (Attspline); + with ttsplitem^ do + begin + BBlx := minx; BBby := miny; + BBrx := maxx; BBty := maxy; + itemvec := vec; + itempatt := patt; + nttknots := nknots; + tspltype := thetype; + dottmarks := markdiam; + tclosed := isclosed; + for i := 1 to nknots do + begin + ttpts[i,1] := contpts[i,1]; + ttpts[i,2] := contpts[i,2]; + ttarry[i] := ttks[i]; + end; + end; (* ttsplitem *) + pushItem (figdepth, ttsplitem); + end + else if (figdepth < 0) then + begin + TylThickThinSpline (thetype, isclosed, contpts, ttks, nknots, vec, patt, markdiam); + end; + +end; (* ttsplhandle *) + + +(* ---- Musical Beams ---- *) +{-----------------------------------------------------} +procedure beamhandle (depth, siz : integer; bk : BeamKind; + x1, y1, x2, y2 : ScaledPts); +var bmitem : pItem; +begin + if (depth = 0) then + begin + dvilinepts (x1, y1, x2, y2, h, v); + IPUSH; + TylBeam (x1, y1, x2, y2, siz, bk); + IPOP; + end + else if (depth > 0) then + begin + bmitem := NewItem (Abeam); + with bmitem^ do + begin + BBlx := min(x1, x2); BBby := min(y1, y2); + BBrx := max(x1, x2); BBty := max(y1, y2); + bx1 := x1; by1 := y1; + bx2 := x2; by2 := y2; + staf := siz; + bkind := bk; + end; (* with *) + pushItem (depth, bmitem); + end + else if (depth < 0) then + begin + TylBeam (x1, y1, x2, y2, siz, bk); + end; (* else *) +end; (* beamhandle *) + + +(* ---- Musical Ties and Slurs ----- *) +{-----------------------------------------------------} +procedure tieslurhandle (depth: integer; pts : ControlPoints; + numk : integer; minthick, maxthick : VThickness); +var tsitem : pItem; + i : integer; +begin +if (depth = 0) then + begin + dvicontpts (pts, numk, h, v); + IPUSH; + TylTieSlur (pts, numk, minthick, maxthick); + IPOP; + end +else if (depth > 0) then + begin + tsitem := NewItem (Atieslur); + with tsitem^ do + begin + ntknots := numk; + for i := 1 to numk do + begin + tspts[i,1] := pts[i,1]; + tspts[i,2] := pts[i,2]; + end; + minth := minthick; + maxth := maxthick; + end; (* with *) + pushItem (depth, tsitem); + end +else if (depth < 0) then + begin + TylTieSlur (pts, numk, minthick, maxthick); + end; (* else *) +end; (* tieslurhandle *) + + +{---------------------------------------------------------} +procedure arccirclehandle (figdepth : integer; scalefact : real; + cx, cy : ScaledPts; + radius : ScaledPts; + ang1, ang2 : integer; + var contpts : ControlPoints; (* IN *) + nknots : integer; + dvih, dviv : ScaledPts; (* possible dvi-offsets *) + thk : VThickness; vec : VectKind; + patt : LineStyle; + minx, maxx, miny, maxy : ScaledPts; + tx, ty : ScaledPts; sx, sy, r : real); + +var midx, midy : ScaledPts; + middlex, middley : ScaledPts; + arcitem : pItem; + i : integer; + isclosedarc : boolean; + +begin + midx := cx; middlex := (minx + maxx) div 2; + midy := cy; middley := (miny + maxy) div 2; + isclosedarc := (ang1 = ang2); +{ + if (isclosedarc) then + maxspanlen := round ((360.0 / 16.0) * DEGTORAD * radius) + else + maxspanlen := round ((abs(ang2 - ang1) / 16.0) * DEGTORAD * radius); +{ } + + + xfmcontpts (contpts, nknots+1, dvih, dviv, midx, midy, + scalefact, r, tx, ty, sx, sy); + + if (figdepth = 0) then + begin (* ---- just do the primitive *) + (* transform to 4th quad *) + dvicontpts (contpts, nknots+1, h, v); + IPUSH; + doTylArc (isclosedarc, + contpts, nknots, thk, vec, patt); + IPOP; + end + else if (figdepth > 0) then + begin + arcitem := NewItem (Aarc); + with arcitem^ do + begin + BBlx := minx; BBby := miny; + BBrx := maxx; BBty := maxy; + itemthick := thk; + itemvec := vec; + itempatt := patt; + narcknots := nknots; + acentx := cx; + acenty := cy; + aradius := radius; + firstang := ang1; + lastang := ang2; + for i := 0 to nknots+1 do + begin + arcpts[i,1] := contpts[i,1]; + arcpts[i,2] := contpts[i,2]; + end; + end; + pushItem (figdepth, arcitem); + end + else if (figdepth < 0) then + begin + doTylArc (isclosedarc, contpts, nknots, thk, vec, patt); + end; +end; (* arccirclehandle *) + + + +{---------------------------------------------------------} +procedure labelhandle (depth : integer; scalefact: real; + lax, lay : ScaledPts; + dvih, dviv : ScaledPts; (* possible dvi-offsets *) + style : integer; + phrase : strng; + tx, ty : ScaledPts); +var labitem : pItem; + null1, null2 : ScaledPts; +begin +(* xfm the label point if necessary *) + lax := lax + round(tx * scalefact); + lay := lay + round(ty * scalefact); + + if (depth = 0) then + begin + null1 := 0; null2 := 0; + dvilinepts (lax, lay, null1, null2, h, v); + IPUSH; + TylLabel (lax, lay, style, phrase.str, phrase.len); + IPOP; + end + else if (depth > 0) then + begin + labitem := NewItem (Alabel); + with labitem^ do + begin + labx := lax; + laby := lay; + fontstyle := style; + strcopy (phrase.str, labeltext.str, phrase.len); + labeltext.len := phrase.len; + end; + pushItem (depth, labitem); + end + else if (depth < 0) then + begin + TylLabel (lax, lay, style, phrase.str, phrase.len); + end; +end; + + +(* #### Insert new handlers here for new "primitives" + i.e., names callable from the \special[tyl ...] level +*) + + + +{----------------------------------------------------------------} +(* transform the current bbox coordinates, and output the new one *) +procedure newbbox (var minx, maxx, miny, maxy : ScaledPts; + midx, midy : ScaledPts; + sx, sy, rot : real; tx, ty : ScaledPts); +var + (* coords of full bbox for transformation [n/s][e/w][x/y] *) + nex, ney, sex, sey, swx, swy, nwx, nwy: ScaledPts; + temp1, temp2 : integer; +begin + (* describe and transform the bbox *) + nwx := round (minx * sx); nex := round (maxx * sx); + sex := round (maxx * sx); swx := round (minx * sx); + ney := round (maxy * sy); nwy := round (maxy * sy); + swy := round (miny * sy); sey := round (miny * sy); + + ptrotate (nex, ney, midx, midy, rot); + ptrotate (sex, sey, midx, midy, rot); + ptrotate (swx, swy, midx, midy, rot); + ptrotate (nwx, nwy, midx, midy, rot); + + nex := nex + tx; sex := sex + tx; + swx := swx + tx; nwx := nwx + tx; + ney := ney + ty; sey := sey + ty; + swy := swy + ty; nwy := nwy + ty; + (* now find the actual extents of the bbox *) + temp1 := min (nex, nwx); + temp2 := min (swx, sex); + minx := min (temp1, temp2); + + temp1 := min (ney, nwy); + temp2 := min (swy, sey); + miny := min (temp1, temp2); + + temp1 := max (nex, nwx); + temp2 := max (swx, sex); + maxx := max (temp1, temp2); + + temp1 := max (ney, nwy); + temp2 := max (swy, sey); + maxy := max (temp1, temp2); +end; + + +{-----------------------------------------------} +(* find the bounding box of the list of primitives + and/or sub-figures in this Item *) + +procedure findBBox (blot : pItem; + var mnx, mxx, mny, mxy : ScaledPts); +var + pi : pItem; + bmnx, bmxx, bmny, bmxy, midx, midy : ScaledPts; (* bbox [min/max][x/y] *) + tmnx, tmxx, tmny, tmxy : ScaledPts; (* temporary, in case of recursion *) + null1, null2 : ScaledPts; + prescale, postscale : real; + old1, old2 : ScaledPts; +begin + bmnx := TWO24; bmny := TWO24; + bmxx := -TWO24; bmxy :=-TWO24; + if (blot^.kind = Afigure) then + begin (* afigure *) + pi := blot^.body^.things; + while (pi <> nil) do + begin (* find the current bbox of the list of items here *) + if (pi^.kind = Afigure) then + begin (* recur *) + findBBox (pi, tmnx, tmxx, tmny, tmxy); + bmnx := min (bmnx, tmnx); + bmny := min (bmny, tmny); + bmxx := max (bmxx, tmxx); + bmxy := max (bmxy, tmxy); + end + else + begin + bmnx := min (bmnx, pi^.BBlx); + bmny := min (bmny, pi^.BBby); + bmxx := max (bmxx, pi^.BBrx); + bmxy := max (bmxy, pi^.BBty); + end; + pi := pi^.nextitem; + end; (* while *) + (* now transform the items inside, AND the bbox *) + pi := blot^.body^.things; + midx := (bmnx + bmxx) div 2; + midy := (bmny + bmxy) div 2; + (* now take care of any pre and post size requirements *) + (* see also the "figurehandle" proc. *) + with blot^ do + begin +(* ### Keep this scaling biz here, too, for now. May blast it later *) + if ((preWid <> 0) and (preHt <> 0)) then + begin + prescale := scalefitfactor ((bmxx - bmnx), (bmxy - bmny), preWid, preHt); + fsx := fsx * prescale; + fsy := fsy * prescale; + end; + if ((postWid <> 0) and (postHt <> 0)) then + begin + postscale := scalefitfactor ((bmxx - bmnx), (bmxy - bmny), postWid, postHt); + fsx := fsx * postscale; + fsy := fsy * postscale; + end; + +(* the actual scale-up is taken care of later in this proc. *) + end; (* with *) + while (pi <> nil) do + begin + with pi^ do + begin + case (kind) of + Aline : begin + xfmlinepts (lx1, ly1, lx2, ly2, 0, 0, midx, midy, 1.0, + blot^.figtheta, blot^.fdx, blot^.fdy, + blot^.fsx, blot^.fsy); + end; + Aspline : begin + xfmcontpts (spts, nsplknots, 0, 0, midx, midy, 1.0, + blot^.figtheta, blot^.fdx, blot^.fdy, + blot^.fsx, blot^.fsy); + end; + Attspline : begin + xfmcontpts (ttpts, nttknots, 0, 0, midx, midy, 1.0, + blot^.figtheta, blot^.fdx, blot^.fdy, + blot^.fsx, blot^.fsy); + end; + Aarc : begin + null1 := 0; null2 := 0; + old1 := acentx; old2 := acenty; + xfmlinepts (acentx, acenty, null1, null2, 0,0, midx, midy, 1.0, + blot^.figtheta, blot^.fdx, blot^.fdy, + blot^.fsx, blot^.fsy); + xfmcontpts (arcpts, narcknots + 1, 0, 0, old1, old2, 1.0, + blot^.figtheta, + blot^.fdx + (acentx - old1), + blot^.fdy + (acenty - old2), + blot^.fsx, blot^.fsy); + end; + Alabel : begin + null1 := 0; null2 := 0; + xfmlinepts (labx, laby, null1, null2, 0,0, midx, midy, 1.0, + blot^.figtheta, blot^.fdx, blot^.fdy, + blot^.fsx, blot^.fsy); + end; + Abeam : ; (* not transformable *) + + Atieslur: ; (* not transformable *) + Afigure : ; (* do not need to re-transform *) + end; (* case *) + end; (* with *) + pi := pi^.nextitem; + end; (* while *) + (* transform the bbox, and re-find the new bbox *) + newbbox (bmnx, bmxx, bmny, bmxy, midx, midy, blot^.fsx, blot^.fsy, + blot^.figtheta, blot^.fdx, blot^.fdy); + mnx := bmnx; mny := bmny; + mxx := bmxx; mxy := bmxy; + end (* if *) + else (* some other primitive *) + begin + mnx := blot^.BBlx; mny := blot^.BBby; + mxx := blot^.BBrx; mxy := blot^.BBty; + end; (* else *) +end; (* findBBox *) + + +{---------------------------------------------------------} +(* traverse the list, determining the current bounding box for + * the items. We need this to find the mid-point + * for doing any remaining rotations + *) +procedure traverse (thefig, theitem : pItem); +var + minx, maxx, miny, maxy : ScaledPts; + curminx, curmaxx, curminy, curmaxy : ScaledPts; +begin + minx := TWO24; maxx := -TWO24; + miny := TWO24; maxy := -TWO24; + + while (theitem <> nil) do + begin + if (theitem^.kind = Afigure) then + begin (* recur *) + findBBox (theitem, curminx, curmaxx, curminy, curmaxy); + with theitem^ do + begin + BBlx := curminx; BBby := curminy; + BBrx := curmaxx; BBty := curmaxy; + (* reset the symbol's parameters since all the + primitives in it have now been transformed + according to the previous specifications *) + figtheta := 0.0; + fsx := 1.0; fsy := 1.0; + fdx := 0; fdy := 0; + preWid := 0; preHt := 0; + postWid := 0; postHt := 0; + end; (* with *) + minx := min (minx, curminx); miny := min (miny, curminy); + maxx := max (maxx, curmaxx); maxy := max (maxy, curmaxy); + end (* if a figure/symbol*) + else + begin (* a primitive *) + with theitem^ do + begin + minx := min (minx, BBlx); miny := min (miny, BBby); + maxx := max (maxx, BBrx); maxy := max (maxy, BBty); + end; (* with *) + end; (* else *) + theitem := theitem^.nextitem; + end; (* while *) + + with thefig^ do + begin (* set the bounding box for this upper-level symbol defn *) + BBlx := minx; + BBby := miny; + BBrx := maxx; + BBty := maxy; + end; (* with *) +end; (* traverse *) + +(* ----- Figure symbols ----- *) +{---------------------------------------------------} +procedure figurehandle (globalsymlist, symbollist : pItem; dopush : integer); +const DoItNow = -1; + NoScale = 1; +var pi, curfig : pItem; + midx, midy : ScaledPts; + null1, null2 : ScaledPts; + prescale, postscale : real; + tmnx, tmny, tmxx, tmxy : ScaledPts; +begin (* figurehandle *) + + (* PUSH. traverse the lists (recursively if necessary) and + * compute the transformed points. + * Convert to 4th quadrant and offset by H & V. + * We can do this destructively here + * since we're going to output them right away anyhow. + * Then call each respective primitive handler with a level + * of -1 to indicate to do its job immediately. + * POP. + *) + curfig := symbollist; + pi := curfig^.body^.things; + (* find and set the bounding box for + the figure's sub-symbols and primitives *) + if (dopush > 0) then + traverse (curfig, pi); + + (* We eventually transform the items + to 4th Quadrant DVI space and output them! *) + + pi := curfig^.body^.things; + + midy := (globalsymlist^.BBby + globalsymlist^.BBty) div 2; + midx := (globalsymlist^.BBlx + globalsymlist^.BBrx) div 2; + + if (dopush > 0) then + begin (* the top-level figure for outputting *) + + (* convert the bounding box because we are about to enter + into DVI space, and all calls to handlers hereafter + are in terms of DVI coordinates *) + + with globalsymlist^ do + begin + +(* Since there were external specifications about this figure, + fit the current figure's actual size to the + "pre" size (specified by W marker) and/or to the + "post" size (specified by the F marker). + We do this by simple scaling, *without* changing the midpoint + of the bounding box, just its extents + *) + if ((preWid <> 0) and (preHt <> 0)) then + begin + prescale := scalefitfactor ((BBrx - BBlx), (BBty - BBby), preWid, preHt); + fsx := fsx * prescale; + fsy := fsy * prescale; + end; + if ((postWid <> 0) and (postHt <> 0)) then + begin + postscale := scalefitfactor ((BBrx - BBlx), (BBty - BBby), postWid, postHt); + fsx := fsx * postscale; + fsy := fsy * postscale; + end; + tmnx := BBlx; tmny := BBby; tmxx := BBrx; tmxy := BBty; + xfmlinepts (tmnx, tmny, tmxx, tmxy, 0,0, midx, midy, 1.0, + 0.0, 0, 0, fsx, fsy); + + toplevelxfm (globalsymlist, globalsymlist, 0); + + dviBBlx := tmnx; + dviBBrx := tmxx; + dviBBby := tmny; + dviBBty := tmxy; + + xfmlinepts (dviBBlx, dviBBby, dviBBrx, dviBBty, 0,0, + midx, midy, 1.0, 0.0, + - (tmnx - BBlx), - (tmny - BBby), + 1.0, 1.0); + + fdx := fdx - (tmnx - BBlx); + fdy := fdy - (tmny - BBby); + end; + + dvilinepts (dviBBlx, dviBBby, dviBBrx, dviBBty, h, v); + pgfigurenum := pgfigurenum + 1; + + (* We are ready to output the figure to the page *) + writeln(logfile); + write(logfile,'Figure #',pgfigurenum:0,' on page ',currpagenum:0,' is approx. '); +{ write(logfile,((globalsymlist^.BBty - globalsymlist^.BBby) div SPPERPT):0,' pts high and '); + writeln(logfile,((globalsymlist^.BBrx - globalsymlist^.BBlx) div SPPERPT):0,' pts wide (actual size)'); +} + write(logfile,((tmxy - tmny) div SPPERPT):0,' pts high and '); + writeln(logfile,((tmxx - tmnx) div SPPERPT):0,' pts wide (actual size)'); + IPUSH; + + end; + + while (pi <> nil) do + begin + with pi^ do + begin + case (kind) of + Aline : begin + dvilinepts (lx1, ly1, lx2, ly2, h, v); (* DVI h and v posit *) + with globalsymlist^ do + linehandle (DoItNow, NoScale, + pi^.lx1, pi^.ly1, pi^.lx2, pi^.ly2, + 0, 0, + pi^.itemthick, pi^.itemvec, pi^.itempatt, + dviBBlx, dviBBrx, dviBBby, dviBBty, + fdx, -fdy, fsx, fsy, -figtheta); + end; (* Aline *) + + Aspline : begin + dvicontpts (spts, nsplknots, h, v); + with globalsymlist^ do + splinehandle (DoItNow, NoScale, pi^.spltype, + pi^.sclosed, pi^.dosmarks, + pi^.spts, pi^.nsplknots, + 0, 0, + pi^.itemthick, pi^.itemvec, pi^.itempatt, + dviBBlx, dviBBrx, dviBBby, dviBBty, + fdx, -fdy, fsx, fsy, -figtheta); + end; (* Aspline *) + + Attspline : begin + dvicontpts (ttpts, nttknots, h, v); + with globalsymlist^ do + ttsplhandle (DoItNow, NoScale, pi^.tspltype, + pi^.tclosed, pi^.dottmarks, + pi^.ttpts, pi^.ttarry, pi^.nttknots, + 0, 0, + pi^.itemvec, pi^.itempatt, + dviBBlx, dviBBrx, dviBBby, dviBBty, + fdx, -fdy, fsx, fsy, -figtheta); + end; (* Attspline *) + + Abeam : begin + dvilinepts (bx1, by1, bx2, by2, h, v); + beamhandle (DoItNow, staf, bkind, bx1, by1, bx2, by2); + end; (* Abeam *) + + Atieslur : begin + dvicontpts (tspts, ntknots, h, v); + tieslurhandle (DoItNow, tspts, ntknots, minth, maxth); + end; (* a tie or slur *) + + Aarc : begin + dvicontpts (arcpts, narcknots + 1, h, v); + with globalsymlist^ do + arccirclehandle (DoItNow, NoScale, + pi^.acentx, pi^.acenty, + pi^.aradius, + pi^.firstang, pi^.lastang, + pi^.arcpts, pi^.narcknots, + 0, 0, + pi^.itemthick, pi^.itemvec, pi^.itempatt, + dviBBlx, dviBBrx, dviBBby, dviBBty, + fdx, -fdy, fsx, fsy, -figtheta); + end; (* arc *) + Alabel : begin + null1 := 0; null2 := 0; + dvilinepts (labx, laby, null1, null2, h, v); + with globalsymlist^ do + labelhandle (DoItNow, NoScale, + pi^.labx, pi^.laby, + 0, 0, + pi^.fontstyle, pi^.labeltext, + fdx, -fdy); + end; (* label *) + + Afigure : begin (* recur *) + figurehandle (globalsymlist, pi, 0); + end; (* another symbol *) + + end; (* case *) + end; (* with *) + pi := pi^.nextitem; + end; (* while *) + if (dopush > 0) then + begin + IPOP; + end; +end; (* figurehandle *) + + + +(* %%% *) +{-----------------------------------------------------} +procedure mainhandlespecials (specnum, numpbytes : integer); +(* specnum is the DVI-number of the special + * numpbytes is the number of parameter bytes + *) +label 888; +const PARSLEN = 50; (* Length of the byte-string-cache *) + EMPTY = 0; +type charset = set of char; +var siz, numknots : integer; (* Lots of temp vars that we use *) + x1, y1, x2, y2 : integer; + sx100, sy100 : real; + transx, transy : ScaledPts; + rot : real; + SPscale : real; + cpts : ControlPoints; + thk : VThickness; + patt : LineStyle; + TTary : ThickAryType; + vk : VectKind; + bk : BeamKind; + markdiam : integer; + radius, ang1, ang2 : integer; + phrase : strng; + style : integer; + nam : strng; + sysnam : strng; (* the first parameter of the \special *) + let : char; + i, gotten : integer; + b : OctByt; + pi : pItem; + minx, miny, maxx, maxy : ScaledPts; + maxthk, minthk : integer; + + tylnam, + beginfigurenam, (* names used for string to string comparisons *) + endfigurenam, + linenam, + splinenam, + ttsplnam, + beamnam, + tieslurnam, + arcnam, + labelnam, + paramnam {internal} : charstring; + + splinetype : SplineKind; + isclosedspline : boolean; + + parsearray : array [1..PARSLEN] of OctByt; (* cache of bytes to run through *) + parsposit, parsmax : integer; (* current and max position in cache *) + usingstream : boolean; (* whether we read/parse using cache or from file *) + + +(*-------------------------------------------------------------- + These procedures depend on the correct ordering of + GETs with respect to the number of bytes read in so far. + precond: byte "b" has been read and gotten < numpbytes + postcond: byte "b" has been read iff gotten < numpbytes. + If your impl. definition of READ is non-standard, you will + have to dink with the ordering and be really careful of + keeping track of 'gotten' and 'numpbytes' variables +--------------------------------------------------------------*) + + function nextpbyte : integer; + begin + if (usingstream) then + begin + if (gotten < numpbytes) then + begin + nextpbyte := Dget1byte; + gotten := gotten + 1; + end + else + nextpbyte := EMPTY; + end + else + begin (* not using stream *) + if (parsposit <= parsmax) then + begin + nextpbyte := parsearray[parsposit]; + parsposit := parsposit + 1; + end + else + begin (* at end of parse array, so read from stream now *) + usingstream := true; + if (gotten < numpbytes) then + begin + nextpbyte := Dget1byte; + gotten := gotten + 1; + end + else + nextpbyte := EMPTY; + end; + end; (* else *) + end; + +(* !!!!! Make sure all these predicates jive correctly with + the key-letter definitions *) +{__________________________________________________________________} + function isanumber (b : integer) : boolean; + begin + isanumber := ((b >= xord['0']) and (b <= xord['9'])); + end; + + function isaletter (b : integer) : boolean; + begin + isaletter := (((b >= xord['A']) and (b <= xord['Z'])) or + ((b >= xord['a']) and (b <= xord['z'])) or + (b = xord['@']) or + (b = xord['"']) ); + end; + + function isaspace (b : integer) : boolean; + begin + isaspace := ((b = xord[' ']) or + (b = CR) or + (b = LF) or + (b = HT) or + (b = FF)); + end; + + function isdelimiter (b : integer) : boolean; + begin + (* not a key-letter *) + isdelimiter := (((b < xord['A']) or (b > xord['Z'])) and + ((b < xord['a']) or (b > xord['z'])) and + (b <> xord['@']) and + (b <> xord['"']) ); + end; + + function isnotnull (b : integer) : boolean; + begin + isnotnull := (b <> EMPTY); + end; + + +{__________________________________________________________________} + function getnumber : integer; + var n : integer; + isneg : boolean; + begin + n := 0; + isneg := false; + while ( (isnotnull (b)) and + (not (isanumber (b)))) do + begin (* not a numeral *) + if (b = xord['-']) then + isneg := true; + b := nextpbyte; + end; + + while (isaspace (b)) do (* Skip spaces *) + b := nextpbyte; + + while ( (isnotnull (b)) and + isanumber (b)) do + begin (* a numeral *) + n := n * 10 + (b - xord['0']); + b := nextpbyte; + end; + + if ((gotten = numpbytes) and + isanumber (b)) then + begin (* end condition *) + n := n * 10 + (b - xord['0']); + end; + + if (isneg) then + getnumber := -(n) + else + getnumber := n; + end; +{__________________________________________________________________} + + function getletter : char; + var k : char; + begin + k := ' '; + while ( (isnotnull (b)) and + (isdelimiter (b) and not (isaspace (b)))) do + begin (* non letter *) + b := nextpbyte; + end; + + if ( (isnotnull (b)) and + ( isaletter (b) or isaspace (b) + and not (isanumber (b)))) then + begin + k := xchr[b]; + b := nextpbyte; + end; + getletter := k; + end; +{__________________________________________________________________} + + function getanything : char; + var k : char; + begin + k := ' '; + while (not (isnotnull (b))) do + begin (* not usable *) + b := nextpbyte; + end; + + if (isnotnull (b)) then + begin + k := xchr[b]; + b := nextpbyte; + end; + getanything := k; + end; + +{**************************************************** + The following routines look for key - letter tokens + that indicate certain attributes for a primitive. + +Currently, the letters used are: + S for scaled-points measurement + P for printers points + M millimeters measurement + C use a Circular vector for drawing + H Horizontal-pen vector + V Vertical vector + B B-spline + I Interpolating B-spline + K Catmull-Rom spline + D Cardinal spline + U Open spline + O closed spline + X put marks on spline control pts + T Transformation marker + R Regular beam characters + G Grace Beam characters + @ Specify center-point for arc/circle + L Line-style + F for beginfigure: Fit figure to wid/ht + W for beginfigure: figure was created at this wid & ht +**************************************************} + + +{__________________________________________________________________} + procedure gettransforms (var sc1, sc2, r : real; + var tr1, tr2 : integer); + label 22; + var i : integer; + dun : boolean; + begin + sc1 := 1.0; sc2 := 1.0; + tr1 := 0; tr2 := 0; + r := 0.0; + i := parsposit - 1; + if (i < 1) then + begin + goto 22; (* exit with defaults *) + end; + dun := false; + while ((i < parsmax) and not dun) do + begin + if (isaletter(parsearray[i])) then + begin + if ((parsearray[i] = xord['t']) or + (parsearray[i] = xord['T'])) then + begin + if (isdelimiter(parsearray[i+1]) and + isdelimiter(parsearray[i-1])) then + begin (* get transform parameters *) + sc1 := getnumber / 100.0; + sc2 := getnumber / 100.0; + tr1 := getnumber; + tr2 := getnumber; + r := float(getnumber); (* degrees about primitive center *) + if (r < 0.0) then + r := r + 360.0; + dun := true; + end; + end; + end; + i := i + 1; + end; (* while *) +22: + end; (* gettransforms *) + +{__________________________________________________________________} + function findmarker (markset : charset) : integer; + label 1111; + var i, sym : integer; + dun : boolean; + begin + i := parsposit - 1; + sym := EMPTY; + if (i < 1) then + goto 1111; + dun := false; + while ((i < parsmax) and not dun) do + begin + if (isaletter(parsearray[i])) then + begin + if (xchr[ parsearray[i] ] in markset) then + begin + if (isdelimiter (parsearray[i+1]) and + isdelimiter (parsearray[i-1])) then + begin + sym := xord[tolowercase(xchr[parsearray[i]])]; + dun := true; + end; + end; + end; (* if a letter *) + i := i + 1; + end; (* while *) +1111: findmarker := sym; + end; + + + + function findscale : integer; + begin + findscale := findmarker(['s','S','p','P','m','M']); + end; + + function findvectkind : integer; + begin + findvectkind := findmarker(['c','C','h','H','v','V']); + end; + + function findlinestyle : integer; + begin + findlinestyle := findmarker(['l','L']); + end; + + function findbeamkind : integer; + begin + findbeamkind := findmarker(['r','R','g','G']); + end; + + function findsplinekind : integer; + begin + findsplinekind := findmarker(['b','B','i','I','k','K','d','D']); + end; + + function findsplclosure : integer; + begin + findsplclosure := findmarker(['o','O','u','U']); + end; + + function findatsign : integer; + begin + findatsign := findmarker(['@']); + end; + + function finddotmark : integer; + begin + finddotmark := findmarker(['x','X']); + end; + + function findfigdimens : integer; + begin + findfigdimens := findmarker(['w','W']); + end; + + function findfitsizes : integer; + begin + findfitsizes := findmarker(['f','F']); + end; + + + {_________________________________________________} + function thescaleof (scal : integer) : real; + begin + if (scal = xord['s']) then + thescaleof := 1 * magfactor + else if (scal = xord['p']) then + thescaleof := SPPERPT * magfactor + else if (scal = xord['m']) then + thescaleof := SPPERMM * magfactor + else if (scal = EMPTY) then + thescaleof := SPPERPT * magfactor; + end; + + + function thevectorof (vkin : integer) : VectKind; + begin + if (vkin = xord['c']) then + thevectorof := VKCirc + else if (vkin = xord['v']) then + thevectorof := VKVert + else if (vkin = xord['h']) then + thevectorof := VKHort + else if (vkin = EMPTY) then + thevectorof := VKCirc; + end; + + function thestyleof (linest : integer) : LineStyle; + begin + if ((linest > 3) or + (linest < 0)) then linest := 0; + case linest of + 0 : thestyleof := solid; + 1 : thestyleof := dotted; + 2 : thestyleof := dashed; + 3 : thestyleof := dotdash; + end; + end; + + + + +(* -----!!!!!!!!!!!! HandleSpecials !!!!!!!!!!!!!------ *) +begin + tylnam := 'tyl'; + beginfigurenam := 'beginfigure'; + endfigurenam := 'endfigure'; + linenam := 'line'; + splinenam := 'spline'; + ttsplnam := 'ttspline'; + beamnam := 'beam'; + tieslurnam := 'tieslur'; + arcnam := 'arc'; + labelnam := 'label'; + paramnam := 'param'; + usingstream := true; (* getting bytes from dvifile *) + + specstart := DVIMark - (specnum - 239 + 1) - 1; + + ourxpos := h; ourypos := v; (* note the global DVI (h,v) coords *) + i := 1; + + b := Dget1byte; (* prime the reading scheme *) + gotten := (specnum - 239 + 1); + + while (isaspace(b)) do + b := nextpbyte; + + let := getletter; + while (let <> ' ') do (* get the name of the system --- Hopefully 'tyl' *) + begin + sysnam.str[i] := tolowercase(let); + sysnam.len := i; + i := i + 1; + let := getletter; + end; + + sysnam.str[i] := chr(32); (* end of string *) + + if (not streq (sysnam.str, tylnam, 3)) then (* TeXtyl doesnt know about this special *) + begin + write (logfile,'The special: '); + writestrng(sysnam,true); + writeln(logfile,' is not tyl-able. Skipping...'); + while (gotten < numpbytes) do + b := nextpbyte; + goto 888; + end; + +(* OTHERWISE: all is okay. Lets look for a primitive to tyl *) + + while (isdelimiter(b)) do + begin + b := nextpbyte; + end; + i := 1; + let := getletter; {xchr[b];} + while (not (isdelimiter(xord[let]))) do (* get the name of the primitive *) + begin + nam.str[i] := tolowercase(let); + nam.len := i; + i := i + 1; + let := getletter; + end; + + nam.str[i] := chr(32); (* end of string *) + + + let := xchr[b]; + +(* Now, fill the parse array with bytes so that we can get + the given parameters, and infer the defaulted params *) + + parsmax := min (PARSLEN, ((numpbytes - gotten) + 1)); + + if (parsmax > 1) then + begin + parsearray[1] := xord[' ']; (* we need this *) + parsearray[2] := b; (* start filling *) + for i := 3 to parsmax do + begin (* fill rest *) + parsearray[i] := nextpbyte; + end; + parsposit := 1; + usingstream := false; (* now we look at bytes in parse array *) + b := nextpbyte; (* start it *) + end + else + begin + usingstream := true; + parsposit := -1; (* undefined *) + end; + + (* --- BEGINFIGURE ---- *) + if streq(nam.str, beginfigurenam, 3) then + begin + multifigure := multifigure + 1; + i := findscale; + SPscale := thescaleof (i); + + gettransforms (sx100, sy100, rot, transx, transy); + (* store all the primitives on pageitems, and dont output + them until we get a endfigure. this way, we can take + care of dealing with all the primitives according to + some global tranformation for the whole figure *) + pi := NewItem (Afigure); + with pi^ do + begin + figtheta := rot; + fsx := sx100; fsy := sy100; + fdx := round (transx * SPscale); + fdy := round (transy * SPscale); + depthnumber := multifigure; (* we're at a new level *) + i := findfigdimens; + if (i <> EMPTY) then + begin + preWid := round (getnumber * SPscale); + preHt := round (getnumber * SPscale); + end; + i := findfitsizes; + if (i <> EMPTY) then + begin + postWid := round (getnumber * SPscale); + postHt := round (getnumber * SPscale); + end; + end; (* with *) + BackupInBuf (DVIMark - specstart); + pushItem (multifigure - 1, pi); + goto 888; + end; + (* ---- ENDFIGURE ---- *) + if streq(nam.str, endfigurenam, 3) then + begin + multifigure := multifigure - 1; + if (multifigure < 0) then + begin + complain (ERRBAD); + write(logfile,'Warning: Too many "endfigure"s !'); + multifigure := 0; + end; + BackupInBuf (DVIMark - specstart); + + if (multifigure = 0) then + begin + (* go do our set of figures (within figures...) *) + figurehandle (pageitems, pageitems, 1); + dispose (pageitems); (* ### should maybe garbage collect here *) + pageitems := nil; + end; (* if *) + goto 888; + end; + + (* --- LINE --- *) + if streq(nam.str, linenam, 3) then + begin + i := findscale; + SPscale := thescaleof(i); + + gettransforms (sx100, sy100, rot, transx, transy); + thk := getnumber; (* get the vector thickness *) + if (thk < 1) then + begin + complain (ERRBAD); + writeln(logfile,'?? Thickness not found. Setting to 1'); + thk := 1; + end; + i := findvectkind; + vk := thevectorof (i); + + i := findlinestyle; + if (i <> EMPTY) then + patt := thestyleof (getnumber) + else + patt := solid; + + x1 := round (getnumber * SPscale); + y1 := round (getnumber * SPscale); + x2 := round (getnumber * SPscale); + y2 := round (getnumber * SPscale); + + minx := min (x1, x2); + maxx := max (x1, x2); + miny := min (y1, y2); + maxy := max (y1, y2); + + BackupInBuf (DVIMark - (specstart)); + cmd1byte (OURFONTFLAG); + linehandle (multifigure, SPscale, x1, y1, x2, y2, 0, 0, thk, vk, patt, + minx, maxx, miny, maxy, + transx, transy, sx100, sy100, rot); + end (* line *) + (* ---- THE SPLINES ---- *) +else if (streq(nam.str, splinenam, 3) or + streq(nam.str, ttsplnam,3)) then + begin + i := findscale; + SPscale := thescaleof (i); + + gettransforms (sx100, sy100, rot, transx, transy); + + if streq(nam.str, splinenam, 3) then + begin + thk := getnumber; + if (thk < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Spline Thickness not found. Setting to 1'); + thk := 1; + end; + end; + i := findvectkind; + vk := thevectorof (i); + + i := findlinestyle; + if (i <> EMPTY) then + patt := thestyleof (getnumber) + else + patt := solid; + + i := findsplinekind; + if (i = xord['b']) then + splinetype := BSPL + else if (i = xord['i']) then + splinetype := INTBSPL + else if (i = xord['k']) then + splinetype := CATROM + else if (i = xord['d']) then + splinetype := CARD + else if (i = EMPTY) then + splinetype := CATROM; + + i := findsplclosure; + if (i = xord['o']) then + isclosedspline := true + else if (i = xord['u']) then + isclosedspline := false + else if (i = EMPTY) then + isclosedspline := false; + + i := finddotmark; + if (i = xord['x']) then + markdiam := getnumber + else if (i = EMPTY) then + markdiam := 0; + + numknots := min (getnumber, MAXCTLPTS); + if (numknots < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Number of spline/ttspline knot points not found. Setting to 1'); + numknots := 1; + end; + + minx := TWO24; miny := TWO24; + maxx := -TWO24; maxy := -TWO24; + + for i := 0 to (numknots + 3) do + begin + cpts[i,1] := 0; + cpts[i,2] := 0; + end; (* for *) + + for i := 1 to numknots do + begin + x1 := round (getnumber * SPscale); + cpts[i,1] := x1; + if (x1 < minx) then + minx := x1; + if (x1 > maxx) then + maxx := x1; + y1 := round (getnumber * SPscale); + cpts[i,2] := y1; + if (y1 < miny) then + miny := y1; + if (y1 > maxy) then + maxy := y1; + end; (* for *) + + if streq(nam.str, ttsplnam, 3) then + begin + for i := 1 to numknots do + begin + TTary[i] := getnumber; + end; + end; + + BackupInBuf (DVIMark - (specstart)); + cmd1byte (OURFONTFLAG); + + if streq(nam.str, splinenam, 3) then + splinehandle (multifigure, SPscale, splinetype, isclosedspline, + markdiam, cpts, numknots, + 0, 0, thk, vk, patt, minx, maxx, miny, maxy, + transx, transy, sx100, sy100, rot) + else + ttsplhandle (multifigure, SPscale, splinetype, isclosedspline, + markdiam, cpts, TTary, numknots, + 0, 0, vk, patt, minx, maxx, miny, maxy, + transx, transy, sx100, sy100, rot); + end (* splines *) + (* --- BEAMS ---- *) + else if streq(nam.str, beamnam, 4) then + begin + i := findscale; + SPscale := thescaleof (i); + + (* no transforms *) + + siz := getnumber; (* the staffsize *) + i := findbeamkind; + if (i = xord['g']) then + bk := grace + else if (i = xord['r']) then + bk := regular + else if (i = EMPTY) then + bk := regular; + + x1 := round (getnumber * SPscale); + y1 := round (getnumber * SPscale); + x2 := round (getnumber * SPscale); + y2 := round (getnumber * SPscale); + + BackupInBuf (DVIMark - (specstart)); + cmd1byte (OURFONTFLAG); + + beamhandle (multifigure, siz, bk, x1, y1, x2, y2); + end (* beam *) + (* ---- TIES AND SLURS ---- *) + else if streq(nam.str, tieslurnam, 3) then + begin + i := findscale; + SPscale := thescaleof (i); + + minthk := getnumber; + if (minthk < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Tie/Slur Min Thickness not found. Setting to 1'); + minthk := 1; + end; + + maxthk := getnumber; + if (maxthk < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Tie/Slur MaxThickness not found. Setting to 1'); + maxthk := 1; + end; + + numknots := min (getnumber, MAXCTLPTS); + if (numknots < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Tie/Slur Number of knot points not found. Setting to 1. Should be 5'); + numknots := 1; + end; + for i := 1 to numknots do + begin + cpts[i,1] := round (getnumber * SPscale); + cpts[i,2] := round (getnumber * SPscale); + end; (* for *) + BackupInBuf (DVIMark - (specstart)); + cmd1byte (OURFONTFLAG); + + tieslurhandle (multifigure, cpts, numknots, minthk, maxthk); + end (* ties and slurs *) + (* --------- ARCS and CIRCLES --------- *) + else if streq (nam.str, arcnam, 3) then + begin + i := findscale; + SPscale := thescaleof (i); + + gettransforms (sx100, sy100, rot, transx, transy); + + thk := getnumber; + if (thk < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Arc Thickness not found. Setting to 1'); + thk := 1; + end; + i := findvectkind; + vk := thevectorof (i); + + i := findlinestyle; + if (i <> EMPTY) then + patt := thestyleof (getnumber) + else + patt := solid; + + radius := round (getnumber * SPscale); + if (radius = 0) then + radius := round(1 * SPscale); + i := findatsign; + if (i <> EMPTY) then + begin + x2 := round (getnumber * SPscale); + y2 := round (getnumber * SPscale); + end + else + begin + x2 := 0; y2 := 0; (* assume center at origin *) + end; + + ang1 := getnumber; + if (abs(ang1) > 360) then + ang1 := ang1 mod 360; + ang2 := getnumber; + if (abs(ang2) > 360) then + ang2 := ang2 mod 360; + + minx := TWO24; miny := TWO24; + maxx := -TWO24; maxy := -TWO24; + + if (ang1 = ang2) then + begin (* a circle *) + defineCircleCpts (radius,x2,y2, cpts, numknots); + end + else + begin (* a real arc *) + definearcpts (radius, x2,y2, ang1, ang2, cpts, numknots); + end; + + for i := 1 to numknots do + begin + x1 := cpts[i,1]; + if (x1 < minx) then + minx := x1; + if (x1 > maxx) then + maxx := x1; + + y1 := cpts[i,2]; + if (y1 < miny) then + miny := y1; + if (y1 > maxy) then + maxy := y1; + end; (* for *) + + BackupInBuf (DVIMark - (specstart)); + cmd1byte (OURFONTFLAG); + + arccirclehandle (multifigure, SPscale, x2, y2, + radius, ang1, ang2, + cpts, numknots, + 0, 0, thk, vk, patt, minx, maxx, miny, maxy, + transx, transy, sx100, sy100, rot) + + end (* arc and circle *) + (* ---------- LABELS --------------*) + else if streq (nam.str, labelnam, 3) then + begin + i := findscale; + SPscale := thescaleof (i); + + style := getnumber; (* font style number *) + if ((style < 1) or (style > MAXLABELFONTS)) then + begin + complain (ERRBAD); + writeln(logfile,'Label style bad? Setting to Style 1'); + style := 1; + end; + + x1 := round (getnumber * SPscale); + y1 := round (getnumber * SPscale); + + let := getletter; + while (let <> '"') do + begin + let := getletter; + end; + i := 0; + let := getanything; (* get next letter or whatever *) + while (let <> '"') do + begin (* get the label phrase *) + i := i + 1; + phrase.str[i] := let; + let := getanything; (* getletter;*) + end; + + phrase.str[i+1] := chr(32); + + phrase.len := i; + + BackupInBuf (DVIMark - specstart); + cmd1byte (OURFONTFLAG); + labelhandle (multifigure, SPscale, x1, y1, 0, 0, style, phrase, 0, 0); + end (* label *) + + (* --------- INTERNAL PARAM -------*) + else if streq (nam.str, paramnam, 3) then + begin + i := getnumber; (* addressable param number *) + + begin + writeln (logfile,' I do not know what internal parameter #',i:0,' is'); + end; (* else *) + BackupInBuf (DVIMark - (specstart)); + end (* Internal param *) + + (* ============== NONE OF THE ABOVE ============== *) + else + begin + complain (ERRNOTBAD); + write (logfile,'Sorry, I don''t know how to tyl '); + writestrng (nam,true); + + while (gotten < numpbytes) do + begin + b := nextpbyte; + end; + end; + 888: + (* make sure that we used up all the bytes in this special *) + if (gotten < numpbytes) then + begin + while (gotten < numpbytes) do + begin (* slurp up excess *) + b := Dgrabbyte; + gotten := gotten + 1; + end; + end; (* if *) + end; (* mainhandlespecials *) + + + (* ================================================== + + The routines below assume coordinates are already in + 4th Quadrant DVI-space + + =====================================================*) + + + + {-----------------------------------------------------} + (* returns 0 if dy.dx not in font + 1 if ok + 2 if ok and caller should use two of the "code"s + coding scheme requires 0<= [dx, dy] <= 16 + AND that max(dx, abs(dy)) is in [0,1,2,4,8,16] + *) +function outvector (dx, dy : integer; var code : integer) : integer; + label 99; + var c : integer; + result : integer; + begin + if (dx < 0) then + begin + outvector := 0; + goto 99; + end; + + result := 0; (* init for potential failure *) + code := (-1); + if (dy < 0) then + begin + c := 160 + dy + dx - 9*max (dx, -dy); + end + else + begin + c := 160 + dy - dx - 7*max (dx, dy); + end; + + (* here translate to OUR coding scheme + and return the correct number + this is needed because "c" thinks the char range + is 0 to 160, while we have only 128 chars *) + + if (c = 0) then (* special cases *) + begin + code := 63; + result := 2; + end + else if (c = 64) then + begin + code := 95; + result := 2; + end + else + begin (* regular ones *) + result := 1; (* just one char is fine *) + if (c in [1..63]) then + code := c - 1 + else if (c in [80..112]) then + code := c - 17 + else if (c in [120..136]) then + code := c - 24 + else if (c in [140..148]) then + code := c - 27 + else if (c in [150..154]) then + code := c - 28 + else if (c = 160) then + code := 127; (* c - 33 *) + end; + 99: + outvector := result; + end; + + + + (* take care of a Manhattan (horizontal /vertical) line *) + {----------------------------------------------------------} +procedure hvline (lx, by, rx, ty, fontindex : integer); + var t, rth, x, y, width, height : integer; + begin + rth := VFontTable[fontindex]^.PenSize; (* thickness of vector in sp *) + if (lx = rx) then + begin (* Vertical line *) + if (ty > by) then + begin + t := by; by := ty; ty := t; (* swap *) + end; + x := round (lx - (rth / 2.0)); + y := by; + width := rth; + height := by - ty; + end + else + begin (* Horizontal line *) + if (ty < by) then + begin + t := by; by := ty; ty := t; (* swap *) + end; + if (lx > rx) then + begin + t := lx; lx := rx; rx := t; (* swap *) + end; + x := lx; + + y := (by + (rth div 2)); (* + rth for {h,v}-space *) + width := rx - lx; + height := rth; + end; + + isetpos (x, y); + cmd1byte (PUTRULE); + cmd4byte (height); + cmd4byte (width); + + (* output two dots on ends of the rules + at lx, by and rx, ty *) + (* the font has already been set before these calls *) + Tyldot (lx, by); + Tyldot (rx, ty); + isetpos (rx, ty); + end; + + + {------------------------------------------------------------} +procedure diagonal (xl, yb, xr, yt : ScaledPts; fontindex: integer); + var t, curx, cury, dx, dy, code : integer; + slope : real; + mxveclen : ScaledPts; + sptovecs : real; + rho : ScaledPts; + + {......................................} + (* compute maximum length vector character that we can use *) + + procedure getincr (var outdx, outdy : integer); + label 99; + var radius, x, y : integer; + sign : integer; + q : real; + + begin (* getincr *) + radius := mxveclen; (* radius of semi-square *) + (* make sure the pt is outside of the semi-square, + scaling down radius if necessary *) + while ( ((xr - curx) < radius) and + (abs (yt - cury) < radius)) do + begin + radius := radius div 2; + end; + if (slope < 0.0) then (* <0 since in 4th quad by now*) + sign := -1 + else + sign := +1; + if (xr = curx) then + begin + outdx := 0; + outdy := sign * radius; + goto 99; + end; + if (yt = cury) then + begin + outdx := abs (radius); + outdy := 0; + goto 99; + end; + + (* compute the intersection with the semi-square, + choose whichever slope is best *) + if (abs (slope) < 1.0) then + begin (* mostly horizontal *) + outdx := abs (radius); + y := yb + round ((curx + abs(radius) - xl) * slope); + outdy := y - cury; + end + else + begin (* mostly vertical *) + x := xl + round ((cury + (sign * radius) - yb) / slope); + outdx := x - curx; + outdy := sign * radius; + end; + + if (abs (outdy) > abs (yt - cury)) then + begin (* truncate *) + outdy := yt - cury; + end; + if (outdx > (xr - curx)) then + begin (* truncate *) + outdx := xr - curx; + end; + if (outdx < 0) then + begin + outdx := 0; + end; + + (* method to find the exact intersection of the line segment + with the semi-circle, used + to determine the x and y values:: + we do this by using the arctangent of the slope as + the angle 'a' from the x-axis. Then use the relation + y = r cos a, and x = r sin a + we can be smart about all this trig stuff by using + the relation : + sin (arctan a) = 1/sqrt(1 + a^2) + cos (arctan a) = a/sqrt(1 + a^2) + Thus: + q := (1.0 / sqrt (slope * slope + 1.0)); + outdx := round (q * radius); + outdy := round (q * radius * slope); + + Unfortunately, we cannot access the Vector Font + coding scheme because the outdx, outdy 's produced + here do no conform to the condition + max (dx, abs(dy)) in [0,1,2,4,8,16] + when converted to vector-font sizes with + sptovecs (see the 'diagonal' proc.). + *) + + 99: + end; (* getincr *) + {.......................................} + + begin (* DIAGONAL *) + if (xr <> xl) then + slope := (yt - yb) / (xr - xl) + else + slope := BIGREAL; (* some illegal value *) + + if (xl > xr) then + begin + t := xl; xl := xr; xr := t; + t := yb; yb := yt; yt := t; + end; (* swap *) + + curx := xl; + cury := yb; + mxveclen := (VFontTable[fontindex]^.MaxVectLen); + rho := mxveclen div 16; (* minimum radius of vector fonts *) + if (rho = 0) then + begin + complain (ERRREALBAD); + writeln(logfile,'Diagonal: Min radius of vector font is zero. setting to 1'); + rho := 1; + end; + + if ((abs(xl - xr) <= rho) and + (abs(yb - yt) <= rho)) then + begin (* pretty much a null line *) + Tyldot (xl, yb); + end + else + begin + sptovecs := 1.0 / rho; (* conversion for scaled pts to vectorfont units *) + + code := -1; (* initialize to a bogus number *) + + (* this conditional really has to have "or" + instead of "and", because of lines that are + *nearly* horizontal or vertical + *) + while (((xr - curx) >= rho) or (abs(yt - cury) >= rho)) do + begin + (* Get the approximate incremental amount. We use this dy/dx + pair in order to index into our vector font coding scheme *) + + getincr (dx, dy); + + (* Get the vector character code corresponding to this + approximate incremental amount *) + t := outvector (round (dx * sptovecs), + round (dy * sptovecs), + code); + (* Now that we have the character code, go find out its actual + physical dimensions for the real dy/dx amounts *) + if (dy > 0) then + dy := VFontTable[fontindex]^.FontInfo[code].Cdp + else + dy := -(VFontTable[fontindex]^.FontInfo[code].Cht); + + dx := VFontTable[fontindex]^.FontInfo[code].Cwd; + + case (t) of + 0: begin + complain (ERRREALBAD); + writeln (logfile,'Error in Diagonal:: bad dydx'); + end; + + 1: begin + isetpos (curx, cury); + iputchar (code); + end; + + 2: begin + isetpos (curx, cury); + iputchar (code); + isetpos (curx + (dx div 2), cury + (dy div 2)); + iputchar (code); + end; + end; (* case *) + + curx := curx + dx; + cury := cury + dy; + end; (* while *) + + if ((code >= 0) and + (((xr - curx) >= rho) and (abs(yt - cury) >= rho))) then + begin + iputchar (code); + end; + end; (* not null line *) + end; + + +{-------------------------------------------------------} +procedure tylBrokenLine (x0, y0, x1, y1, fontindex : integer; + line_type: LineStyle); +label 10; +var useXaxis: boolean; + a0, b0, a1, b1: integer; + a2, a3, b2, b3, K, gap, dot, dash: integer; + s, z, fit: real; + J, frame, T: integer; + Dotgap, Dotdot: integer; + Dashgap, Dashdash: integer; + DDotgap, DDotdot, DDotdash: integer; + a1ma0 : integer; + +{.........................................................} + procedure spread (lt : LineStyle; extra, T : integer); + label 20; + begin + if (T = 0) then + begin { only partial frame fits } + if (useXaxis) then + diagonal (a0, b0, a1, b1, fontindex) + else + diagonal (b0, a0, b1, a1, fontindex); + goto 20; { exit } + end; + J := 0; + s := float (b1 - b0)/float(a1 - a0); + z := float (extra)/float(T); + case lt of + dotted : repeat a2 := a0 + J*frame; + if (extra > 0) then a2 := a2 + round(J*z); + a3 := a2 + dot; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + end; + J := J + 1; + until (a3 >= a1); + dashed : repeat a2 := a0 + J*frame; + if (extra > 0) then a2 := a2 + round(J*z); + a3 := a2 + dash; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + end; + J := J + 1; + until (a3 >= a1); + dotdash : repeat a2 := a0 + J*frame; + if (extra > 0) then a2 := a2 + round(J*z); + a3 := a2 + dash; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + a2 := a3 + gap; + if (extra > 0) then a2 := a2 + round(z*0.5); + a3 := a2 + dot; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + end; + end; + J := J + 1; + until (a3 >= a1); + end; + 20: + end; { spread } + +{......................................................} + procedure balance (lt : LineStyle; extra, T : integer); + label 30; + begin + if (T = 0) then + begin { only partial frame fits } + if (useXaxis) then + diagonal (a0, b0, a1, b1, fontindex) + else + diagonal (b0, a0, b1, a1, fontindex); + goto 30; { exit } + end; + J := 0; + s := float(b1 - b0)/float(a1 - a0); + case lt of + dashed : repeat a2 := a0 + J*frame - extra div 2; + a3 := a2 + dash; + if (J = 0) then a2 := a0; + if (a3 > a1) then a3 := a1; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + end; + J := J + 1; + until (a3 >= a1); + dotdash : repeat a2 := a0 + J*frame - extra div 2; + a3 := a2 + dash; + if (J = 0) then a2 := a0; + if (a3 > a1) then a3 := a1; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + a2 := a3 + gap; + a3 := a2 + dot; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + end; + end; + J := J + 1; + until (a3 >= a1); + end; + 30: + end; { balance } + +{......................................................} + function project (I : integer) : integer; + var K : integer; { gives the projection of lengths onto axes } + begin + K := round(I*float(abs(a1-a0))/s); + if K = 0 then K := 1; + project := K; + end; +{......................................................} + procedure setlengths (findex :integer); + (* sets the "optimal" sizes for textured lines *) + var penrad : integer; + siz : VThickness; + begin + penrad := VFontTable[findex]^.PenSize; + siz := VFontTable[findex]^.psize; + + Dotdot := penrad div siz; Dotgap := 6 * penrad; + Dashdash := 6 * penrad; Dashgap := 6 * penrad; + DDotdash := 6 * penrad; DDotgap := 4 * penrad; + DDotdot := penrad div siz; + end; +{........................................} +procedure setframesize; +begin + case line_type of { length of frame depends on type of broken line } + solid : frame := 0; + dotted : frame := gap + dot; + dashed : frame := gap + dash; + dotdash : frame := 2*gap + dot + dash; + end; +end; + +{.................................................} +begin (* TylBrokenLine *) +if ((x0 = x1) and (y0 = y1)) then + begin + diagonal (x0, y0, x1, y1, fontindex); { null line } + goto 10; + end; + + setlengths (fontindex); + +if (abs (y1-y0) > abs(x1-x0)) then { longer axis is used as base } + begin + useXaxis := false; + a0 := y0; b0 := x0; + a1 := y1; b1 := x1; + end +else + begin + useXaxis := true; + a0 := x0; b0 := y0; + a1 := x1; b1 := y1; + end; +{ the distance between a0 and a1 is now greater than that between b0 and b1. } + +{ redefine distances as integral units along axes } + s := distance (float(a0),float(b0),float(a1),float(b1)); + + case line_type of + solid: ; + dotted: + begin + gap := project(Dotgap); + dot := project(Dotdot); + end; + dashed: + begin + gap := project(Dashgap); + dash := project(Dashdash); + end; + dotdash: + begin + gap := project(DDotgap); + dot := project(DDotdot); + dash := project(DDotdash); + end; + end; + + { ensure direction of line is from smaller to + larger along the longer axis } + if (a0 > a1) then + begin + J := a0; a0 := a1; a1 := J; + J := b0; b0 := b1; b1 := J; + end; + + setframesize; + + a1ma0 := a1 - a0; + + { fit is the number of frames that fit in line } + if (frame <> 0) then + begin + fit := (float(a1ma0) / float(frame)); + end + else + fit := 1.0; + + if (fit >= 1.0) then + T := round (fit) + else + begin + (* change frame elements (dot, dash, gap) since frame is too large *) + case line_type of + dotted : begin + gap := gap - (frame - a1ma0); + if (gap < dot) then + begin + goto 10; (* exit *) + end; + setframesize; + end; + + dashed, + dotdash : begin + (* idea:decrease gap; if too small then shrink dash and refigure gap*) + if ((frame - a1ma0) > (gap div 2)) then + begin + dash := round (dash * fit * 0.80); + gap := round (gap * fit); + setframesize; + end; + gap := gap - (frame - a1ma0); + if (line_type = dotdash) then + gap := gap div 2; + if (gap < dot) then + begin + goto 10; (* exit *) + end; + setframesize; + end; + end; (* case *) + T := 1; (* NOW it will fit *) + end; (* else *) + + + case line_type of + solid : begin + if (useXaxis) then + diagonal (a0, b0, a1, b1, fontindex) + else + diagonal (b0, a0, b1, a1, fontindex); + end; + + dotted : begin { dotted lines begin and end on a dot } + if ((T*frame + dot) = a1ma0) then + spread(dotted, 0, T) + else if ((T*frame + dot) > a1ma0) then + begin +{ gap := gap - ((T*frame+dot)-a1ma0); +{} + spread(dotted, a1ma0 - T*frame - dot, T); + +{ spread(dotted, a1ma0 - (T-1)*frame - dot, T-1); +{} + end + else + spread(dotted, a1ma0 - T*frame - dot, T); + end; + + dashed : begin + { dashed lines begin and end on dash : + the beginning and ending dashes are at least half + the dash length long. } + if ((T*frame + dash) = a1ma0) then + spread(dashed, 0, T) + else if ((T*frame + dash) > a1ma0) then + balance(dashed, T*frame + dash - a1ma0, T) + else spread(dashed, a1ma0 - T*frame - dash, T); + end; + + dotdash : begin { if ending on a dash then beginning and ending + dashes are half the dash length long - final + dots are full dot length } + if ((T*frame + dash) = a1ma0) then + spread(dotdash, 0, T) + else if ((T*frame + dash + gap + dot) = a1ma0) then + spread(dotdash, 0, T) + else if ((T*frame + dash) > a1ma0) then + balance(dotdash, T*frame + dash - a1ma0, T) + else if ((T*frame + dash + gap + dot) > a1ma0) then + spread(dotdash, a1ma0 - T*frame - dash, T) + else spread(dotdash, a1ma0 - T*frame - dash - gap - dot, T); + end; + end; +10: + end; + + + +{-------------------------------------------------------} +procedure clampthickness (var thic : VThickness); + begin + (* #### this is just a simple clamp + really should be something like: + while not (thic in set_of_appropriate_thicknesses) do + modify thic and try again + *) + if (thic <= LoVThick ) then + thic := LoVThick + 1; + while ((not (thic in [1,2,3,4,5,6,7,8,9,10,11,12])) and + (thic <= HiVThick)) do + thic := thic + 1; + + if (thic > HiVThick) then + thic := HiVThick; + end; + +{----------------------------------------------------------} +procedure slurclamp (var thic : ThickAryType; totpts : integer); + (* this post-clamps the sampled thicknesses calculated over the + whole of the spline *) + + var i : integer; + oneseventh : integer; + middle : integer; + startval, endval: integer; + deltaval, val, incrval, alpha, alphaincr: real; + + begin + { $$ NOTE:: How does the ttspline interpolation of thicknesses + compare to the below results?? Can we avoid having it done + elsewhere and concentrate on it here?? } + + oneseventh := round (totpts / 7.0); + for i := 1 to oneseventh do + begin + thic[i] := thic[1]; + end; + for i := 6*oneseventh to totpts do + begin + thic[i] := thic[totpts]; + end; + + middle := round (totpts / 2.0); + for i := 3*oneseventh to 4*oneseventh do + begin + thic[i] := thic[middle]; + end; + + startval := thic[oneseventh - 1]; + endval := thic[3*oneseventh + 1]; + deltaval := (2*(endval - startval))/(2*oneseventh); + alphaincr := PI / (2 * oneseventh + 1); + alpha := PI; + val := float(startval); + for i := oneseventh to (3*oneseventh - 1) do + begin (* interpolate: ease in from minthick to middlethickness *) + alpha := alpha + alphaincr; + incrval := ((cos (alpha) + 1.0) / 2.0) * deltaval; + val := val + incrval; + thic[i] := round(val); + end; + + startval := thic[4*oneseventh - 1]; + endval := thic[6*oneseventh + 1]; + deltaval := (2*(endval - startval))/(2*oneseventh); + alphaincr := PI / (2 * oneseventh + 1); + alpha := 0.0; + val := float(startval); + for i := (4*oneseventh + 1) to 6*oneseventh do + begin (* ease out from middle thickness to min thick at far end *) + alpha := alpha + alphaincr; + incrval := ((cos (alpha) + 1.0) / 2.0) * deltaval; + val := val + incrval; + thic[i] := round(val); + end; + end; + +{-------------------------------------------------------} +procedure layline (xl, yb, xr, yt, fontindex : integer; + pattern : LineStyle; useVecfontOnly : boolean); + var t: integer; + begin + if (xr < xl) then + begin + t := xr; xr := xl; xl := t; + t := yb; yb := yt; yt := t; + end; + + isetfont (VFontTable[fontindex]^.DVIFontNum); + + (* we may want to require using a vector font only, + instead of a combination of vectors and TeX-rules. + It may look better this way. + *) + if (useVecfontOnly) then + begin + tylBrokenLine (xl, yb, xr, yt, fontindex, pattern); + end + else + begin (* be smart about the lines *) + if ((xl = xr) and (yb = yt)) or + ((xl <> xr) and (yb <> yt)) then (* Null or diagonal lines *) + begin + if (pattern = solid) then + diagonal (xl, yb, xr, yt, fontindex) + else + tylBrokenLine (xl, yb, xr, yt, fontindex, pattern); + end + else + begin +{ if (pattern = solid) then + hvline (xl, yb, xr, yt, fontindex) (* make use of rules *) + else +USENORULES } + tylBrokenLine (xl, yb, xr, yt, fontindex, pattern); + end + end; + + end; + + + +{------------------------------------------------------} +procedure layAspline (thetype : SplineKind; + isclosed : boolean; + isanArc: boolean; + domarks : integer; + var cpts : ControlPoints; + numpts : integer; + thick: VThickness; + vkind : VectKind; + patt : LineStyle); + const DontDoThicks = false; + VectorsOnly = true; + var pointList: SplineSegments; + i, xs, ys : integer; + tt1, tt2 : ThickAryType; + F: VecIndex; + begin + + clampthickness (thick); + for i := 0 to (numpts + 3) do + tt1[i] := thick; + + (* do any marks if necessary to show the control points *) + if (domarks > 0) then + begin + F := GetVectFont (domarks, VKCirc); + isetfont (VFontTable[F]^.DVIFontNum); + for i := 1 to numpts do + begin + Tyldot (cpts[i,1], cpts[i,2]); + end; + end; + + drawSpline (thetype, isclosed, isanArc, patt, + numpts, cpts, pointList, DontDoThicks, tt1, tt2); + + + F := GetVectFont (thick, vkind); + xs := pointList[1, 1]; + ys := pointList[1, 2]; + + for i := 2 to lastPoint do + begin + layline (xs, ys, pointList[i, 1], pointList[i, 2], F, patt, VectorsOnly); + xs := pointList[i, 1]; + ys := pointList[i, 2]; + end; + if (isclosed) then (* complete the motion *) + layline (pointList[lastPoint,1], pointList[lastPoint,2], + pointList[1,1], pointList[1,2], F, patt, VectorsOnly); + end; + + +{-----------------------------------------------------} +procedure layNspline (thetype : SplineKind; + isclosed : boolean; + isitaslur : boolean; + domarks : integer; + var cpts : ControlPoints; + numpts : integer; + var thickmatrix : ThickAryType; + vkind : VectKind; + patt : LineStyle); + const NotAnArc = false; + DoThicksToo = true; + VectorsOnly = true; + var pointList: SplineSegments; + i, xs, ys : integer; + ts : VThickness; + tt : ThickAryType; + F : VecIndex; + begin + (* do any marks if necessary to show the control points *) + if (domarks > 0) then + begin + F := GetVectFont (domarks, VKCirc); + isetfont (VFontTable[F]^.DVIFontNum); + for i := 1 to numpts do + begin + Tyldot (cpts[i,1], cpts[i,2]); + end; + end; + + drawSpline (thetype, isclosed, NotAnArc, patt, + numpts, cpts, pointList, + DoThicksToo, thickmatrix, tt); + if ((isitaslur) and (not skiptsclamp)) then + begin + slurclamp(tt, lastPoint); (* which kind of clamping to use *) + end; + + xs := pointList[1, 1]; + ys := pointList[1, 2]; + ts := tt[1]; + + for i := 2 to lastPoint do + begin + clampthickness (ts); + F := GetVectFont (ts, vkind); + layline (xs, ys, pointList[i, 1], pointList[i, 2], F, patt, VectorsOnly); + xs := pointList[i, 1]; + ys := pointList[i, 2]; + ts := tt[i]; + end; + if (isclosed) then + begin + ts := tt[lastPoint]; + clampthickness(ts); + F := GetVectFont (ts, vkind); + layline (pointList[lastPoint,1], pointList[lastPoint,2], + pointList[1,1], pointList[1,2], F, patt, VectorsOnly); + end; + end; + + + +{-----------------------------------------------------} +procedure TylBeam (* fromx, fromy, tox, toy: ScaledPts; + staffsize : integer; kind : BeamKind *); + + begin + + end; (* TylBeam *) + + +{-------------------------------------------------------} +procedure TylLine (* xl, yb, xr, yt: ScaledPoints; + thickness: VThickness; + vec: VectKind; patt : LineStyle *); + const dontCare = false; + var findex: VecIndex; + begin + clampthickness (thickness); + findex := GetVectFont (thickness, vec); + layline (xl, yb, xr, yt, findex, patt, dontCare); + end; + + +{-----------------------------------------------------} +procedure TylThickThinSpline (* thetype : SplineKind; isclosed : boolean; + var KnotArray: ControlPoints; + var ThikThinAry: ThickAryType; + numknots: integer; + vec: VectKind; + patt : LineStyle; domarks : integer *); + const NotAnArc = false; + begin + layNspline (thetype, isclosed, NotAnArc, domarks, KnotArray, numknots, + ThikThinAry, vec, patt); + end; + +{----------------------------------------------------} +procedure TylSpline (* thetype : SplineKind; isclosed : boolean; + var KnotArray: ControlPoints; numknots: integer; + thick: VThickness; vec: VectKind; patt : LineStyle; domarks : integer*); + const NotAnArc = false; + begin + layAspline (thetype, isclosed, NotAnArc, domarks, KnotArray, numknots, + thick, vec, patt); + end; + +{-----------------------------------------------------} +procedure TylTieSlur (* KnotArray: ControlPoints; + numknots: integer; + minthick, maxthick: VThickness *); + const ItsASlur = true; + NotClosed = false; + var ourttarray : ThickAryType; + one7th : real; + val : VThickness; + begin + + clampthickness (minthick); + clampthickness (maxthick); + if (numknots <> 5) then + writeln ('TieSlur needs 5 control points '); + one7th := 1.0/7.0; + val := round (one7th * (maxthick - minthick)); + ourttarray[1] := minthick; + ourttarray[2] := minthick + val; + ourttarray[3] := maxthick; + ourttarray[4] := minthick + val; + ourttarray[5] := minthick; + + layNspline (CATROM, NotClosed, ItsASlur, 0, KnotArray, numknots, ourttarray, + VKCirc, solid); + end; + + +{-------------------------------------------------------} +procedure doTylArc (* iscircle : boolean; + var apts : ControlPoints; + numknots : integer; + thick : VThickness; + vec : VectKind; + patt : LineStyle *); + + const ItsAnArc = true; + begin + + layAspline (BSPL, iscircle, ItsAnArc, 0, apts, numknots, thick, vec, patt); + end; + +{-----------------------------------------------------------} +procedure TylArc (* radius : ScaledPts; centx, centy : ScaledPts; + firstangle, secondangle : integer; + thick : VThickness; vec : VectKind; patt : LineStyle *); + var apts : ControlPoints; + numknots : integer; + iscircle : boolean; + begin + iscircle := (firstangle = secondangle); + if iscircle then + begin + { maxspan := round ((360.0 / 16.0) * DEGTORAD * radius); + {} + defineCircleCpts (radius, centx, centy, apts, numknots); + end + else + begin + { maxspan := round ((abs (secondangle - firstangle) / 16.0) * DEGTORAD * radius); +{ } + definearcpts (radius, centx, centy, + firstangle, secondangle, apts, numknots); + end; + + doTylArc (iscircle, apts, numknots, thick, vec, patt); + + end; + +{-----------------------------------------------------------} +procedure TylLabel (* xpos, ypos : ScaledPts; + fontstyle : integer; + phrase : charstring; + phraselen : integer *); +var findex : integer; + c : integer; + spaceover : integer; + +begin +if ((fontstyle < 1) or (fontstyle > MAXLABELFONTS)) then + begin + complain (ERRREALBAD); + writeln(logfile,'Unexpected bad fontstyle in TylLabel: ',fontstyle:0,'?'); + jumpout; + end; +findex := GetLabFont (fontstyle); +isetpos (xpos, ypos); +IPUSH; +isetfont (LFontTable[findex]^.DVIFontNum); +spaceover := LFontTable[findex]^.spacewidth; +for c := 1 to phraselen do + begin + if (phrase[c] <> xchr[32]) then + begin + cmd1byte (SET1); + cmd1byte (xord[ phrase[ c ]]); + end + else + begin (* move over *) + cmd1byte (RIGHTLEFT + 2); (* assume distance is less than 3 bytes *) + cmdSigned (spaceover, 3); + end; + end; +IPOP; +end; + + +(* && start dvidvi section *) +{-----------------------------------------------------} +procedure initialize; + var + i: integer; + begin + for i := 0 to 31 do + xchr[i] := '?'; + xchr[32] := ' '; + xchr[33] := '!'; + xchr[34] := '"'; + xchr[35] := '#'; + xchr[36] := '$'; + xchr[37] := '%'; + xchr[38] := '&'; + xchr[39] := ''''; + xchr[40] := '('; + xchr[41] := ')'; + xchr[42] := '*'; + xchr[43] := '+'; + xchr[44] := ','; + xchr[45] := '-'; + xchr[46] := '.'; + xchr[47] := '/'; + xchr[48] := '0'; + xchr[49] := '1'; + xchr[50] := '2'; + xchr[51] := '3'; + xchr[52] := '4'; + xchr[53] := '5'; + xchr[54] := '6'; + xchr[55] := '7'; + xchr[56] := '8'; + xchr[57] := '9'; + xchr[58] := ':'; + xchr[59] := ';'; + xchr[60] := '<'; + xchr[61] := '='; + xchr[62] := '>'; + xchr[63] := '?'; + xchr[64] := '@'; + xchr[65] := 'A'; + xchr[66] := 'B'; + xchr[67] := 'C'; + xchr[68] := 'D'; + xchr[69] := 'E'; + xchr[70] := 'F'; + xchr[71] := 'G'; + xchr[72] := 'H'; + xchr[73] := 'I'; + xchr[74] := 'J'; + xchr[75] := 'K'; + xchr[76] := 'L'; + xchr[77] := 'M'; + xchr[78] := 'N'; + xchr[79] := 'O'; + xchr[80] := 'P'; + xchr[81] := 'Q'; + xchr[82] := 'R'; + xchr[83] := 'S'; + xchr[84] := 'T'; + xchr[85] := 'U'; + xchr[86] := 'V'; + xchr[87] := 'W'; + xchr[88] := 'X'; + xchr[89] := 'Y'; + xchr[90] := 'Z'; + xchr[91] := '['; + xchr[92] := '\'; + xchr[93] := ']'; + xchr[94] := '^'; + xchr[95] := '_'; + xchr[96] := '`'; + xchr[97] := 'a'; + xchr[98] := 'b'; + xchr[99] := 'c'; + xchr[100] := 'd'; + xchr[101] := 'e'; + xchr[102] := 'f'; + xchr[103] := 'g'; + xchr[104] := 'h'; + xchr[105] := 'i'; + xchr[106] := 'j'; + xchr[107] := 'k'; + xchr[108] := 'l'; + xchr[109] := 'm'; + xchr[110] := 'n'; + xchr[111] := 'o'; + xchr[112] := 'p'; + xchr[113] := 'q'; + xchr[114] := 'r'; + xchr[115] := 's'; + xchr[116] := 't'; + xchr[117] := 'u'; + xchr[118] := 'v'; + xchr[119] := 'w'; + xchr[120] := 'x'; + xchr[121] := 'y'; + xchr[122] := 'z'; + xchr[123] := '{'; + xchr[124] := '|'; + xchr[125] := '}'; + xchr[126] := '~'; + for i := 127 to 255 do + xchr[i] := '?'; + for i := 0 to 127 do + xord[chr(i)] := 32; + for i := 32 to 126 do + xord[xchr[i]] := i; + initallspline; + initVnMnLtables; + multifigure := 0; + pgfigurenum := 0; + TotBytesWritten := 0; + ourq := 0; + specstart := 0; + currpagenum := 0; + newbackptr := (-1); + oldbackptr := (-1); + ourfontnum := (-1); (* undefined *) + origTexfont := (-1); + ourpushdepth := 0; + FTBDs := 0; + InitDVIBuf; + nf := 0; + inpostamble := false; + didnewfonts := false; + maxpages := 10000; + sysdependent; + s := 0; + skiptsclamp := false; + ErrorOccurred := false; + end; + + + +procedure inputln (var buffer : strng); +var + k: 0..ARRLIMIT; +begin + + flush(output); + + if eoln(input) then + readln(input); + k := 1; + while (k < ARRLIMIT) and (not eoln(input)) do + begin + buffer.str[k] := input^; + k := k + 1; + get(input) + end; + buffer.str[k] := ' '; + buffer.len := k - 1; +end; + +function revindex (st : strng; let : char) : integer; +label 2; +var posit,i : integer; +begin + posit := 0; + for i := st.len downto 1 do + begin + if (st.str[i] = let) then + begin + posit := i; + goto 2; + end; + end; +2: + revindex := posit; +end; + + +procedure stripblanks (var st : strng); +var i,j,k: integer; + temp : charstring; + begin + j := 1; + i := 1; + while ((i <= st.len) and + ((st.str[i] = ' ') or (st.str[i] = xchr[HT]))) do + begin + j := j + 1; + i := i + 1; + end; + +(* j now points to the first non-blank character in st.str *) + i := 1; + for k := j to st.len do + begin + if ((st.str[k] <> ' ') and (st.str[k] <> xchr[HT])) then + begin + temp[i] := st.str[k]; + i := i + 1; + end; + end; + (* now copy it back *) + if (i <> 1) then + begin (* there was blankspace *) + for k := 1 to (i- 1) do + st.str[k] := temp[k]; + st.len := i - 1; + + st.str[i] := chr(32); (* end of string *) + + end; + end; + + +{-----------------------------------------------------} +procedure AskandOpenFiles; +var isok : boolean; + i : integer; + rp : integer; + tempname : strng; +begin + isok := false; + while (not isok) do + begin + write (' DVI-input File Name: '); + inputln (dvifname); + stripblanks (dvifname); + + rp := revindex (dvifname, '.'); + if (rp = 0) then + begin + (* add a ".dvi" extension *) + i := dvifname.len; + dvifname.str[i + 1] := '.'; + dvifname.str[i + 2] := 'd'; + dvifname.str[i + 3] := 'v'; + dvifname.str[i + 4] := 'i'; + dvifname.len := i + 4; + end; + if (not opendvifile) then + begin + isok := false; (* it is empty *) + writestrng(dvifname,false); + writeln(': Empty File?? Try another name.'); + end + else + isok := true; + end; (* while *) + + (* and ask for the name of the output file *) + (* default it to be the same prefix, but with a ".tyl" suffix *) + strcopy (dvifname.str, outname.str, dvifname.len); + outname.len := dvifname.len; + rp := revindex (outname, '.'); + i := rp - 1; + outname.str[i + 1] := '.'; + outname.str[i + 2] := 't'; + outname.str[i + 3] := 'y'; + outname.str[i + 4] := 'l'; + outname.len := i + 4; + + writeln (' DVI-output File Name :'); + write('(different than input name)[default of '); + writestrng (outname,false); + write(']'); + inputln (tempname); + if (tempname.len > 1) then + begin (* a filename was typed in *) + + strcopy (tempname.str, outname.str, tempname.len); + end; + + openoutputfile; + + strcopy (dvifname.str, logfilnam.str, dvifname.len); + logfilnam.len := dvifname.len; + rp := revindex (logfilnam, '.'); + (* add a ".tlog" extension *) + i := rp - 1; + logfilnam.str[i + 1] := '.'; + logfilnam.str[i + 2] := 't'; + logfilnam.str[i + 3] := 'l'; + logfilnam.str[i + 4] := 'o'; + logfilnam.str[i + 5] := 'g'; + logfilnam.len := i + 5; + + openlogfile; +end; + + +{-----------------------------------------------------} + function inTFM (z: integer): boolean; + label + 9997, 9998, 9999; + var + k: integer; + lh: integer; + nw: integer; + alpha, beta: integer; + begin + readtfmword; + lh := b2 * 256 + b3; + readtfmword; + font[nf].bc := b0 * 256 + b1; + font[nf].ec := b2 * 256 + b3; + if (font[nf].ec < font[nf].bc) then + font[nf].bc := font[nf].ec + 1; + readtfmword; + nw := b0 * 256 + b1; + if ((nw = 0) or (nw > 256)) then + goto 9997; + for k := 1 to 3 + lh do + begin + if eof(tfmfile) then + goto 9997; + readtfmword; + if (k = 4) then + if (b0 < 128) then + tfmchecksum := ((b0 * 256 + b1) * 256 + b2) * 256 + b3 + else + tfmchecksum := (((b0 - 256) * 256 + b1) * 256 + b2) * 256 + b3 + end; + + for k := 0 to (font[nf].ec - font[nf].bc) do + begin + readtfmword; + if (b0 > nw) then + goto 9997; + font[nf].widths[k] := b0 + end; + alpha := 16 * z; + beta := 16; + while z >= TWO23 do + begin + z := z div 2; + beta := beta div 2 + end; + for k := 0 to nw - 1 do + begin + readtfmword; + inwidth[k] := (((b3 * z) div 256 + b2 * z) div 256 + b1 * z) div beta; + if b0 > 0 then + if b0 < 255 then + goto 9997 + else + inwidth[k] := inwidth[k] - alpha; + end; + if inwidth[0] <> 0 then + goto 9997; + with font[nf] do + begin + for k := 0 to (ec - bc) do + if widths[k] = 0 then + begin + widths[k + bc] := TWO31; +{ pixelwidths[k + bc] := 0;} + end + else + begin + widths[k + bc] := inwidth[widths[k]]; +{ pixelwidths[k + bc] := round(conv * widths[k]);} + end; + end; (* with *) + inTFM := true; + goto 9999; +9997: + complain (ERRREALBAD); + writestrng(tfmname,true); + writeln(logfile,'---not loaded, TFM file is bad'); + +9998: + inTFM := false; +9999: + + end; + + + +{-----------------------------------------------------} +procedure Fastdefinefont (fn: integer); +var p, k: integer; + n, waste: integer; + c, q, d: integer; + +begin { Fastdefinefont } + c := Dsign4byte; + q := Dsign4byte; + d := Dsign4byte; + p := Dget1byte; + n := Dget1byte; + for k := 1 to (p + n) do + waste := Dget1byte; +end; { Fastdefinefont } + + +{-----------------------------------------------------} + procedure definefont (e: integer); + var + f: 0..MAXFONTS; + p, k: integer; + n: integer; + c, q, d: integer; + r: integer; + begin + if (nf = MAXFONTS) then + begin + complain (ERRREALBAD); + writeln(logfile,'TeXtyl capacity exceeded (max fonts=', MAXFONTS: 1, ')!'); + writeln('TeXtyl capacity exceeded (max fonts=', MAXFONTS: 1, ')!'); + jumpout + end; + font[nf].num := e; + f := 0; + while font[f].num <> e do (* find first occurrence *) + f := f + 1; + c := Dsign4byte; + font[nf].checksum := c; + q := Dsign4byte; + font[nf].scaledsize := q; + d := Dsign4byte; + font[nf].designsize := d; + p := Dget1byte; + n := Dget1byte; + font[nf].name.len := p + n; + for k := 1 to (p + n) do + font[nf].name.str[k] := Dget1byte; + + if (f = nf) then + begin (* f = nf *) + for k := 1 to AREALENGTH do + tfmname.str[k] := ' '; + + r := 0; + + for k := 1 to font[nf].name.len do + begin + r := r + 1; + tfmname.str[r] := xchr[font[nf].name.str[k]] + end; + tfmname.str[r + 1] := '.'; + tfmname.str[r + 2] := 't'; + tfmname.str[r + 3] := 'f'; + tfmname.str[r + 4] := 'm'; + + tfmname.str[r + 5] := chr(32); + + tfmname.len := r + 4; + + if (not opentfmfile) then + begin + complain (ERRREALBAD); + writestrng(tfmname,true); + writeln(logfile,'---not loaded, TFM file can''t be opened!'); + writestrng(tfmname, false); + writeln(' cannot be opened. Aborting.'); + jumpout; + end + else + begin + if (q <= 0) or (q >= TWO27) then + begin + complain (ERRREALBAD); + writestrng(tfmname,true); + writeln(logfile,'---not loaded, bad scale (', q: 1, ')!'); + end + else if (d <= 0) or (d >= TWO27) then + begin + complain (ERRREALBAD); + writestrng(tfmname,true); + writeln(logfile,'---not loaded, bad design size (', d: 1, ')!'); + end + else + if inTFM(q) then + begin (* intfm *) + font[nf].space := q div 6; + if (c <> 0) and (tfmchecksum <> 0) and (c <> tfmchecksum) then + begin + writeln(logfile,'Problem in fig#',pgfigurenum:0,' on page ',currpagenum:0); + writestrng(tfmname,true); + writeln(logfile,'---beware: check sums do not agree!'); + writeln(logfile,' (', c: 1, ' vs. ', tfmchecksum: 1, ')'); + end; + d := round(100.0 * conv * q / (trueconv * d)); + nf := nf + 1; + font[nf].space := 0; + end (* intfm *) + end; + end; + end; + +{-----------------------------------------------------} + function firstpar (o: OctByt): integer; + var fpar : integer; + begin + case (o) of + 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, + 126, 127: + fpar := o - 0; + 128, 133, 235, 239, 243: + fpar := Dget1byte; + 129, 134, 236, 240, 244: + fpar := Dget2byte; + 130, 135, 237, 241, 245: + fpar := Dget3byte; + 143, 148, 153, 157, 162, 167: + fpar := Dsign1byte; + 144, 149, 154, 158, 163, 168: + fpar := Dsign2byte; + 145, 150, 155, 159, 164, 169: + fpar := Dsign3byte; + 131, 132, 136, 137, 146, 151, 156, + 160, 165, 170, 238, 242, 246: + fpar := Dsign4byte; + 138, 139, 140, 141, 142, 247, 248, + 249, 250, 251, 252, 253, 254, 255: + fpar := 0; + 147: + fpar := w; + 152: + fpar := x; + 161: + fpar := y; + 166: + fpar := z; + 171, 172, 173, 174, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, + 234: + fpar := o - 171 + end; + firstpar := fpar; + end; + +{-----------------------------------------------------} + function specialcases (o: OctByt; p: integer): boolean; + label + 46, 44, 30, 9998; + var + pure: boolean; + + begin + pure := true; + if ((o < 157) or (o > 249)) then + begin + complain (ERRREALBAD); + writeln(logfile, 'undefined command ', o: 1, '!'); + goto 30; + end; + case (o) of + 157, 158, 159, 160: + begin + goto 44; + end; + 161, 162, 163, 164, 165: + begin + y := p; + goto 44; + end; + 166, 167, 168, 169, 170: + begin + z := p; + goto 44; + end; + 171, 172, 173, 174, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, + 234: + begin + goto 46; + end; + 235, 236, 237, 238: + begin + goto 46; + end; + 243, 244, 245, 246: + begin + definefont(p); + goto 30; + end; + + 239, 240, 241, 242: + begin (* =========specials============= *) + mainhandlespecials (o, p); + goto 30; + end; + 247: + begin + complain (ERRREALBAD); + writeln(logfile,'preamble command within a page!'); + goto 9998; + end; + 248, 249: + begin + complain (ERRREALBAD); + writeln(logfile,'postamble command within a page!'); + goto 9998; + end; + (* others: + begin + write(' ', 'undefined command ', o: 1, '!'); + goto 30; + end + *) + end; +44: (* label *) + if (v > 0) and (p > 0) then + if (v > TWO31 - p) then + begin + p := TWO31 - v + end; + if (v < 0) and (p < 0) then + if ((-v) > (p + TWO31)) then + begin + p := -v - TWO31 + end; + + v := v + p; + + goto 30; +46: (* label *) + font[nf].num := p; + curfont := 0; + while font[curfont].num <> p do + curfont := curfont + 1; + goto 30 ; +9998: + pure := false; +30: + specialcases := pure; + end; + + +{-----------------------------------------------------} + function dopage : boolean; + label + 41, 42, 43, 30, 9998, 9999; + var + o: OctByt; + p, q: integer; + + begin + curfont := nf; + s := 0; + h := 0; + v := 0; + w := 0; + x := 0; + y := 0; + z := 0; + + ourxpos := 0; + ourypos := 0; + ourfontnum := (-1); + while true do + begin + o := Dget1byte; + p := firstpar(o); + if eof(dvifile) then begin + writeln(logfile, 'Bad DVI file: ', 'the file ended prematurely', '!'); + writeln('Bad DVI file: ', 'the file ended prematurely', '!'); + jumpout + end; + if o <= 131 then + begin + goto 41; + end + else + begin + if (o > 156) then + begin + if specialcases(o, p) then + goto 30 + else + goto 9998; + end; + + case (o) of + 133, 134, 135, 136: + begin + goto 41; + end; + 132, 137: + begin + goto 42 + end; + 138: + begin + goto 30; + end; + 139: + begin (* BOP *) + complain (ERRREALBAD); + writeln(logfile, 'bop occurred before eop'); + goto 9998; (* Fail *) + end; + 140: + begin (* EOP *) + if (s <> 0) then + begin + complain (ERRREALBAD); + writeln(logfile, 'stack not empty at end of page (level ', s: 1, ')!'); + end; + if (multifigure <> 0) then + begin + complain (ERRBAD); + writeln(logfile,'Some figure definition not closed at end of page ', currpagenum:0,'!'); + end; + + write (currpagenum:0,']'); + write (logfile,currpagenum:0,']'); + if ((currpagenum mod 10) = 0) then + writeln; + dopage := true; + goto 9999; + end; + 141: + begin (* PUSH *) + with stack[s] do + begin + sh := h; + sv := v; + sw := w; + sx := x; + sy := y; + sz := z; + end; (* with *) + s := s + 1; + goto 30; + end; + 142: + begin (* POP *) + if s = 0 then + begin + complain (ERRREALBAD); + writeln(logfile,'illegal pop at level zero!'); + end + else + begin + s := s - 1; + with stack[s] do + begin + h := sh; + v := sv; + w := sw; + x := sx; + y := sy; + z := sz; + end; + end; + goto 30; + end; + 143, 144, 145, 146: + begin + q := p; + goto 43 + end; + 147, 148, 149, 150, 151: + begin + w := p; + q := p; + goto 43 + end; + 152, 153, 154, 155, 156: + begin + x := p; + q := p; + goto 43 + end; + (* others: + if specialcases(o, p) then + goto 30 + else + goto 9998; + *) + end; (* case *) + end; (* else *) +41: (* finish cmd to set/put a char *) + if p < 0 then + p := 255 - (-1 - p) mod 256 + else if p >= 256 then + p := p mod 256; + if (p < font[curfont].bc) or (p > font[curfont].ec) then + q := TWO31 + else + q := font[curfont].widths[p]; + if (q = TWO31) then + begin + complain (ERRREALBAD); + writeln(logfile,'Character ', p:1,' invalid in font #',curfont:0); + end; + if o >= 133 then + goto 30; + if q = TWO31 then + q := 0; + goto 43; + +42: (* finish cmd to set/put rule *) + q := Dsign4byte; + if o = 137 then + goto 30; + goto 43 ; + +43: (*finish cmd that sets h += q *) + if (h > 0) and (q > 0) then + if (h > (TWO31 - q)) then + begin + q := TWO31 - h + end; + if (h < 0) and (q < 0) then + if ((-h) > (q + TWO31)) then + begin + q := (-h) - TWO31 + end; + + h := h + q; +30: + end; +9998: + dopage := false; +9999: + + end; + +{-----------------------------------------------------} + procedure skippages; + label + 9999; + var + p: integer; + k: 0..255; + downthedrain: integer; + begin + while true do + begin + if eof(dvifile) then + begin + writeln(logfile, 'Bad DVI file: ', 'the file ended prematurely', '!'); + write(' ', 'Bad DVI file: ', 'the file ended prematurely', '!'); + jumpout + end; + k := Dget1byte; + p := firstpar(k); + case (k) of + 139: + begin (* BOP *) + newbackptr := DVIMark + TotBytesWritten - 1; + currpagenum := Dsign4byte; (* count[0] *) + for k := 1 to 9 do + waste := Dsign4byte; (* WAS count[k] := *) + downthedrain := Dsign4byte; + BackupInBuf (4); + cmdSigned (oldbackptr, 4); + oldbackptr := newbackptr; + write(' ['); + write(logfile,' ['); + goto 9999; + end; + 132, 137: (* RULE *) + downthedrain := Dsign4byte; + 243, 244, 245, 246: + begin + definefont(p); + end; + 239, 240, 241, 242: (* specials *) + begin + mainhandlespecials (k, p); + end; + 248: + begin (* POST *) + ourq := DVIMark + TotBytesWritten - 1; + inpostamble := true; + goto 9999 + end; + (* others: + null + *) + end + end; + 9999: + + end; + +{-----------------------------------------------------} + procedure readpostamble; + var + k: integer; + p, q, m: integer; + indx : integer; + begin + if (Dsign4byte <> numerator) then + writeln(logfile,'Postamble',' numerator',' doesn''t match the preamble!'); + if (Dsign4byte <> denominator) then + writeln(logfile,'Postamble',' denominator',' doesn''t match the preamble!'); + if (Dsign4byte <> mag) then + begin + writeln(logfile,'Postamble',' magnification',' doesn''t match the preamble!'); + end; + maxv := Dsign4byte; + maxh := Dsign4byte; + maxs := Dget2byte; + BackupInBuf (2); + cmd2byte (maxs + 2); (* pretend the stack depth + * does not increase by + * more than two + *) + + totalpages := Dget2byte; + repeat + k := Dget1byte; + if (k >= 243) and (k < 247) then + begin + p := firstpar(k); + Fastdefinefont(p); + k := 138; + end + until k <> 138; (* NOP *) + + (* here, backup 1, enter all our fonts and + then output the 249 that we backed over *) + BackupInBuf (1); + for indx := 1 to MFontsDefd do + begin + with MFontTable[indx]^ do + enterfont (DVIFontNum, Cksum, DesSize, + DesSize, FontName ); + end; (* for *) + for indx := 1 to VFontsDefd do + begin + with VFontTable[indx]^ do + enterfont (DVIFontNum, Cksum, DesSize, + DesSize, FontName); + end; (* for *) + for indx := 1 to LFontsDefd do + begin + with LFontTable[indx]^ do + enterfont (DVIFontNum, Cksum, DesSize, + DesSize, FontName); + end; + cmd1byte(249); (* post post *) + + if (k <> 249) then + writeln(logfile,'byte ',k:0,' is not postpost!'); + q := Dsign4byte; + BackupInBuf (4); + cmd4byte (ourq); + m := Dget1byte; + if (m <> 2) then + writeln(logfile,'identification should be ', 2: 1, '!'); + m := 223; + while (m = 223) and not eof(dvifile) do + m := Dget1byte; + if not eof(dvifile) then + begin + writeln(' ', 'Bad DVI file: ', 'signature in should be 223', '!'); + writeln(logfile, 'Bad DVI file: ', 'signature in should be 223', '!'); + jumpout + end; + end; + + +(* MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN *) +begin (* main *) + initialize; + AskandOpenFiles; (* ask for filenames of inputdvi and outputfil *) + + writeln(logfile, TylVersion,' for Berkeley Unix'); + + write(logfile,'Reading File: '); + writestrng(dvifname,true); + writeln(logfile); + + + p := Dget1byte; + if (p <> 247) then + begin + write(' ', 'Bad DVI file: ', 'First byte isn''t start of preamble!', '!'); + writeln(logfile,'Bad DVI file: ', 'First byte isn''t start of preamble!', '!'); + jumpout + end; + p := Dget1byte; + if (p <> 2) then + writeln(logfile,'identification in byte 1 should be ', 2: 1, '!'); + numerator := Dsign4byte; + denominator := Dsign4byte; + if (numerator <= 0) then + begin + write(' ', 'Bad DVI file: ', 'numerator is ', numerator: 1, '!'); + writeln(logfile, 'Bad DVI file: ', 'numerator is ', numerator: 1, '!'); + jumpout + end; + if (denominator <= 0) then + begin + write(' ', 'Bad DVI file: ', 'denominator is ', denominator: 1, '!'); + writeln(logfile, 'Bad DVI file: ', 'denominator is ', denominator: 1, '!'); + jumpout + end; + conv := numerator / 254000.0 * (resolution / denominator); + mag := Dsign4byte; + if (mag <= 0) then + begin + write(' ', 'Bad DVI file: ', 'magnification is ', mag: 1, '!'); + writeln(logfile, 'Bad DVI file: ', 'magnification is ', mag: 1, '!'); + jumpout + end; + magfactor := mag / 1000.0; + trueconv := conv; + conv := trueconv * magfactor; + p := Dget1byte; (* the 'k' of the preamble *) + while p > 0 do + begin + p := p - 1; + waste := Dget1byte; + end; + + skippages; + if not inpostamble then + begin + while (maxpages > 0) do + begin (* while *) + maxpages := maxpages - 1; + if (not dopage) then + begin + write(' ', 'Bad DVI file: ', 'page ended unexpectedly', '!'); + writeln(logfile, 'Bad DVI file: ', 'page ended unexpectedly', '!'); + jumpout + end; + (* now we are at an EOP ---end of page *) + (* flushout GDVIbuffer, and reset counters *) +{ writeln('EOP: bytes used= ',GDVIBuf.TotByteLen:0); } + WriteDVIBuf; + ClearDVIBuf; + multifigure := 0; + pgfigurenum := 0; + FTBDs := 0; + didnewfonts := false; + repeat + k := Dget1byte; + if (k >= 243) and (k < 247) then + begin (* fontdefs *) + p := firstpar(k); + definefont(p); + k := 138 + end; + until (k <> 138); (* nop *) + + if (k = 248) then + begin + inpostamble := true; + ourq := DVIMark + TotBytesWritten - 1; + goto 30 + end; + + if (k = 139) then (* BOP *) + begin + newbackptr := DVIMark + TotBytesWritten - 1; + currpagenum := Dsign4byte; (* Count[0] *) + for k := 1 to 9 do + waste := Dsign4byte; (* WAS count[k] := *) + waste := Dsign4byte; (* backpointer *) + BackupInBuf (4); + cmdSigned (oldbackptr, 4); + oldbackptr := newbackptr; + write(' ['); + write(logfile,' ['); + end + else + begin (* NOT bop?? *) + writeln('We did not find BOP when expected'); + writeln(logfile,'We did not find BOP when expected'); + jumpout; + end; + + end; (* while *) +30: + end; (* if not inpostamble *) + if (not inpostamble) then + skippages; + waste := Dsign4byte; (* ptr to the last bop in file *) + BackupInBuf (4); + cmdSigned (oldbackptr, 4); + readpostamble; + WriteDVIBuf; + + while ((TotBytesWritten mod 4) <> 0) do + OutputByte(223); (* final signatures *) + + writeln; + writeln(logfile); + write ('Output written on '); + writestrng(outname, false); + write(' (',currpagenum:0,' page'); + if (currpagenum > 1) then + write('s'); + writeln(', ',TotBytesWritten:0,' bytes).'); + + write (logfile,'Output written on '); + writestrng(outname, true); + write(logfile,' (',currpagenum:0,' page'); + if (currpagenum > 1) then + write(logfile,'s'); + writeln(logfile,', ',TotBytesWritten:0,' bytes).'); + + write ('Log written on '); + writestrng(logfilnam, false); writeln; + write (logfile,'Log written on '); + writestrng(logfilnam, true); writeln (logfile); + writeln; + writeln(logfile); +666: + if (ErrorOccurred) then + begin + writeln; + writeln('Some error(s) occurred. Please check Logfile for details'); + writeln('Assume that the outputfile is incorrect'); + end; +end. + diff --git a/macros/latex209/contrib/textyl/psrc/textyl.pas.aa b/macros/latex209/contrib/textyl/psrc/textyl.pas.aa new file mode 100644 index 0000000000..2001f83217 --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/textyl.pas.aa @@ -0,0 +1,1000 @@ + +(*$b0*) + +program tyldvidvi(input,output); +(* ---------------------------------------------------------- + TeXtyl line-drawing interface for TeX. + copyright (c) 1987 John S. Renner + All rights reserved. + +ABSTRACT: TeXtyl reads in a DVI file, and processes 'specials' + that refer to graphics capabilities that it knows about, + like line, spline, ThickThinSpline, and musical + beams and slurs. TeXtyl then outputs a new DVI file, + with the special-macros expanded and converted to + DVI-commands for character setting. + +DEPENDENCIES: Few assumptions about Pascal are assumed. All + identifiers are unique to eight characters. There are + notes to indicate system-dependencies. + I assume the standard definition of "READ(fil, x)" to be + equivalent to "x := fil^; GET(fil)" , and + "WRITE(fil, x)" == "fil^ := x; PUT(fil)" . + Arrays are passed by reference (VAR) for efficiency. + See also the "sysdependent" procedure; + Problem areas, or areas for expansion are marked with ### + +-------------------------------------------------------------*) +(* Revision History: + Jun. 1986 v1.0 Basic version of TeXtyl + Dec. 1986 v1.1 Added adaptive subdivision for spline + interpolation. Added Cardinal basis. + Mar. 1987 v1.2 Added F and W flags for beginfigure + to allow required and/or actual dimensions + to interface with files output by the + DP drawing program from Carnegie-Mellon + also various fixes + Apr. 1987 v1.3 Added linestyles (dotted, dashed, dotdashed) + +*) + +label + 666, 30; +(*=====================CONST============================*) +#include "tylext.h" +#include "texpaths.h" + +const + TylVersion = 'This is TeXtyl, Version 1.30'; + (* for dvi-commands *) + PUT1 = 133; + SET1 = 128; + PUTRULE = 137; + NOP = 138; + PUSH = 141; + POP = 142; + RIGHTLEFT = 143; + DOWNUP = 157; + FONTDEF = 244; + USEFONT = 236; + OURFONTFLAG = 256; (* our special 'byte' value flag *) + + USESTDAREA = 0; (* flag to use the 'standard' area to find .tfm files *) + + (* some conversions and numbers *) + SPPERPT = 65536; (* scaled points per printers point *) + SPPERMM = 186468; (* scaled pts per millimetre *) + + RADTODEG = 57.29577952; (* degrees per radian *) + DEGTORAD = 0.0174532925; (* radians per degree *) + PI = 3.141592654; + + TWO16 = 65536; (* 2 ^ 16 *) + TWO20 = 1048576; (* 2 ^ 20 *) + TWO23 = 8388608; + TWO24 = 16777216; + TWO27 = 134217728; + TWO31 = 2147483647; (* 2^31 - 1 *) + + BIGREAL = 1.0e30; + MAXVECLENsp = 262144; (* Normal maximum length of longest + * vector-font character in scaled points + *) + (* Music Font dependent constants *) + DOTCHAR = 127; (* ascii number of char that is a dot *) + QNOTEGHUS = 18.0; (* MF: Global Horizontal Units for a Quarternote *) + QNOTEGVUS = 16.0; (* MF: Global Vertical units for a quarternote *) + GBMGHUS = 12.0; (* MF: horizontal units for a grace beam *) + GBMGVUS = 9.0; + + BMSTART = 0; BMEND = 69; (* indices for start/end of the beam chars *) + LOBM1 = 0; (* indices for the regular beam chars that *) + HIBM1 = 34; (* are 1 quarternote long, and *) + LOBM1p5 = 35; (* for those that are 1.5 quarternotes long *) + HIBM1p5 = 69; + + GBMSTART = 70; GBMEND = 105; (* indices for the grace beams *) + LOGBMp5 = 70; (* indices for grace beam chars that *) + HIGBMp5 = 87; (* are 0.5 grace quarternote long, and *) + LOGBMp66 = 88; (* 0.66 grace quarternotes long *) + HIGBMp66 = 105; + + LoVThick = 1; (* Bounds for Vector char thicknesses *) + HiVThick = 13; + + SizVFontTable = 39; (* size of the Vector Font Table *) { 3*HiVThick } + SizMFontTable = 18;(* size of the Music Font Table *) + MAXLABELFONTS = 5; + SizLFontTable = MAXLABELFONTS; (* size of the Label Font Table *) + + MAXCTLPTS = 63; (* max number of control points *) + MAXCTLPTSp3 = 66; (* max control points + 3 *) + ARRLIMIT = 100; (* limit for strings and other arrays *) + MAXSPLINESEGS = 480; (* max number of spline segments *) + MAXOLEN = 128; (* max length of Ostring that holds bytes of dvi cmds *) + MAXTBDs = 50; (* max number of Fonts-to-be-Defined *) + + MAXDVISTRINGS = 600; (* max number of DVI Ostrings per page *) + TFMSIZE = 8000; (* size of TFM array to hold .tfm file info *) + + (* Numeric names for the TeXtyl primitives *) + Aline = 1; (* should be first *) + Aspline = 2; + Attspline = 3; + Abeam = 4; + Atieslur = 5; + Aarc = 6; + Alabel = 7; + Afigure = 8; (* should be last one *) + + MAXFONTS = 60; (* number of TeX fonts to keep track of *) + STACKSIZE = 50; (* size of stack for pushes and pops *) + AREALENGTH = TYLPATHLEN; (* see also "sysdependent" proc for this value*) + + CR = 13; (* numbers of certain ascii characters *) + LF = 10; + HT = 9; + FF = 12; + ERRSIGNAL = '?'; + ERRNOTBAD = 0; + ERRBAD = 1; + ERRREALBAD = 2; + + + READACCESS = 4; + WRITEACCESS = 2; + NOPATH = 0; + FONTPATH = 3; + + + +(*===========================TYPES=============================*) +type + (* ---- Bytes ---- *) + + Inbyt = -128 .. 127; + + OctByt = 0 .. 256; (* DVI commands are 0..255, but we need + one more for an internal flag *) + bytefile = packed file of Inbyt; + + (* ---- Strings ---- *) + asciicode = 32 .. 126; + charstring = packed array [1 .. ARRLIMIT] of char; + ascstring = packed array [1 .. ARRLIMIT] of asciicode; + (* rep for character strings *) + strng = record + len: 0 .. ARRLIMIT; + str:charstring; + end; + (* rep for ascii strings *) + astrng = record + len: 0 .. ARRLIMIT; + str: ascstring; + end; + (* byte strings *) + pOstring = ^Ostring; + Ostring = packed array[1 .. MAXOLEN] of OctByt; + + (* ---- PUBLIC types ---- *) + VThickness = LoVThick .. HiVThick; + VectKind = (VKCirc, VKVert, VKHort); + BeamKind = (regular, grace); + SplineKind = (BSPL, INTBSPL, CATROM, CARD); + LineStyle = (solid, dotted, dashed, dotdash); + ScaledPts = integer; + MusIndex = integer; + VecIndex = integer; + + ThickAryType = array[0 .. MAXSPLINESEGS] of VThickness; + SplineSegments = array[1 .. MAXSPLINESEGS, 1 .. 2] of ScaledPts; + ControlPoints = array [0 .. MAXCTLPTSp3, 1 .. 2] of ScaledPts; + + + (* ----- Private Types ---- *) + FontInfRec = record + Cht, Cdp, Cwd : ScaledPts; + Angle : real; + end; + + pVectFontInfRec = ^VectFontInfRec; (* vector font info *) + VectFontInfRec = record + vkind : VectKind; + DesSize : ScaledPts; + PenSize : ScaledPts; + psize : VThickness; + MaxVectLen : ScaledPts; + FontName : strng; + Cksum : integer; + Isdefined : boolean; + DVIFontNum: integer; + FontInfo : array [0 .. 127] of FontInfRec; + end; + + pMusFontInfRec = ^MusFontInfRec; (* music font info *) + MusFontInfRec = record + DesSize : ScaledPts; + Family : integer; + FontName : strng; + Cksum : integer; + Isdefined : boolean; + DVIFontNum: integer; + Staffsize : integer; + ghu : ScaledPts; + gvu : ScaledPts; + FontInfo : array [0 .. 127] of FontInfRec; + end; + + pLabFontInfRec = ^LabFontInfRec; (* label fonts info *) + LabFontInfRec = record + DesSize : ScaledPts; + FontName : strng; + Cksum : integer; + Isdefined : boolean; + DVIFontNum : integer; + internalnumber : integer; + spacewidth : ScaledPts; + end; + + + (* list of dvi-strings *) + dvistary = array[1 .. MAXDVISTRINGS] of pOstring; + + DVIBuftype = record + TotByteLen : integer; + Numstrings : integer; + curstrindex : integer; + Dstrings : dvistary; + end; + + (* representation of list of fonts that have to be defined + * before we output the BOP of the page we + * just scanned + *) + ToBeDefinedRec = record + which : char; + indx : integer; + end; + + stackrec = record + sh, sv, sw, sx, sy, sz: integer; + end; + + Stacktype = array [0 .. STACKSIZE] of stackrec; + + Oneby4Vector = array[1 .. 4] of real; + Fourby4Matrix = array[1 .. 4, 1 .. 4] of real; + Oneby5Vector = array[1 .. 5] of real; + + Primitive = Aline .. Afigure; + + pItem = ^Item; + figptr = ^Figure; + + Item = packed record + nextitem : pItem; + BBlx, BBby, BBrx, BBty : ScaledPts; (* Bounding box *) + itemthick : VThickness; + itemvec : VectKind; + itempatt : LineStyle; + case kind : Primitive of + Aline : ( lx1, ly1, lx2, ly2 : ScaledPts; + ); + Aspline : ( spltype : SplineKind; + sclosed : boolean; + dosmarks : integer; + nsplknots : integer; + spts : ControlPoints; + ); + Attspline : ( tspltype : SplineKind; + tclosed : boolean; + dottmarks : integer; + nttknots : integer; + ttpts : ControlPoints; + ttarry : ThickAryType; + ); + Abeam : ( bx1, by1, bx2, by2 : ScaledPts; + staf : integer; + bkind : BeamKind; + ); + Atieslur : ( ntknots : integer; + minth, maxth : VThickness; + tspts : ControlPoints; + ); + Aarc : ( acentx, acenty : ScaledPts; + aradius : ScaledPts; + firstang, lastang : integer; + narcknots : integer; + arcpts : ControlPoints; + ); + Alabel : ( labx, laby : ScaledPts; + fontstyle : integer; + labeltext : strng; + ); + Afigure : ( figtheta : real; + fsx, fsy : real; + fdx, fdy : ScaledPts; + preWid, preHt : ScaledPts; + postWid, postHt : ScaledPts; + depthnumber : integer; + body : figptr; + ); + end; + + + Figure = record + things : pItem; + end; + + +(*==============================VARS============================*) +var + (* ----- Private vars *) + catrommtx : Fourby4Matrix; (* basis matrix for catmul-rom splines*) + bsplmtx : Fourby4Matrix; (* basis matrix for B-splines *) + cardmtx : Fourby4Matrix; (* Cardinal spline matrix *) + lastPoint : integer; (* num of output points *) + intervals : integer; (* count of spline interval we are on *) + ourxpos, (* internal x-position on page *) + ourypos, (* internal y-position on page *) + ourfontnum : integer; (* internal number of TeX font currently in use*) + ourpushdepth : integer; (* depth of internal pushes *) + origTexfont : integer; (* number of TeX font in use before tyling *) + + GDVIBuf : DVIBuftype; (* Global DVI buffer that contains a list of + * dvi commands for this page. All dvi-cmds + * parsed are put here and possibly modified + * before being written to the output file + *) + + VFontTable : array [1 .. SizVFontTable] of pVectFontInfRec; + MFontTable : array [1 .. SizMFontTable] of pMusFontInfRec; + LFontTable : array [1 .. SizLFontTable] of pLabFontInfRec; + (* the font tables, and the number of fonts defined in each *) + VFontsDefd, + MFontsDefd, + LFontsDefd : integer; + + GDVIFN : integer; (* dvi font number currently in use *) + + (* table of fonts yet To-Be-Defined *) + TBD : array[1 .. MAXTBDs] of ToBeDefinedRec; + FTBDs : integer; (* number of fonts to be defined for current page *) + + pageitems : pItem; (* list of primitives in current use in the current + * figure on the current page + *) + + TotBytesWritten : integer; + ourq : integer; (* the 'q' for the postpost *) + specstart: integer; (* the place in the DVI buffer where the + * start of the special begins. + * this is so that we know how far to back up + * and over-write the old \special macro string + * with the cmds of our 'macro-expansion' + *) + + multifigure : integer; (* depth of definition recursion of figures *) + didnewfonts : boolean; (* did we define the new fonts for this page? *) + prevfont : integer; (* to keep track of prev font before the + * PUSH and expansion of the special + *) + + pgfigurenum : integer; (* figure number for this page *) + currpagenum : integer; (* number of page we are on *) + skiptsclamp : boolean; (* DEBUG: should we skip post-clamping ties *) + dviBBlx, dviBBrx, (* Bounding box of figure in DVI space *) + dviBBby, dviBBty : ScaledPts; + ErrorOccurred : boolean; (* global flag in case some error happened *) + + + thefilename, realnameoffile : charstring; (* used externally *) + + (* ----- End private vars *) + + + tfmbyte : Inbyt; + + vaxbyt : Inbyt; + + tfm: array[-100 .. TFMSIZE] of OctByt; + + xord: array [char] of asciicode; + xchr: array [0 .. 255] of char; + outname: strng; (* name of output file *) + tfmname : strng; (* name of a .tfm file *) + dvifname : strng; (* name of the input dvi file *) + logfilnam: strng; (* name of the log file *) + + dvifile: bytefile; + tfmfile: bytefile; + outputfil: bytefile; + logfile : text; + + curfont: integer; + s : 0 .. STACKSIZE; + h, v, w, x, y, z: integer; + stack: Stacktype; + + font: array [0 .. MAXFONTS] of + record + num: integer; + name: astrng; + checksum: integer; + scaledsize: integer; + designsize: integer; + space: integer; + bc: integer; + ec: integer; + widths: array [0 .. 127] of ScaledPts + end; + nf : 0 .. MAXFONTS; + + MINREAL : real; (* a system-dependent 'constant' *) + b0, b1, b2, b3: OctByt; + inwidth: array [0 .. 255] of integer; + tfmchecksum: integer; + conv: real; + trueconv: real; + numerator, + denominator: integer; + defaultdirectory: strng; + mag, + magfactor: real; + maxv, maxh, maxs : integer; + maxpages, + totalpages : integer; + resolution: real; + inpostamble : boolean; + newbackptr, + oldbackptr : integer; + p, k : integer; + waste : integer; + + +(* ==================forward declarations============================ *) + +{ These hooks assume that the parameters are filled "correctly", + and are already transformed into 4th Quadrant DVI-space } + + +procedure TylTieSlur (var KnotArray: ControlPoints; + numknots: integer; + minthick, maxthick: VThickness); forward; + +procedure TylThickThinSpline (thetype : SplineKind; + isclosed : boolean; + var KnotArray: ControlPoints; + var ThikThinAry: ThickAryType; + numknots: integer; + vec: VectKind; + patt: LineStyle; + domarks : integer); forward; + +procedure TylSpline (thetype : SplineKind; + isclosed : boolean; + var KnotArray: ControlPoints; + numknots: integer; + thick: VThickness; + vec: VectKind; + patt: LineStyle; + domarks : integer); forward; + +procedure TylLine (xl, yb, xr, yt: ScaledPts; + thickness: VThickness; + vec: VectKind; + patt: LineStyle); forward; + +procedure TylBeam (fromx, fromy, tox, toy: ScaledPts; + staffsize : integer; + kind : BeamKind); forward; + +procedure TylArc (radius : ScaledPts; + centx, centy : ScaledPts; + firstangle, secondangle : integer; + thick : VThickness; + vec : VectKind; + patt: LineStyle); forward; + +procedure TylLabel (xpos, ypos : ScaledPts; + fontstyle : integer; + phrase : charstring; + phraselen : integer); forward; + +(* private procedures *) +procedure definebeams (var M : pMusFontInfRec); forward; +procedure definevectors (var Vec: pVectFontInfRec); forward; +procedure defineNewfonts; forward; +procedure doTylArc (iscircle : boolean; var apts : ControlPoints; + numknots : integer; thick : VThickness; + vec : VectKind; patt : LineStyle); forward; +procedure strcopy (src : charstring; var dest : charstring; + len : integer); forward; +procedure writestrng (s :strng; tologfile : boolean); forward; +(* end private procs *) + +{------------------------------------------------------} +procedure jumpout; +begin + goto 666; (* global label *) +end; + + +(*-------------- System Dependent stuff ----------------------*) +(* the default-directory should be where the .tfm files are + * to be found. the string len should reflect this name. + * Check with the local site maintainer about any necessary + * additions to the reset and rewrite procedures for opening + * 8-bit binary files. + *) + + + + + +procedure sysdependent; + begin + + + setpaths; + + defaultdirectory.str := TYLPATH; + defaultdirectory.len := TYLPATHLEN; (* AREALENGTH const should be this, too *) + writeln(TylVersion,' for Berkeley Unix'); + + resolution := 300.0; (* just a number *) + MINREAL := 1.0e-20; (* so that we avoid some underflows *) + end; + +{------------------------------------------------------------} +procedure complain (severity :integer); +begin + writeln(logfile,'Error in fig#',pgfigurenum:0,' on page ',currpagenum:0); + case severity of + ERRNOTBAD : begin + write (ERRSIGNAL); + end; + ERRBAD : begin + write (ERRSIGNAL); + ErrorOccurred := true; + end; + ERRREALBAD : begin + write (ERRSIGNAL,'! '); + ErrorOccurred := true; + end; + + end; (* case *) +end; + +function opendvifile : boolean; +begin + + strcopy (dvifname.str, thefilename, dvifname.len); + thefilename[dvifname.len + 1] := ' '; + if (testaccess (READACCESS, NOPATH)) then + begin + reset (dvifile, realnameoffile); + opendvifile := true; + end + else + begin + writestrng(dvifname, false); + writeln(' : DVI file not found/readable '); + opendvifile := false; + end; + +end; + +function opentfmfile : boolean; +begin + + strcopy (tfmname.str, thefilename, tfmname.len); + thefilename[tfmname.len + 1] := ' '; + if (testaccess (READACCESS, FONTPATH)) then + begin + reset(tfmfile, realnameoffile); + opentfmfile := true; + end + else + begin + writestrng(tfmname, false); + writeln(' : TFM file not fount/readable '); + opentfmfile := false; + end; + +end; + +procedure openoutputfile; +begin + + strcopy (outname.str, thefilename, outname.len); + thefilename[outname.len + 1] := ' '; + if (testaccess (WRITEACCESS, NOPATH)) then + rewrite (outputfil, realnameoffile) + else + begin + writestrng(outname, false); + writeln(' : Output file not writable'); + jumpout; + end; + +end; + +procedure openlogfile; +begin + + strcopy (logfilnam.str, thefilename, logfilnam.len); + thefilename[logfilnam.len + 1] := ' '; + if (testaccess (WRITEACCESS, NOPATH)) then + rewrite (logfile, realnameoffile) + else + begin + writestrng(logfilnam, false); + writeln(' : Log file not writable'); + jumpout; + end; + +end; + + +(* &&Module Tylsupport *) + + +{---------------------------------------------------} +procedure ClearBufString (var s : pOstring); +(* clear a DVI buffer string to contain no-ops*) +var i : integer; +begin + for i := 1 to MAXOLEN do + s^[i] := NOP; +end; + +{---------------------------------------------------} +function NewBufString : pOstring; +var s : pOstring; +begin + new (s); + ClearBufString (s); + NewBufString := s; +end; + + + +(* NOTATION:: + * All procedures that put a dvi-command into the + * temporary buffer are prefixed with "cmd"... + * Functions that deal with reading .tfm files are prefixed + * with "T" or have "tfm" in their names. + * Functions that deal with reading DVI files are + * prefixed with a "D". + *) + +{--------------------------------------------} +procedure cmd1byte (cmd : OctByt); +begin + with GDVIBuf do + begin + if (Numstrings > MAXDVISTRINGS) then (* buffer full *) + begin + complain (ERRREALBAD); + writeln (logfile,'error: too many dvistrings. Totbytes = ',TotByteLen); + jumpout; + end; + if (curstrindex > MAXOLEN) then (* current string full *) + begin + Numstrings := Numstrings + 1; + if (Dstrings[Numstrings] <> nil) then + dispose (Dstrings[Numstrings]); + Dstrings[Numstrings] := NewBufString; + ClearBufString(Dstrings[Numstrings]); + curstrindex := 1; + end; + Dstrings[Numstrings]^[curstrindex] := cmd; (* insert command byte *) + TotByteLen := TotByteLen + 1; + curstrindex := curstrindex + 1; + end; +end; + + +{---------------------------------------------------} +procedure cmd2byte (cmd : integer); +begin + cmd1byte (cmd div 256); + cmd1byte (cmd mod 256); +end; + +{---------------------------------------------------} +procedure cmd3byte (cmd : integer); +begin + cmd1byte (cmd div TWO16); + cmd1byte ((cmd div 256) mod 256); + cmd1byte (cmd mod 256); +end; + +{---------------------------------------------------} +procedure cmd4byte (cmd : integer); +var tmp : integer; +begin + tmp := cmd; + if (tmp >= 0) then + begin + cmd1byte (tmp div TWO24); + end + else + begin + tmp := tmp + TWO31 + 1; (* need the +1 *) + cmd1byte (tmp div TWO24 + 128); + end; + tmp := tmp mod TWO24; + cmd1byte (tmp div TWO16); + tmp := tmp mod TWO16; + cmd1byte (tmp div 256); + cmd1byte (tmp mod 256); +end; + +{---------------------------------------------------} +(* ### may be system dependent as integers are assumed + to be signed 32-bits *) + +procedure cmdSigned (i : integer; numbytes: integer); +var tmp : integer; +begin + if (numbytes = 4) then + cmd4byte (i) + else + begin (* <= 3 bytes *) + tmp := i; + if (numbytes = 3) then + begin + if (tmp < 0) then + tmp := tmp + TWO24; + cmd1byte (tmp div TWO16); + tmp := tmp mod TWO16; + cmd1byte (tmp div 256); + end; + if (numbytes = 2) then + begin + if (tmp < 0) then + tmp := tmp + TWO16; + cmd1byte (tmp div 256); + end; + if (numbytes = 1) then + begin + if (tmp < 0) then + tmp := tmp + 256; + end; + cmd1byte (tmp mod 256); (* for all *) + end; +end; + + + +{---------------------------------------------------} +function Tgetvaxbyte : OctByt; +label 9999; +begin + tfmbyte := tfmfile^; + if (tfmbyte < 0) then + Tgetvaxbyte := tfmbyte + 256 + else + Tgetvaxbyte := tfmbyte; + if (eof (tfmfile)) then + begin + complain (ERRREALBAD); + writeln (logfile,' early EOF of tfm file! '); + goto 9999; + end; + get (tfmfile); +9999: +end; + + +{---------------------------------------------------} +procedure readtfmword; + +begin + + b0 := Tgetvaxbyte; + b1 := Tgetvaxbyte; + b2 := Tgetvaxbyte; + b3 := Tgetvaxbyte; + +end; + + +{---------------------------------------------------} +function DVaxByte : OctByt; +label 99; +begin + vaxbyt := dvifile^; + if (eof (dvifile)) then + begin + DVaxByte := 0; + goto 99; + end; + if (vaxbyt < 0) then + DVaxByte := vaxbyt + 256 + else + DVaxByte := vaxbyt; + get (dvifile); +99: +end; + + + +{---------------------------------------------------} +(* get a byte from the DVI file, but do not copy it into the DVIbuffer *) +function Dgrabbyte : integer; +var + b: OctByt; +begin + if eof(dvifile) then + Dgrabbyte := 0 + else + begin + + b := DVaxByte; + + Dgrabbyte := b; + end; +end; + + +{---------------------------------------------------} +function Dget1byte : integer; +var + b: OctByt; +begin + if eof(dvifile) then + Dget1byte := 0 + else + begin + + b := DVaxByte; + + Dget1byte := b + end; + cmd1byte(b); +end; + +{---------------------------------------------------} +function Dsign1byte : integer; +var + b: OctByt; +begin + + b := DVaxByte; + + if b < 128 then + Dsign1byte := b + else + Dsign1byte := b - 256; + cmd1byte(b); +end; + +{---------------------------------------------------} +function Dget2byte : integer; +var + a, b: OctByt; +begin + + a := DVaxByte; + b := DVaxByte; + + Dget2byte := a * 256 + b; + cmd1byte(a); + cmd1byte(b); +end; + +{---------------------------------------------------} +function Dsign2byte : integer; +var + a, b: OctByt; +begin + + a := DVaxByte; + b := DVaxByte; + + if a < 128 then + Dsign2byte := a * 256 + b + else + Dsign2byte := (a - 256) * 256 + b; + cmd1byte(a); + cmd1byte(b); +end; + +{---------------------------------------------------} +function Dget3byte : integer; +var + a, b, c: OctByt; +begin + + a := DVaxByte; + b := DVaxByte; + c := DVaxByte; + + Dget3byte := (a * 256 + b) * 256 + c; + cmd1byte(a); + cmd1byte(b); + cmd1byte(c); +end; + +{---------------------------------------------------} +function Dsign3byte : integer; +var + a, b, c: OctByt; +begin + + a := DVaxByte; + b := DVaxByte; + c := DVaxByte; + + if a < 128 then + Dsign3byte := (a * 256 + b) * 256 + c + else + Dsign3byte := ((a - 256) * 256 + b) * 256 + c; + cmd1byte(a); + cmd1byte(b); + cmd1byte(c); +end; + +{---------------------------------------------------} +function Dsign4byte : integer; +var + a, b, c, d: OctByt; +begin + + a := DVaxByte; + b := DVaxByte; + c := DVaxByte; + d := DVaxByte; + + if a < 128 then + Dsign4byte := ((a * 256 + b) * 256 + c) * 256 + d + else + Dsign4byte := (((a - 256) * 256 + b) * 256 + c) * 256 + d; + cmd1byte(a); + cmd1byte(b); + cmd1byte(c); + cmd1byte(d); +end; + + +{---------------------------------------------------} +(* write a byte out to the ouput file, but if we + * encounter the font flag, define the new fonts, and + * continue + *) +procedure OutputByte (b : OctByt); +var x : Inbyt; + n : integer; +begin + n := b; + if (n = OURFONTFLAG) then + begin (* our special macro-flag *) + n := NOP; (* nullify it *) + if (not didnewfonts) then + begin + didnewfonts := true; + defineNewfonts; (* expand the defns in the outfile itself *) + end; + end; (* if *) + + if (n > 127) then + begin + x := n - 256; + end + else + x := n; + outputfil^ := x; + put (outputfil); + + TotBytesWritten := TotBytesWritten + 1; (* keep count of all bytes *) +end; + +{---------------------------------------------------} +procedure Output2Byte (i : integer); +begin + OutputByte (i div 256); + OutputByte (i mod 256); +end; diff --git a/macros/latex209/contrib/textyl/psrc/textyl.pas.ab b/macros/latex209/contrib/textyl/psrc/textyl.pas.ab new file mode 100644 index 0000000000..8240ef5a81 --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/textyl.pas.ab @@ -0,0 +1,1000 @@ + +{---------------------------------------------------} +procedure Output4Byte (i : integer); +var tmp : integer; +begin + tmp := i; + if (tmp >= 0) then + begin + OutputByte (tmp div TWO24); + end + else + begin + tmp := tmp + TWO31 + 1; (* need the +1 *) + OutputByte (tmp div TWO24 + 128); + end; + tmp := tmp mod TWO24; + OutputByte (tmp div TWO16); + tmp := tmp mod TWO16; + OutputByte (tmp div 256); + OutputByte (tmp mod 256); +end; + + +{---------------------------------------------------} + +function rtan (ang : real) : real; +var rads : real; + cosrads : real; +begin + rads := ang * DEGTORAD; + cosrads := cos (rads); + if (cosrads = 0.0) then { this happens at 90 and 270 } + cosrads := cos ((ang - 0.01) * DEGTORAD); + rtan := (sin (rads)) / (cosrads); +end; + +{---------------------------------------------------} +function float (i : integer) : real; +begin + float := i + 0.00; +end; + + +{---------------------------------------------------} +function tolowercase (let: char) : char; +const Diff = 32; (* xord['a'] - xord['A'] *) +var olet : integer; +begin + olet := xord[let]; + if (olet >= xord['A']) then + begin + if (olet <= xord['Z']) then + begin + let := xchr[olet + Diff]; + end; + end; + tolowercase := let; +end; + +{---------------------------------------------------} +(* decide if the first string is the same as the second -- + * at least the first 'len' characters + * We need this since most Pascal impls. are brain-dead + * when it comes to string comparisons + *) +function streq (a, b : charstring; len : integer) : boolean; +label 1; +var i : integer; + same : boolean; +begin + same := true; + for i := 1 to len do + begin + if (a[i] <> b[i]) then + begin + same := false; + goto 1; + end; (* if *) + end; (* for *) +1: + streq := same; +end; (* streq *) + +{-------------------------------------------------------} +procedure strcopy (* src : charstring; var dest : charstring; len : integer *); +var i : integer; + begin + for i := 1 to len do + dest[i] := src[i]; + end; + +{-------------------------------------------------------} +procedure writestrng (* s :strng; tologfile : boolean *); +var i : integer; +begin +if (tologfile) then + begin + for i := 1 to s.len do + write (logfile, s.str[i]); + end +else + begin + for i := 1 to s.len do + write (s.str[i]); + end; +end; + + +{---------------------------------------------------} +(* Move the current DVI position to posx, posy by + * moving relatively from our current position + * and store the new position + *) + +procedure isetpos (posx, posy : integer); +var dy, dx: ScaledPts; + numbytes : integer; +begin + dx := posx - ourxpos; + dy := posy - ourypos; + + numbytes := 1; + if ((dx < 128) and (dx >= -128)) then + numbytes := 1 + else if ((dx < 32768) and (dx >= -32768)) then + numbytes := 2 + else if ((dx < TWO23) and (dx >= - TWO23))then + numbytes := 3 + else if ((dx < TWO31) and (dx >= - TWO31))then + numbytes := 4 + else + begin + complain (ERRREALBAD); + writeln('Panic: dx is too big/small in isetpos: ',dx); + writeln(logfile,'Panic: dx is too big/small in isetpos: ',dx); + end; + + cmd1byte (RIGHTLEFT + numbytes -1); (* number of bytes in its arg list *) + cmdSigned (dx, numbytes); + + numbytes := 1; + if ((dy < 128) and (dy >= -128)) then + numbytes := 1 + else if ((dy < 32768) and (dy >= -32768)) then + numbytes := 2 + else if ((dy < TWO23) and (dy >= - TWO23))then + numbytes := 3 + else if ((dy < TWO31) and (dy >= - TWO31))then + numbytes := 4 + else + begin + complain (ERRREALBAD); + writeln('Panic: dy is too big/small in isetpos: ',dy); + writeln(logfile,'Panic: dy is too big/small in isetpos: ',dy); + end; + + cmd1byte (DOWNUP + numbytes -1); + + cmdSigned (dy, numbytes); + + ourxpos := posx; + ourypos := posy; +end; + +{---------------------------------------------------} +(* put out a character *) +procedure iputchar (charno : OctByt); +begin + cmd1byte (PUT1); + cmd1byte (charno); +end; + + +{---------------------------------------------------} +(* set the font number, but only if it is different than + * the last one we accessed. + *) +procedure isetfont (DVINum : integer); +begin + if (ourfontnum <> DVINum) then + begin + cmd1byte (USEFONT); + cmd2byte (DVINum); + ourfontnum := DVINum; + end; +end; + + +procedure IPUSH; +begin + if (ourpushdepth = 0) then + begin (* first push --> start tyling *) + origTexfont := font[curfont].num; + end + else + begin + prevfont := ourfontnum; (* store the internal font number in use at this time *) + end; + cmd1byte (NOP); + cmd1byte (NOP); (* our greeting *) + cmd1byte (PUSH); + ourpushdepth := ourpushdepth + 1; +end; + +procedure IPOP; +begin + cmd1byte (POP); + cmd1byte(NOP); + cmd1byte(NOP); (* our signature *) + ourpushdepth := ourpushdepth - 1; + if (ourpushdepth < 0) then + begin + complain (ERRREALBAD); + writeln(logfile,'Error: too many internal pops'); + end; + if (ourpushdepth = 0) then + begin (* we are totally done with tyling for now *) + if (nf > 0) then + isetfont (origTexfont); (* only if it is valid *) + end + else + begin + if (prevfont >= 0) then + isetfont(prevfont); (* restore that internal font previously in use *) + end; +end; + +{---------------------------------------------------} +(* Assumes that the correct font is currently set *) +procedure Tyldot (dotx, doty : ScaledPts); +begin + if (dotx <> 0) and (doty <> 0) then + isetpos (dotx, doty); + iputchar (DOTCHAR); +end; + +{---------------------------------------------------} +procedure InitDVIBuf; +var i: integer; +begin + with GDVIBuf do + begin + TotByteLen := 0; + Numstrings := 0; + for i := 1 to MAXDVISTRINGS do + Dstrings[i] := nil; + curstrindex := MAXOLEN + 1; + end; +end; + +{---------------------------------------------------} +procedure ClearDVIBuf; +var i : integer; +begin + with GDVIBuf do + begin + for i := 1 to Numstrings do + begin + dispose (Dstrings[i]); + Dstrings[i] := nil; + end; + TotByteLen := 0; + Numstrings := 0; + curstrindex := MAXOLEN + 1; + end; +end; + +{---------------------------------------------------} +procedure WriteDVIBuf; +var i: integer; + curstr: integer; + b : OctByt; +begin + curstr := 1; + with GDVIBuf do + begin + while (curstr < Numstrings) do + begin + for i := 1 to MAXOLEN do + begin + b := Dstrings[curstr]^[i]; + OutputByte (b); + end; + curstr := curstr + 1; + end; (* while *) + +(* now do the last string *) + for i := 1 to (curstrindex - 1) do + begin + b := Dstrings[Numstrings]^[i]; + OutputByte(b); + end; (* for *) + end; (* with *) + ClearDVIBuf; +end; + +{---------------------------------------------------} +procedure BackupInBuf (nbytes : integer); +var nstrs, rem : integer; +begin + with GDVIBuf do + begin + nstrs := (TotByteLen - nbytes) div MAXOLEN; + rem := (TotByteLen - nbytes) mod MAXOLEN; + Numstrings := nstrs + 1; + curstrindex := rem + 1; (* points to position to-be-filled *) + if (curstrindex = 0) then + curstrindex := MAXOLEN; + TotByteLen := TotByteLen - nbytes; + end; +end; + +{-----------------------------------------------------} +function DVIMark : integer; +begin + DVIMark := GDVIBuf.TotByteLen; +end; + + + +{---------------------------------------------} +function NewItem (what : Primitive): pItem; +var i : pItem; + f : figptr; +begin + + new (i); + with i^ do + begin + nextitem := nil; + BBlx := 0; + BBby := 0; + BBrx := 0; + BBty := 0; + itemthick := LoVThick; + itemvec := VKCirc; + itempatt := solid; + kind := what; + case (what) of (* give defaults *) + Aline : ; + Aspline: begin + nsplknots := 0; + dosmarks := 0; + sclosed := false; + spltype := BSPL; + end; + Attspline: begin + nttknots := 0; + dottmarks := 0; + tspltype := BSPL; + tclosed := false; + end; + Abeam : ; + Atieslur: begin + ntknots := 0; + end; + Aarc: begin + narcknots := 0; + end; + Alabel: begin + fontstyle := -1; (* undefined *) + labeltext.len := 0; + end; + Afigure: begin + figtheta := 0.0; + fsx := 1.0; fsy := 1.0; + fdx := 0; fdy := 0; + preWid := 0; preHt := 0; + postWid := 0; postHt := 0; + depthnumber := 0; (* for now *) + new (f); (* a new figure *) + body := f; + body^.things := nil; + end; + end; (*case *) + end; (* with *) + NewItem := i; +end; (* NewItem *) + +{ ### Note: "pageitems" could be extended to be a list +{ of macrodefinitions which contain primitives , and +{ then could be instanced. E.g., a library of common +{ figures callable from \special level } + + +{------------------------------------------------------} +procedure pushItem (depth : integer; newthing : pItem); +label 101; +var i, p : pItem; + dun : boolean; +begin + if (pageitems = nil) then + begin + if (newthing^.kind = Afigure) then + begin + pageitems := newthing; + goto 101; + end + else + begin + pageitems := NewItem (Afigure); + pageitems^.depthnumber := depth; + end; + end; + + (* Assume that pageitems points to Afigure *) + + (* traverse the list *) + i := pageitems; (* point to front of list for now *) + p := i^.body^.things; + dun := false; + while ((p <> nil) and not dun) do + begin + if (depth = i^.depthnumber) then + begin (* simple push *) + dun := true; + (* Note: this is the case when pushing another figure item + onto an already-existing list. We push the newfigure + with a depth of (fig^.depthnumber - 1) because it + really is part of the higer-level figure + *) + end + else if (depth > i^.depthnumber) then + begin + (* there MUST be a figure with a higher number deeper *) + while ((p^.kind <> Afigure) and (p^.nextitem <> nil)) do + begin + p := p^.nextitem; + end; + + if (p^.kind = Afigure) then + begin + i := p; + p := i^.body^.things; + end + else + begin + complain (ERRREALBAD); + writeln(logfile,'OOPS p^.kind isnt a figure. It must be near endoflist'); + end; + end; + end; (* while *) + + (* we have the correct front of list-list, + and i points to Afigure item *) + newthing^.nextitem := p; + i^.body^.things := newthing; +101: +end; (* pushItem *) + + + +{---------------------------------------------} +function Tgetfixword (k: integer) : real; +var a : 0 .. 4096; + f : integer; +begin + a := (tfm[k] * 16) + (tfm[k + 1] div 16); + f := ((((tfm[k + 1] mod 16) * 256) + + tfm[k + 2]) * 256) + + tfm[k + 3]; + if (a > 2047) then + begin + a := 4096 - a; + if (f > 0) then + begin + f := TWO20 - f; + a := a - 1; + end; + end; + Tgetfixword := a + f / TWO20; +end; + +{-----------------------------------------------------} +function TgetSigned (k: integer): integer; +var i: integer; +begin + i := tfm[k]; + if (i < 128) then + i := i - 256; + TgetSigned := (((((i * 256) + tfm[k + 1]) * 256) + + tfm[k + 2]) * 256) + tfm[k + 3]; +end; + + + +{-----------------------------------------------------------} +(* open a .tfm file and return the parameters in it. + * Used only in conjuction with the vector and music fonts + *) +procedure gettfm (tfmfilnam: strng; + var dessize, p1, p2, p3, p4, p5, p6, p7 : ScaledPts; + var cksum : integer); +label 9999; +var tfmptr: integer; + lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np: integer; + charbase, widthbase, heightbase, depthbase, + italicbase, ligkernbase, kernbase, extenbase, + parambase : integer; + tempdesignsize : ScaledPts; +begin + p1 := 0; p2 := 0; p3 := 0; p4 := 0; + p5 := 0; p6 := 0; p7 := 0; + cksum := -1; + + strcopy(tfmfilnam.str, tfmname.str, tfmfilnam.len); + tfmname.len := tfmfilnam.len; + + tfmname.str[tfmname.len + 1] := chr(32); + + if (not opentfmfile) then + begin + complain (ERRREALBAD); + writestrng(tfmname,true); + writeln(logfile,'---not loaded, TFM file can''t be opened!'); + writestrng(tfmname,false); + writeln(' cannot be opened. Aborting'); + jumpout; + end; + + + tfm[0] := Tgetvaxbyte; + tfm[1] := Tgetvaxbyte; + + + lf := (tfm[0] * 256) + tfm[1]; + if ((4 * lf - 1) > TFMSIZE) then + begin + complain (ERRREALBAD); + write(logfile,'The tfm file:'); + writestrng(tfmfilnam, true); + writeln(logfile,' is bigger than I can handle!'); + goto 9999; + end; + + for tfmptr := 2 to (4 * lf) - 1 do + begin + + tfm[tfmptr] := Tgetvaxbyte; + + end; (* for *) + + tfmptr := 2; + lh := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + bc := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + ec := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + nw := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + nh := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + nd := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + ni := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + nl := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + nk := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + ne := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + np := (tfm[tfmptr] * 256) + tfm[tfmptr + 1]; + tfmptr := tfmptr + 2; + + if (lf <> (6 + lh + ((ec - bc) + 1) + nw + nh + + nd + ni + nl + nk + ne + np)) then + begin + complain (ERRREALBAD); + writestrng(tfmfilnam, true); + writeln(logfile,': subfile sizes don''t add up to the stated total!'); + writeln(logfile,'Sorry, but I can''t go on; are you sure this is a TFM?'); + goto 9999 + end; + if (bc > (ec + 1)) or (ec > 255) then + begin + complain (ERRREALBAD); + writeln(logfile,'The character code range ', bc: 1, '..', ec: 1, 'is illegal!'); + writeln(logfile,'Sorry, but I can''t go on; are you sure this is a TFM?'); + goto 9999; + end; + charbase := (6 + lh) - bc; + widthbase := (charbase + ec) + 1; + heightbase := widthbase + nw; + depthbase := heightbase + nh; + italicbase := depthbase + nd; + ligkernbase := italicbase + ni; + kernbase := ligkernbase + nl; + extenbase := kernbase + nk; + parambase := (extenbase + ne) - 1; + + dessize := round (Tgetfixword (28) * SPPERPT); (* now in ScaledPts *) + tempdesignsize := round (dessize * magfactor); + cksum := TgetSigned (24); + (* return the special 7 parameters for the font *) + p1 := round (Tgetfixword (4 * (parambase + 1)) * tempdesignsize); + p2 := round (Tgetfixword (4 * (parambase + 2)) * tempdesignsize); + p3 := round (Tgetfixword (4 * (parambase + 3)) * tempdesignsize); + p4 := round (Tgetfixword (4 * (parambase + 4)) * tempdesignsize); + p5 := round (Tgetfixword (4 * (parambase + 5)) * tempdesignsize); + p6 := round (Tgetfixword (4 * (parambase + 6)) * tempdesignsize); + p7 := round (Tgetfixword (4 * (parambase + 7)) * tempdesignsize); + +9999: +end; + + +{---------------------------------------------------} +procedure initVnMnLtables; +var i: integer; +begin + for i := 1 to SizVFontTable do + VFontTable[i] := nil; + for i := 1 to SizMFontTable do + MFontTable[i] := nil; + for i := 1 to SizLFontTable do + LFontTable[i] := nil; + VFontsDefd := 0; + MFontsDefd := 0; + LFontsDefd := 0; + GDVIFN := 300; (* starting number for any new fonts that we define *) +end; + + +{-------------------------------------------------------} +procedure fonttobedefined (kind : char; findex : integer); +begin + FTBDs := FTBDs + 1; +(* reset this to zero after outputting + 1. fontdefs + 2. bop + 3. contents of dvi page + 4. eop +*) + TBD[FTBDs].which := kind; + TBD[FTBDs].indx := findex; +end; + + +{-----------------------------------------------------} +procedure enterfont (fontnum : integer; ck : integer; + scalefact, dessiz : ScaledPts; + nam : strng); +var n: integer; + len : integer; +begin + cmd1byte(FONTDEF); + cmd2byte(fontnum); + cmd4byte(ck); + cmd4byte(scalefact); + cmd4byte(dessiz); + cmd1byte(USESTDAREA); + + len := nam.len; + + + cmd1byte(len - 4); (* skip the length of the .tfm suffix *) + + + for n := 1 to (nam.len - 4) do + + begin (* skip the .tfm suffix *) + cmd1byte (xord [ nam.str[n] ]); + end; +end; + + +{-----------------------------------------------------} +procedure Outputfont (fontnum : integer; ck : integer; + scalefact, dessiz : ScaledPts; + nam : strng); +var n: integer; + len : integer; +begin + OutputByte(FONTDEF); + Output2Byte(fontnum); + Output4Byte(ck); + Output4Byte(scalefact); + Output4Byte(dessiz); + OutputByte(USESTDAREA); + + len := nam.len; + + + OutputByte(len - 4); + + + for n := 1 to (nam.len - 4) do + + begin (* dont output the default dir prefix, nor the .tfm suffix *) + OutputByte(xord [ nam.str[n] ]); + end; +end; + +{-----------------------------------------------------} +procedure defineNewfonts; +(* this needs to be done before first access to a font on a page + later someone else will have to re-define all of them in the postamble *) +label 99; +var i, n : integer; + f : integer; +begin + for i := 1 to FTBDs do + begin + if (TBD[i].which = 'V') then + begin + f := TBD[i].indx; + with VFontTable[f]^ do + begin + if (Isdefined) then + goto 99; + Outputfont (DVIFontNum, Cksum, DesSize, DesSize, + FontName); + Isdefined := true; + end; (*with *) + end (* if *) + else if (TBD[i].which = 'M') then + begin (* music font *) + f := TBD[i].indx; + with MFontTable[f]^ do + begin + if (Isdefined) then + goto 99; + Outputfont (DVIFontNum, Cksum, DesSize, DesSize, + FontName); + Isdefined := true; + end; (* with *) + end (* else *) + else if (TBD[i].which = 'L') then + begin (* label font *) + f := TBD[i].indx; + with LFontTable[f]^ do + begin + if (Isdefined) then + goto 99; + Outputfont (DVIFontNum, Cksum, DesSize, DesSize, {### is this right?} + FontName); + Isdefined := true; + end; (* with *) + end + else + begin + complain (ERRREALBAD); + writeln(logfile,'Unknown type of font to be defined:"',TBD[i].which,'"'); + end; (* else *) +99: + end; (* for *) +end; + + +{---------------------------------------------------} +function GetMusFont (stfsiz, fam : integer) : MusIndex; +label 20, 99; +var mustfmnam : strng; + found, i : MusIndex; + design, p1, p2, p3, p4, linesp, gwidth, p7 : ScaledPts; + cksm, r, k : integer; +begin + (* see if it already exists *) + found := 0; + for i := 1 to MFontsDefd do (* loop through since there are few *) + with MFontTable[i]^ do + begin + if (Staffsize = stfsiz) and + (Family = fam) then + begin + found := i; + goto 20; + end; + end; (* with *) + +20: if (found <> 0) then + begin + GetMusFont := found; + goto 99; + end; + + (* Not here already--go get it *) + for k := 1 to ARRLIMIT do + mustfmnam.str[k] := ' '; + + r := 0; + + mustfmnam.str[r+1] := 'm'; + mustfmnam.str[r+2] := 'u'; + mustfmnam.str[r+3] := 's'; + mustfmnam.str[r+4] := xchr[stfsiz + xord['0']]; + mustfmnam.str[r+5] := xchr[fam + xord['0']]; + mustfmnam.str[r+6] := '.'; + mustfmnam.str[r+7] := 't'; + mustfmnam.str[r+8] := 'f'; + mustfmnam.str[r+9] := 'm'; + + mustfmnam.str[r+10] := chr(32); + + mustfmnam.len := 9 + r; + gettfm (mustfmnam, design, p1, p2, p3, p4, linesp, gwidth, p7, cksm); + + MFontsDefd := MFontsDefd + 1; + if (MFontsDefd > SizMFontTable) then + begin + complain (ERRREALBAD); + writestrng(mustfmnam, true); + writeln(logfile,'---not loadable. Size of Music Font table too small'); + writestrng(mustfmnam,false); + writeln(' cannot be loaded. Too many music fonts. Table too small.'); + jumpout; + end; + + i := MFontsDefd; + new (MFontTable[i]); + with MFontTable[i]^ do + begin + Staffsize := stfsiz; + Family := fam; + DesSize := design; + strcopy (mustfmnam.str, FontName.str, mustfmnam.len); + FontName.len := mustfmnam.len; + Cksum := cksm; + ghu := round (gwidth / QNOTEGHUS); + gvu := round (linesp / QNOTEGVUS); + DVIFontNum := GDVIFN + 1; + Isdefined := false; + end; + + GDVIFN := GDVIFN + 1; +(* call someone to do the defns of cdp, cht, cwd foreach beam *) + definebeams (MFontTable[i]); + fonttobedefined ('M', i); + GetMusFont := i; +99: +end; + + +{---------------------------------------------------} +function GetVectFont (size : VThickness; vk : VectKind) : VecIndex; +label 20, 99; +var vectfmnam : strng; + found, i : VecIndex; + design, p1, p2, w0, w1, maxveclen, p6, p7 : ScaledPts; + cksm, r, k : integer; +begin + (* see if it already exists *) + found := 0; + + for i := 1 to VFontsDefd do + with VFontTable[i]^ do + begin + if ((psize = size) and + (vkind = vk)) then + begin + found := i; + goto 20; + end; + end; (* with *) + +20: + if (found <> 0) then + begin + GetVectFont := found; + goto 99; + end; + + (* Not here--go get it *) + for k := 1 to ARRLIMIT do + vectfmnam.str[k] := ' '; + + r := 0; + + case (vk) of + VKCirc : vectfmnam.str[r+1] := 'c'; + VKVert : vectfmnam.str[r+1] := 'v'; + VKHort : vectfmnam.str[r+1] := 'h'; + end; (*case *) + vectfmnam.str[r+2] := 'v'; + vectfmnam.str[r+3] := 'e'; + vectfmnam.str[r+4] := 'c'; + if (size <= 9) then + begin + vectfmnam.str[r+5] := xchr[size + xord['0']]; + vectfmnam.str[r+6] := '.'; + vectfmnam.str[r+7] := 't'; + vectfmnam.str[r+8] := 'f'; + vectfmnam.str[r+9] := 'm'; + + vectfmnam.str[r+10] := chr(32); + + vectfmnam.len := 9 + r; + end + else + begin + vectfmnam.str[r+5] := xchr[(size div 10) + xord['0']]; + vectfmnam.str[r+6] := xchr[(size - ((size div 10)*10)) + xord['0']]; + vectfmnam.str[r+7] := '.'; + vectfmnam.str[r+8] := 't'; + vectfmnam.str[r+9] := 'f'; + vectfmnam.str[r+10] := 'm'; + + vectfmnam.str[r+11] := chr(32); + + vectfmnam.len := 10 + r; + end; + + gettfm (vectfmnam, design, p1, p2, w0, w1, maxveclen, p6, p7, cksm); + VFontsDefd := VFontsDefd + 1; + if (VFontsDefd > SizVFontTable) then + begin + complain (ERRREALBAD); + writestrng(vectfmnam, true); + writeln(logfile,'---not loadable. Size of Vector Font table too small'); + writestrng(vectfmnam,false); + writeln(' cannot be loaded. Too many vector fonts. Table too small.'); + jumpout; + end; + + i := VFontsDefd; + new (VFontTable[i]); + with VFontTable[i]^ do + begin + vkind := vk; + psize := size; + DesSize := design; + if (vk = VKVert) then + PenSize := w1 + else + PenSize := w0; + PenSize := round (size * (MAXVECLENsp / 16.0)); + MaxVectLen := maxveclen; + strcopy (vectfmnam.str, FontName.str, vectfmnam.len); + FontName.len := vectfmnam.len; + Cksum := cksm; + Isdefined := false; + DVIFontNum := GDVIFN + 1; + end; + + GDVIFN := GDVIFN + 1; + + definevectors (VFontTable[i]); +(* someone asked for it, so they must want it, and we should fntdef it *) + fonttobedefined ('V', i); + GetVectFont := i; +99: +end; + +{----------------------------------------------------------} +function GetLabFont (style : integer) : integer; +label 30, 99; +var labtfmnam : strng; + found, i : integer; + design, p1, space, p3, p4, p5, p6, p7 : ScaledPts; + cksm, r, k : integer; +begin +if (style > MAXLABELFONTS) then + style := 1; + found := 0; + for i := 1 to LFontsDefd do + with LFontTable[i]^ do + begin + if (internalnumber = style) then + begin + found := i; + goto 30; + end; + end; +30: + if (found <> 0) then + begin + GetLabFont := found; + goto 99; + end; + for k := 1 to ARRLIMIT do + labtfmnam.str[k] := ' '; + + r := 0; + + labtfmnam.str[r + 1] := 'c'; + labtfmnam.str[r + 2] := 'm'; + case style of + 1: begin (* cmtt10 *) + labtfmnam.str[r + 3] := 't'; + labtfmnam.str[r + 4] := 't'; + labtfmnam.str[r + 5] := '1'; + labtfmnam.str[r + 6] := '0'; + k := r + 6; + end; + 2: begin (* cmb10 *) + labtfmnam.str[r + 3] := 'b'; + labtfmnam.str[r + 4] := '1'; + labtfmnam.str[r + 5] := '0'; diff --git a/macros/latex209/contrib/textyl/psrc/textyl.pas.ac b/macros/latex209/contrib/textyl/psrc/textyl.pas.ac new file mode 100644 index 0000000000..0ec7bacff5 --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/textyl.pas.ac @@ -0,0 +1,1000 @@ + k := r + 5; + end; + 3: begin (* cmsl10 *) + labtfmnam.str[r + 3] := 's'; + labtfmnam.str[r + 4] := 'l'; + labtfmnam.str[r + 5] := '1'; + labtfmnam.str[r + 6] := '0'; + k := r + 6; + end; + 4: begin (* cmtt8 *) + labtfmnam.str[r + 3] := 't'; + labtfmnam.str[r + 4] := 't'; + labtfmnam.str[r + 5] := '8'; + k := r + 5; + end; + 5: begin (* cmsl8 *) + labtfmnam.str[r + 3] := 's'; + labtfmnam.str[r + 4] := 'l'; + labtfmnam.str[r + 5] := '8'; + k := r + 5; + end; + end; (* case *) + labtfmnam.str[k + 1] := '.'; + labtfmnam.str[k + 2] := 't'; + labtfmnam.str[k + 3] := 'f'; + labtfmnam.str[k + 4] := 'm'; + + labtfmnam.str[k+5] := chr(32); + + labtfmnam.len := k + 4; + + gettfm (labtfmnam, design, p1, space, p3, p4, p5, p6, p7, cksm); + + LFontsDefd := LFontsDefd + 1; + + if (LFontsDefd > SizLFontTable) then + begin + complain (ERRREALBAD); + writestrng(labtfmnam, true); + writeln(logfile,'---not loadable. Size of Label Font table too small'); + writestrng(labtfmnam,false); + writeln(' cannot be loaded. Too many label fonts. Table too small.'); + jumpout; + end; + + i := LFontsDefd; + new (LFontTable[i]); + with LFontTable[i]^ do + begin + strcopy (labtfmnam.str, FontName.str, labtfmnam.len); + FontName.len := labtfmnam.len; + Cksum := cksm; + DesSize := design; + internalnumber := style; + spacewidth := space; + DVIFontNum := GDVIFN +1; + Isdefined := false; + end; (* with *) + + GDVIFN := GDVIFN + 1; + fonttobedefined ('L', i); + GetLabFont := i; +99: +end; + + +{------------------------------------------------} +function vectangle (dx, dy : integer) :real; +begin + if (dx <> 0) then + vectangle := arctan (dy / (dx * 1.0)) * RADTODEG + else + begin + if (dy > 0) then + vectangle := 90.0 + else + vectangle := -90.0; + end; +end; + + +{-----------------------------------------------------------} +procedure definevectors (* var Vec: pVectFontInfRec *); +var units : real; +begin + units := Vec^.MaxVectLen / 16.0; +with Vec^.FontInfo[ 0] do begin + Cht := round( 15.9688 * units); + Cdp := 0; + Cwd := round( 0.9981 * units); + Angle := 86.4237; +end; + +with Vec^.FontInfo[ 1] do begin + Cht := round( 15.8764 * units); + Cdp := 0; + Cwd := round( 1.9846 * units); + Angle := 82.8750; +end; + +with Vec^.FontInfo[ 2] do begin + Cht := round( 15.7260 * units); + Cdp := 0; + Cwd := round( 2.9486 * units); + Angle := 79.3803; +end; + +with Vec^.FontInfo[ 3] do begin + Cht := round( 15.5223 * units); + Cdp := 0; + Cwd := round( 3.8806 * units); + Angle := 75.9638; +end; + +with Vec^.FontInfo[ 4] do begin + Cht := round( 15.2717 * units); + Cdp := 0; + Cwd := round( 4.7724 * units); + Angle := 72.6460; +end; + +with Vec^.FontInfo[ 5] do begin + Cht := round( 14.9813 * units); + Cdp := 0; + Cwd := round( 5.6180 * units); + Angle := 69.4440; +end; + +with Vec^.FontInfo[ 6] do begin + Cht := round( 14.6585 * units); + Cdp := 0; + Cwd := round( 6.4131 * units); + Angle := 66.3706; +end; + +with Vec^.FontInfo[ 7] do begin + Cht := round( 14.3108 * units); + Cdp := 0; + Cwd := round( 7.1554 * units); + Angle := 63.4349; +end; + +with Vec^.FontInfo[ 8] do begin + Cht := round( 13.9452 * units); + Cdp := 0; + Cwd := round( 7.8442 * units); + Angle := 60.6422; +end; + +with Vec^.FontInfo[ 9] do begin + Cht := round( 13.5680 * units); + Cdp := 0; + Cwd := round( 8.4800 * units); + Angle := 57.9946; +end; + +with Vec^.FontInfo[ 10] do begin + Cht := round( 13.1847 * units); + Cdp := 0; + Cwd := round( 9.0645 * units); + Angle := 55.4915; +end; + +with Vec^.FontInfo[ 11] do begin + Cht := round( 12.8000 * units); + Cdp := 0; + Cwd := round( 9.6000 * units); + Angle := 53.1301; +end; + +with Vec^.FontInfo[ 12] do begin + Cht := round( 12.4178 * units); + Cdp := 0; + Cwd := round( 10.0895 * units); + Angle := 50.9061; +end; + +with Vec^.FontInfo[ 13] do begin + Cht := round( 12.0412 * units); + Cdp := 0; + Cwd := round( 10.5361 * units); + Angle := 48.8141; +end; + +with Vec^.FontInfo[ 14] do begin + Cht := round( 11.6726 * units); + Cdp := 0; + Cwd := round( 10.9431 * units); + Angle := 46.8476; +end; + +with Vec^.FontInfo[ 15] do begin + Cht := round( 11.3137 * units); + Cdp := 0; + Cwd := round( 11.3137 * units); + Angle := 45.0000; +end; + +with Vec^.FontInfo[ 16] do begin + Cht := round( 10.9431 * units); + Cdp := 0; + Cwd := round( 11.6726 * units); + Angle := 43.1524; +end; + +with Vec^.FontInfo[ 17] do begin + Cht := round( 10.5361 * units); + Cdp := 0; + Cwd := round( 12.0412 * units); + Angle := 41.1859; +end; + +with Vec^.FontInfo[ 18] do begin + Cht := round( 10.0895 * units); + Cdp := 0; + Cwd := round( 12.4178 * units); + Angle := 39.0939; +end; + +with Vec^.FontInfo[ 19] do begin + Cht := round( 9.6000 * units); + Cdp := 0; + Cwd := round( 12.8000 * units); + Angle := 36.8699; +end; + +with Vec^.FontInfo[ 20] do begin + Cht := round( 9.0645 * units); + Cdp := 0; + Cwd := round( 13.1847 * units); + Angle := 34.5085; +end; + +with Vec^.FontInfo[ 21] do begin + Cht := round( 8.4800 * units); + Cdp := 0; + Cwd := round( 13.5680 * units); + Angle := 32.0054; +end; + +with Vec^.FontInfo[ 22] do begin + Cht := round( 7.8442 * units); + Cdp := 0; + Cwd := round( 13.9452 * units); + Angle := 29.3578; +end; + +with Vec^.FontInfo[ 23] do begin + Cht := round( 7.1554 * units); + Cdp := 0; + Cwd := round( 14.3108 * units); + Angle := 26.5651; +end; + +with Vec^.FontInfo[ 24] do begin + Cht := round( 6.4131 * units); + Cdp := 0; + Cwd := round( 14.6585 * units); + Angle := 23.6294; +end; + +with Vec^.FontInfo[ 25] do begin + Cht := round( 5.6180 * units); + Cdp := 0; + Cwd := round( 14.9813 * units); + Angle := 20.5560; +end; + +with Vec^.FontInfo[ 26] do begin + Cht := round( 4.7724 * units); + Cdp := 0; + Cwd := round( 15.2717 * units); + Angle := 17.3540; +end; + +with Vec^.FontInfo[ 27] do begin + Cht := round( 3.8806 * units); + Cdp := 0; + Cwd := round( 15.5223 * units); + Angle := 14.0362; +end; + +with Vec^.FontInfo[ 28] do begin + Cht := round( 2.9486 * units); + Cdp := 0; + Cwd := round( 15.7260 * units); + Angle := 10.6197; +end; + +with Vec^.FontInfo[ 29] do begin + Cht := round( 1.9846 * units); + Cdp := 0; + Cwd := round( 15.8764 * units); + Angle := 7.1250; +end; + +with Vec^.FontInfo[ 30] do begin + Cht := round( 0.9981 * units); + Cdp := 0; + Cwd := round( 15.9688 * units); + Angle := 3.5763; +end; + +with Vec^.FontInfo[ 31] do begin + Cht := 0; + Cdp := 0; + Cwd := round( 16.0000 * units); + Angle := 0.0000; +end; + +with Vec^.FontInfo[ 32] do begin + Cdp := round( 0.9981 * units); + Cht := 0; + Cwd := round( 15.9688 * units); + Angle := -3.5763; +end; + +with Vec^.FontInfo[ 33] do begin + Cdp := round( 1.9846 * units); + Cht := 0; + Cwd := round( 15.8764 * units); + Angle := -7.1250; +end; + +with Vec^.FontInfo[ 34] do begin + Cdp := round( 2.9486 * units); + Cht := 0; + Cwd := round( 15.7260 * units); + Angle := -10.6197; +end; + +with Vec^.FontInfo[ 35] do begin + Cdp := round( 3.8806 * units); + Cht := 0; + Cwd := round( 15.5223 * units); + Angle := -14.0362; +end; + +with Vec^.FontInfo[ 36] do begin + Cdp := round( 4.7724 * units); + Cht := 0; + Cwd := round( 15.2717 * units); + Angle := -17.3540; +end; + +with Vec^.FontInfo[ 37] do begin + Cdp := round( 5.6180 * units); + Cht := 0; + Cwd := round( 14.9813 * units); + Angle := -20.5560; +end; + +with Vec^.FontInfo[ 38] do begin + Cdp := round( 6.4131 * units); + Cht := 0; + Cwd := round( 14.6585 * units); + Angle := -23.6294; +end; + +with Vec^.FontInfo[ 39] do begin + Cdp := round( 7.1554 * units); + Cht := 0; + Cwd := round( 14.3108 * units); + Angle := -26.5651; +end; + +with Vec^.FontInfo[ 40] do begin + Cdp := round( 7.8442 * units); + Cht := 0; + Cwd := round( 13.9452 * units); + Angle := -29.3578; +end; + +with Vec^.FontInfo[ 41] do begin + Cdp := round( 8.4800 * units); + Cht := 0; + Cwd := round( 13.5680 * units); + Angle := -32.0054; +end; + +with Vec^.FontInfo[ 42] do begin + Cdp := round( 9.0645 * units); + Cht := 0; + Cwd := round( 13.1847 * units); + Angle := -34.5085; +end; + +with Vec^.FontInfo[ 43] do begin + Cdp := round( 9.6000 * units); + Cht := 0; + Cwd := round( 12.8000 * units); + Angle := -36.8699; +end; + +with Vec^.FontInfo[ 44] do begin + Cdp := round( 10.0895 * units); + Cht := 0; + Cwd := round( 12.4178 * units); + Angle := -39.0939; +end; + +with Vec^.FontInfo[ 45] do begin + Cdp := round( 10.5361 * units); + Cht := 0; + Cwd := round( 12.0412 * units); + Angle := -41.1859; +end; + +with Vec^.FontInfo[ 46] do begin + Cdp := round( 10.9431 * units); + Cht := 0; + Cwd := round( 11.6726 * units); + Angle := -43.1524; +end; + +with Vec^.FontInfo[ 47] do begin + Cdp := round( 11.3137 * units); + Cht := 0; + Cwd := round( 11.3137 * units); + Angle := -45.0000; +end; + +with Vec^.FontInfo[ 48] do begin + Cdp := round ( 11.6726 * units); + Cht := 0; + Cwd := round( 10.9431 * units); + Angle := -46.8476; +end; + +with Vec^.FontInfo[ 49] do begin + Cdp := round ( 12.0412 * units); + Cht := 0; + Cwd := round( 10.5361 * units); + Angle := -48.8141; +end; + +with Vec^.FontInfo[ 50] do begin + Cdp := round ( 12.4178 * units); + Cht := 0; + Cwd := round( 10.0895 * units); + Angle := -50.9061; +end; + +with Vec^.FontInfo[ 51] do begin + Cdp := round ( 12.8000 * units); + Cht := 0; + Cwd := round( 9.6000 * units); + Angle := -53.1301; +end; + +with Vec^.FontInfo[ 52] do begin + Cdp := round ( 13.1847 * units); + Cht := 0; + Cwd := round( 9.0645 * units); + Angle := -55.4915; +end; + +with Vec^.FontInfo[ 53] do begin + Cdp := round ( 13.5680 * units); + Cht := 0; + Cwd := round( 8.4800 * units); + Angle := -57.9946; +end; + +with Vec^.FontInfo[ 54] do begin + Cdp := round ( 13.9452 * units); + Cht := 0; + Cwd := round( 7.8442 * units); + Angle := -60.6422; +end; + +with Vec^.FontInfo[ 55] do begin + Cdp := round ( 14.3108 * units); + Cht := 0; + Cwd := round( 7.1554 * units); + Angle := -63.4349; +end; + +with Vec^.FontInfo[ 56] do begin + Cdp := round ( 14.6585 * units); + Cht := 0; + Cwd := round( 6.4131 * units); + Angle := -66.3706; +end; + +with Vec^.FontInfo[ 57] do begin + Cdp := round ( 14.9813 * units); + Cht := 0; + Cwd := round( 5.6180 * units); + Angle := -69.4440; +end; + +with Vec^.FontInfo[ 58] do begin + Cdp := round ( 15.2717 * units); + Cht := 0; + Cwd := round( 4.7724 * units); + Angle := -72.6460; +end; + +with Vec^.FontInfo[ 59] do begin + Cdp := round ( 15.5223 * units); + Cht := 0; + Cwd := round( 3.8806 * units); + Angle := -75.9638; +end; + +with Vec^.FontInfo[ 60] do begin + Cdp := round ( 15.7260 * units); + Cht := 0; + Cwd := round( 2.9486 * units); + Angle := -79.3803; +end; + +with Vec^.FontInfo[ 61] do begin + Cdp := round ( 15.8764 * units); + Cht := 0; + Cwd := round( 1.9846 * units); + Angle := -82.8750; +end; + +with Vec^.FontInfo[ 62] do begin + Cdp := round ( 15.9688 * units); + Cht := 0; + Cwd := round( 0.9981 * units); + Angle := -86.4237; +end; + +with Vec^.FontInfo[ 63] do begin + Cht := round( 8.0000 * units); + Cdp := 0; + Cwd := 0; + Angle := 90.0000; +end; + +with Vec^.FontInfo[ 64] do begin + Cht := round( 7.9382 * units); + Cdp := 0; + Cwd := round( 0.9923 * units); + Angle := 82.8750; +end; + +with Vec^.FontInfo[ 65] do begin + Cht := round( 7.7611 * units); + Cdp := 0; + Cwd := round( 1.9403 * units); + Angle := 75.9638; +end; + +with Vec^.FontInfo[ 66] do begin + Cht := round( 7.4906 * units); + Cdp := 0; + Cwd := round( 2.8090 * units); + Angle := 69.4440; +end; + +with Vec^.FontInfo[ 67] do begin + Cht := round( 7.1554 * units); + Cdp := 0; + Cwd := round( 3.5777 * units); + Angle := 63.4349; +end; + +with Vec^.FontInfo[ 68] do begin + Cht := round( 6.7840 * units); + Cdp := 0; + Cwd := round( 4.2400 * units); + Angle := 57.9946; +end; + +with Vec^.FontInfo[ 69] do begin + Cht := round( 6.4000 * units); + Cdp := 0; + Cwd := round( 4.8000 * units); + Angle := 53.1301; +end; + +with Vec^.FontInfo[ 70] do begin + Cht := round( 6.0206 * units); + Cdp := 0; + Cwd := round( 5.2680 * units); + Angle := 48.8141; +end; + +with Vec^.FontInfo[ 71] do begin + Cht := round( 5.6569 * units); + Cdp := 0; + Cwd := round( 5.6569 * units); + Angle := 45.0000; +end; + +with Vec^.FontInfo[ 72] do begin + Cht := round( 5.2680 * units); + Cdp := 0; + Cwd := round( 6.0206 * units); + Angle := 41.1859; +end; + +with Vec^.FontInfo[ 73] do begin + Cht := round( 4.8000 * units); + Cdp := 0; + Cwd := round( 6.4000 * units); + Angle := 36.8699; +end; + +with Vec^.FontInfo[ 74] do begin + Cht := round( 4.2400 * units); + Cdp := 0; + Cwd := round( 6.7840 * units); + Angle := 32.0054; +end; + +with Vec^.FontInfo[ 75] do begin + Cht := round( 3.5777 * units); + Cdp := 0; + Cwd := round( 7.1554 * units); + Angle := 26.5651; +end; + +with Vec^.FontInfo[ 76] do begin + Cht := round( 2.8090 * units); + Cdp := 0; + Cwd := round( 7.4906 * units); + Angle := 20.5560; +end; + +with Vec^.FontInfo[ 77] do begin + Cht := round( 1.9403 * units); + Cdp := 0; + Cwd := round( 7.7611 * units); + Angle := 14.0362; +end; + +with Vec^.FontInfo[ 78] do begin + Cht := round( 0.9923 * units); + Cdp := 0; + Cwd := round( 7.9382 * units); + Angle := 7.1250; +end; + +with Vec^.FontInfo[ 79] do begin + Cht := 0; + Cdp := 0; + Cwd := round( 8.0000 * units); + Angle := 0.0000; +end; + +with Vec^.FontInfo[ 80] do begin + Cdp := round( 0.9923 * units); + Cht := 0; + Cwd := round( 7.9382 * units); + Angle := -7.1250; +end; + +with Vec^.FontInfo[ 81] do begin + Cdp := round( 1.9403 * units); + Cht := 0; + Cwd := round( 7.7611 * units); + Angle := -14.0362; +end; + +with Vec^.FontInfo[ 82] do begin + Cdp := round( 2.8090 * units); + Cht := 0; + Cwd := round( 7.4906 * units); + Angle := -20.5560; +end; + +with Vec^.FontInfo[ 83] do begin + Cdp := round( 3.5777 * units); + Cht := 0; + Cwd := round( 7.1554 * units); + Angle := -26.5651; +end; + +with Vec^.FontInfo[ 84] do begin + Cdp := round( 4.2400 * units); + Cht := 0; + Cwd := round( 6.7840 * units); + Angle := -32.0054; +end; + +with Vec^.FontInfo[ 85] do begin + Cdp := round( 4.8000 * units); + Cht := 0; + Cwd := round( 6.4000 * units); + Angle := -36.8699; +end; + +with Vec^.FontInfo[ 86] do begin + Cdp := round( 5.2680 * units); + Cht := 0; + Cwd := round( 6.0206 * units); + Angle := -41.1859; +end; + +with Vec^.FontInfo[ 87] do begin + Cdp := round( 5.6569 * units); + Cht := 0; + Cwd := round( 5.6569 * units); + Angle := -45.0000; +end; + +with Vec^.FontInfo[ 88] do begin + Cdp := round ( 6.0206 * units); + Cht := 0; + Cwd := round( 5.2680 * units); + Angle := -48.8141; +end; + +with Vec^.FontInfo[ 89] do begin + Cdp := round ( 6.4000 * units); + Cht := 0; + Cwd := round( 4.8000 * units); + Angle := -53.1301; +end; + +with Vec^.FontInfo[ 90] do begin + Cdp := round ( 6.7840 * units); + Cht := 0; + Cwd := round( 4.2400 * units); + Angle := -57.9946; +end; + +with Vec^.FontInfo[ 91] do begin + Cdp := round ( 7.1554 * units); + Cht := 0; + Cwd := round( 3.5777 * units); + Angle := -63.4349; +end; + +with Vec^.FontInfo[ 92] do begin + Cdp := round ( 7.4906 * units); + Cht := 0; + Cwd := round( 2.8090 * units); + Angle := -69.4440; +end; + +with Vec^.FontInfo[ 93] do begin + Cdp := round ( 7.7611 * units); + Cht := 0; + Cwd := round( 1.9403 * units); + Angle := -75.9638; +end; + +with Vec^.FontInfo[ 94] do begin + Cdp := round ( 7.9382 * units); + Cht := 0; + Cwd := round( 0.9923 * units); + Angle := -82.8750; +end; + +with Vec^.FontInfo[ 95] do begin + Cdp := round ( 8.0000 * units); + Cht := 0; + Cwd := 0; + Angle := -90.0000; +end; + +with Vec^.FontInfo[ 96] do begin + Cht := round( 4.0000 * units); + Cdp := 0; + Cwd := 0; + Angle := 90.0000; +end; + +with Vec^.FontInfo[ 97] do begin + Cht := round( 3.8806 * units); + Cdp := 0; + Cwd := round( 0.9701 * units); + Angle := 75.9638; +end; + +with Vec^.FontInfo[ 98] do begin + Cht := round( 3.5777 * units); + Cdp := 0; + Cwd := round( 1.7889 * units); + Angle := 63.4349; +end; + +with Vec^.FontInfo[ 99] do begin + Cht := round( 3.2000 * units); + Cdp := 0; + Cwd := round( 2.4000 * units); + Angle := 53.1301; +end; + +with Vec^.FontInfo[100] do begin + Cht := round( 2.8284 * units); + Cdp := 0; + Cwd := round( 2.8284 * units); + Angle := 45.0000; +end; + +with Vec^.FontInfo[101] do begin + Cht := round( 2.4000 * units); + Cdp := 0; + Cwd := round( 3.2000 * units); + Angle := 36.8699; +end; + +with Vec^.FontInfo[102] do begin + Cht := round( 1.7889 * units); + Cdp := 0; + Cwd := round( 3.5777 * units); + Angle := 26.5651; +end; + +with Vec^.FontInfo[103] do begin + Cht := round( 0.9701 * units); + Cdp := 0; + Cwd := round( 3.8806 * units); + Angle := 14.0362; +end; + +with Vec^.FontInfo[104] do begin + Cht := 0; + Cdp := 0; + Cwd := round( 4.0000 * units); + Angle := 0.0000; +end; + +with Vec^.FontInfo[105] do begin + Cdp := round( 0.9701 * units); + Cht := 0; + Cwd := round( 3.8806 * units); + Angle := -14.0362; +end; + +with Vec^.FontInfo[106] do begin + Cdp := round( 1.7889 * units); + Cht := 0; + Cwd := round( 3.5777 * units); + Angle := -26.5651; +end; + +with Vec^.FontInfo[107] do begin + Cdp := round( 2.4000 * units); + Cht := 0; + Cwd := round( 3.2000 * units); + Angle := -36.8699; +end; + +with Vec^.FontInfo[108] do begin + Cdp := round( 2.8284 * units); + Cht := 0; + Cwd := round( 2.8284 * units); + Angle := -45.0000; +end; + +with Vec^.FontInfo[109] do begin + Cdp := round ( 3.2000 * units); + Cht := 0; + Cwd := round( 2.4000 * units); + Angle := -53.1301; +end; + +with Vec^.FontInfo[110] do begin + Cdp := round ( 3.5777 * units); + Cht := 0; + Cwd := round( 1.7889 * units); + Angle := -63.4349; +end; + +with Vec^.FontInfo[111] do begin + Cdp := round ( 3.8806 * units); + Cht := 0; + Cwd := round( 0.9701 * units); + Angle := -75.9638; +end; + +with Vec^.FontInfo[112] do begin + Cdp := round ( 4.0000 * units); + Cht := 0; + Cwd := 0; + Angle := -90.0000; +end; + +with Vec^.FontInfo[113] do begin + Cht := round( 2.0000 * units); + Cdp := 0; + Cwd := 0; + Angle := 90.0000; +end; + +with Vec^.FontInfo[114] do begin + Cht := round( 1.7889 * units); + Cdp := 0; + Cwd := round( 0.8944 * units); + Angle := 63.4349; +end; + +with Vec^.FontInfo[115] do begin + Cht := round( 1.4142 * units); + Cdp := 0; + Cwd := round( 1.4142 * units); + Angle := 45.0000; +end; + +with Vec^.FontInfo[116] do begin + Cht := round( 0.8944 * units); + Cdp := 0; + Cwd := round( 1.7889 * units); + Angle := 26.5651; +end; + +with Vec^.FontInfo[117] do begin + Cht := 0; + Cdp := 0; + Cwd := round( 2.0000 * units); + Angle := 0.0000; +end; + +with Vec^.FontInfo[118] do begin + Cdp := round( 0.8944 * units); + Cht := 0; + Cwd := round( 1.7889 * units); + Angle := -26.5651; +end; + +with Vec^.FontInfo[119] do begin + Cdp := round( 1.4142 * units); + Cht := 0; + Cwd := round( 1.4142 * units); + Angle := -45.0000; +end; + +with Vec^.FontInfo[120] do begin + Cdp := round ( 1.7889 * units); + Cht := 0; + Cwd := round( 0.8944 * units); + Angle := -63.4349; +end; + +with Vec^.FontInfo[121] do begin + Cdp := round ( 2.0000 * units); + Cht := 0; + Cwd := 0; + Angle := -90.0000; +end; + +with Vec^.FontInfo[122] do begin + Cht := round( 1.0000 * units); + Cdp := 0; + Cwd := 0; + Angle := 90.0000; +end; + +with Vec^.FontInfo[123] do begin + Cht := round( 0.7071 * units); + Cdp := 0; + Cwd := round( 0.7071 * units); + Angle := 45.0000; +end; + +with Vec^.FontInfo[124] do begin + Cht := 0; + Cdp := 0; + Cwd := round( 1.0000 * units); + Angle := 0.0000; +end; + +with Vec^.FontInfo[125] do begin + Cdp := round( 0.7071 * units); + Cht := 0; + Cwd := round( 0.7071 * units); + Angle := -45.0000; +end; + +with Vec^.FontInfo[126] do begin + Cdp := round ( 1.0000 * units); + Cht := 0; + Cwd := 0; + Angle := -90.0000; +end; + +with Vec^.FontInfo[127] do begin + Cht := 0; + Cdp := 0; + Cwd := 0; + Angle := -90.0000; +end; + +end; (* define vectors *) + + + + +{-------------------------------------------------} +(* If, for some reason, you do not want to deal with + music capabilities, replace the body of this procedure + with just a begin end; pair and also the TylBeam proc. +*) +procedure definebeams (* var M : pMusFontInfRec *); +var i : integer; + begin + +end; + +{----------------------------------------------------------} +(* use pre-calculated coordinates of a circle that has a diff --git a/macros/latex209/contrib/textyl/psrc/textyl.pas.ad b/macros/latex209/contrib/textyl/psrc/textyl.pas.ad new file mode 100644 index 0000000000..e7f93892da --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/textyl.pas.ad @@ -0,0 +1,1000 @@ + * given unit-radius. Scale those points to fit the desired radius + *) +procedure defineCircleCpts (rad : ScaledPts; centx, centy : ScaledPts; + var CircleCpt : ControlPoints; + var numpts : integer); +const UnitRadius = 16777216; (* TWO24 scaledpts *) +var ratio : real; +begin + if (rad = 0) then + begin + complain (ERRBAD); + writeln(logfile,'Error in fig#',pgfigurenum:0,' on page ',currpagenum:0); + writeln(logfile,'Zero length radius for circle! Setting to 1 sp'); + rad := 1; + end; + ratio := float(rad) / float(UnitRadius); + numpts := 16; + CircleCpt[1,1] := round (ratio * 16777216.00000) + centx; + CircleCpt[1,2] := 0 + centy; {round (ratio * 0.00000)} + CircleCpt[2,1] := round (ratio * 15500126.47492) + centx; + CircleCpt[2,2] := round (ratio * 6420362.60441) + centy; + CircleCpt[3,1] := round (ratio * 11863283.20303) + centx; + CircleCpt[3,2] := round (ratio * 11863283.20303) + centy; + CircleCpt[4,1] := round (ratio * 6420362.60441) + centx; + CircleCpt[4,2] := round (ratio * 15500126.47492) + centy; + CircleCpt[5,1] := 0 + centx; {round (ratio * -0.00000) } + CircleCpt[5,2] := round (ratio * 16777216.00000) + centy; + CircleCpt[6,1] := round (ratio * -6420362.60441) + centx; + CircleCpt[6,2] := round (ratio * 15500126.47492) + centy; + CircleCpt[7,1] := round (ratio * -11863283.20303) + centx; + CircleCpt[7,2] := round (ratio * 11863283.20303) + centy; + CircleCpt[8,1] := round (ratio * -15500126.47492) + centx; + CircleCpt[8,2] := round (ratio * 6420362.60441) + centy; + CircleCpt[9,1] := round (ratio * -16777216.00000) + centx; + CircleCpt[9,2] := 0 + centy; {round (ratio * -0.00000)} + CircleCpt[10,1] := round (ratio * -15500126.47492) + centx; + CircleCpt[10,2] := round (ratio * -6420362.60441) + centy; + CircleCpt[11,1] := round (ratio * -11863283.20303) + centx; + CircleCpt[11,2] := round (ratio * -11863283.20303) + centy; + CircleCpt[12,1] := round (ratio * -6420362.60441) + centx; + CircleCpt[12,2] := round (ratio * -15500126.47492) + centy; + CircleCpt[13,1] := 0 + centx; {round (ratio * 0.00000) } + CircleCpt[13,2] := round (ratio * -16777216.00000) + centy; + CircleCpt[14,1] := round (ratio * 6420362.60441) + centx; + CircleCpt[14,2] := round (ratio * -15500126.47492) + centy; + CircleCpt[15,1] := round (ratio * 11863283.20303) + centx; + CircleCpt[15,2] := round (ratio * -11863283.20303) + centy; + CircleCpt[16,1] := round (ratio * 15500126.47492) + centx; + CircleCpt[16,2] := round (ratio * -6420362.60441) + centy; + (* create the pre-list phantom *) + CircleCpt[0,1] := CircleCpt[16,1]; + CircleCpt[0,2] := CircleCpt[16,2]; +end; + + +{---------------------------------------------------------------} +(* compute control points for an arc going from startangle to + * stopangle, centered at (centx, centy) + *) +procedure definearcpts (rad : ScaledPts; centx, centy : ScaledPts; + startang, stopang : integer; + var cpts : ControlPoints; + var nknots : integer); +var n : integer; + a, b, curr, delta: real; + i : integer; +begin + a := startang * DEGTORAD; + b := stopang * DEGTORAD; + n := 16; + + if (a > b) then + begin + a := a - (2 * PI); + end; + + delta := abs(b - a) / n; + + if (a = b) then + begin + complain (ERRNOTBAD); + writeln(logfile,'Error in compute arc points:: should be a circle'); + end; + curr := a; + i := 1; + while ((curr <= b)) do + begin (* make arc about (centx,centy) *) + cpts[i,1] := round (rad * cos (curr)) + centx; + cpts[i,2] := round (rad * sin (curr)) + centy; + i := i + 1; + curr := curr + delta; + end; (* while *) + +(* go one point beyond -- + * around the arc so that we can have good smoothness + * for this phantom point + *) + + cpts[i,1] := round (rad * cos (b + delta)) + centx; + cpts[i,2] := round (rad * sin (b + delta)) + centy; + +(* and one phantom point before the list *) + cpts[0,1] := round (rad * cos (a - delta)) + centx; + cpts[0,2] := round (rad * sin (a - delta)) + centy; + + + nknots := i-1; +end; + + + +(* &&Module spline.p *) +(* + Procedures below may make free use of the global variables + arrayXY [list of control points] + pointmatrix [list of spline segments] + knot [list of spline knots] + catrommtx [matrix for Catmull-Rom splines] + bsplmtx [matrix for B-splines] + lastPoint, intervals +*) + + +{-----------------------------------------------------} +function max (a, b: integer):integer; +begin + if (a > b) then + max := a + else + max := b; +end; + +{-----------------------------------------------------} +function min (a, b: integer):integer; +begin + if (a < b) then + min := a + else + min := b; +end; + +{---------------------------------------------------------------------} +(* initialize the Catmull-Rom basis matrix *) + +procedure initcrmatrix; +begin + catrommtx[1,1] := -0.5; catrommtx[1,2] := 1.5; + catrommtx[1,3] := -1.5; catrommtx[1,4] := 0.5; + catrommtx[2,1] := 1.0; catrommtx[2,2] := -2.5; + catrommtx[2,3] := 2.0; catrommtx[2,4] := -0.5; + catrommtx[3,1] := -0.5; catrommtx[3,2] := 0.0; + catrommtx[3,3] := 0.5; catrommtx[3,4] := 0.0; + catrommtx[4,1] := 0.0; catrommtx[4,2] := 1.0; + catrommtx[4,3] := 0.0; catrommtx[4,4] := 0.0; +end; + +{-----------------------------------------------------} +procedure initbsplmatrix; +begin + bsplmtx[1,1] := -1.0/6.0; bsplmtx[1,2] := 0.5; + bsplmtx[1,3] := -0.5; bsplmtx[1,4] := 1.0/6.0; + bsplmtx[2,1] := 0.5; bsplmtx[2,2] := -1.0; + bsplmtx[2,3] := 0.5; bsplmtx[2,4] := 0.0; + bsplmtx[3,1] := -0.5; bsplmtx[3,2] := 0.0; + bsplmtx[3,3] := 0.5; bsplmtx[3,4] := 0.0; + bsplmtx[4,1] := 1.0/6.0; bsplmtx[4,2] := 2.0/3.0; + bsplmtx[4,3] := 1.0/6.0; bsplmtx[4,4] := 0.0; +end; + +{--------------------------------------------------------} +(* init the Cardinal Spline Matrix *) +procedure initcardmatrix; +begin + cardmtx[1,1] := -1.0; cardmtx[1,2] := 1.0; + cardmtx[1,3] := -1.0; cardmtx[1,4] := 1.0; + cardmtx[2,1] := 2.0; cardmtx[2,2] := -2.0; + cardmtx[2,3] := 1.0; cardmtx[2,4] := -1.0; + cardmtx[3,1] := -1.0; cardmtx[3,2] := 0.0; + cardmtx[3,3] := 1.0; cardmtx[3,4] := 0.0; + cardmtx[4,1] := 0.0; cardmtx[4,2] := 1.0; + cardmtx[4,3] := 0.0; cardmtx[4,4] := 0.0; +end; + +{--------------------------------------------------------} +procedure initallspline; + begin + initcrmatrix; + initbsplmatrix; + initcardmatrix; + end; + + +{-----------------------------------------------------} +procedure matXvector (var m: Fourby4Matrix; (* IN *) + var v: Oneby4Vector; (* IN *) + var result: Oneby4Vector); (* OUT *) +var t: Oneby4Vector; +begin + t[1] := v[1]*m[1,1] + v[2]*m[1,2] + v[3]*m[1,3] + v[4]*m[1,4]; + t[2] := v[1]*m[2,1] + v[2]*m[2,2] + v[3]*m[2,3] + v[4]*m[2,4]; + t[3] := v[1]*m[3,1] + v[2]*m[3,2] + v[3]*m[3,3] + v[4]*m[3,4]; + t[4] := v[1]*m[4,1] + v[2]*m[4,2] + v[3]*m[4,3] + v[4]*m[4,4]; + result[1] := t[1]; result[2] := t[2]; + result[3] := t[3]; result[4] := t[4]; +end; + +{-----------------------------------------------------} +(* actually the dot-product *) +function vecXvec (var v1, v2: Oneby4Vector) : real; +begin + vecXvec := v1[1]*v2[1] + v1[2]*v2[2] + v1[3]*v2[3] + v1[4]*v2[4]; +end; + + +{------------------------------------------------------} +(* basXctl is the pre-computed BasisMatrix times the control-point vector *) + +function splinePosition (var basXctl : Oneby4Vector; (* IN *) + t : real ) : real; +var tvect : Oneby4Vector; { vector of t values for spline matrix} +begin + tvect[4] := 1.0; + tvect[3] := t; + tvect[2] := t * t; + if (tvect[2] <= MINREAL) then + begin (* avoid underflow problems *) + tvect[2] := 0.0; + end; + tvect[1] := t * tvect[2]; (* t^3 *) + splinePosition := vecXvec (tvect, basXctl); +end; + +{-------------------------------------------------} +function TwoToThe (n : integer) : integer; +label 78; +var i : integer; + tmp : integer; +begin +tmp := 1; +if (n <= 0) then + goto 78; +if (n < 6) then + begin + case n of + 1 : tmp := 2; + 2 : tmp := 4; + 3 : tmp := 8; + 4 : tmp := 16; + 5 : tmp := 32; + end; (* case *) + end (* if *) +else + begin + tmp := 32; + for i := 6 to n do + tmp := tmp * 2; + end; +78: + TwoToThe := tmp; +end; + +{------------------------------------------------------} +function distance (x0, y0, x1, y1 : real) : real; +var res : real; +begin + res := sqrt ( (x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0)); + distance := res; +end; + + +{------------------------------------------------------} +(* compute the number of subdivisions for this span. + We do this by a quadrature method and a simple linear-distance + metric. This is not optimal in the number of subdivisions actually + required, but is computationally efficient and accurate to the + nearest power of 2 . + *) +function numsubdivisions (var XtimesBas, YtimesBas : Oneby4Vector; + resolution : ScaledPts): integer; +var n : integer; + d : integer; + t : real; + x0, y0, xt, yt : real; +begin + x0 := splinePosition (XtimesBas, 0.0); + y0 := splinePosition (YtimesBas, 0.0); + + t := 1.0; + n := 0; + xt := splinePosition (XtimesBas, t); + yt := splinePosition (YtimesBas, t); + + while ((round (distance (x0, y0, xt, yt)) > resolution) or + (n < 1)) do + begin + t := t / 2.0; (* perform the quadrature *) + n := n + 1; + xt := splinePosition (XtimesBas, t); + yt := splinePosition (YtimesBas, t); + end; (* while *) + numsubdivisions := TwoToThe (n); +end; + +{------------------------------------------------------------------------} +(* compute new control vertices such that the resulting spline + * will interpolate through the old control points. + * This will work as long as the actual arc length + * between consecutive nodes does not vary from span to span. + * The method is noted in Wu and Abel's CACM 20(10) Oct 77 paper + * but the actual working method is from + * Barsky and Greenberg's paper in + * CG&IP 14(3) Nov 1980 pp.203-226 + *) +procedure invertsplvertices (numpts : integer; + isclosed : boolean; + var xys : ControlPoints); (* INOUT *) +var i : integer; + beta, Xrprime, Yrprime : array[0..MAXCTLPTS] of real; + tempxys : ControlPoints; +begin + (* compute the values of beta *) + beta[1] := 0.25; + for i := 2 to numpts + 1 do + beta[i] := 1.0 / (4.0 - beta[i - 1]); + + (* and the r primes from the original vertices *) + Xrprime[1] := beta[1] * xys[1,1] * 5.0; + Yrprime[1] := beta[1] * xys[1,2] * 5.0; + for i := 2 to numpts -1 do + begin + Xrprime[i] := beta[i] * (6.0 * xys[i,1] - Xrprime[i - 1]); + Yrprime[i] := beta[i] * (6.0 * xys[i,2] - Yrprime[i - 1]); + end; (* for *) + Xrprime[numpts] := beta[numpts] * (5.0 * xys[numpts,1] - Xrprime[numpts - 1]); + Yrprime[numpts] := beta[numpts] * (5.0 * xys[numpts,2] - Yrprime[numpts - 1]); + +(* Now perform the back-substitution from the bottom up *) + tempxys[numpts,1] := round (Xrprime[numpts]); + tempxys[numpts,2] := round (Yrprime[numpts]); + for i := numpts - 1 downto 1 do + begin + tempxys[i,1] := round (Xrprime[i] - beta[i] * tempxys[i + 1, 1]); + tempxys[i,2] := round (Yrprime[i] - beta[i] * tempxys[i + 1, 2]); + end; + +if (isclosed) then + begin + (* at this point, we've probably been through one control-point + * adjustment, so let's not muck it up + *) + tempxys[numpts+1,1] := tempxys[1,1]; + tempxys[numpts+1,2] := tempxys[1,2]; + tempxys[numpts+2,1] := tempxys[2,1]; + tempxys[numpts+2,2] := tempxys[2,2]; + tempxys[0,1] := tempxys[numpts,1]; + tempxys[0,2] := tempxys[numpts,2]; + (* copy them back *) + for i := 0 to (numpts+2) do + begin + xys[i,1] := tempxys[i,1]; + xys[i,2] := tempxys[i,2]; + end; + end (* closed *) +else + begin + (* copy back *) + for i := 2 to numpts -1 do + begin + xys[i,1] := tempxys[i,1]; + xys[i,2] := tempxys[i,2]; + end; + end; (* open*) +end; + + +{-----------------------------------------------------} +(* adjust the list of control points so that we can use + * it for B-spline interpolation. + * Add any "phantom" vertices necessary so that the end + * conditions will be correct for interpolation + *) +procedure Bctlptadjust (isclosed : boolean; isarc : boolean; + var n: integer; (* INOUT *) + var xys: ControlPoints; (* INOUT *) + var thx: ThickAryType); (* INOUT *) +var j : integer; + tmp : ControlPoints; + tmpthx : ThickAryType; +begin (* ctlpt adjust*) + +if (isclosed) then + begin +(* here, we have to supply the last 'real' point for the user, + and add three phantoms-- one before, and two after *) + + if (n = 2) then + begin + complain (ERRBAD); + writeln(logfile,'A closed spline requires more than 2 control points '); + writeln(logfile,'making a temporary fix in order to continue...'); + xys[3,1] := xys[1,1]; + xys[3,2] := xys[1,2]; + end; + + for j := 1 to (n) do + begin + tmp[j, 1] := xys[j, 1]; + tmp[j, 2] := xys[j, 2]; + tmpthx[j] := thx[j]; + end; + (* Now take care of the 'phantom' vertices *) + tmp[n+1, 1] := xys[1, 1]; + tmp[n+1, 2] := xys[1, 2]; + tmpthx[n+1] := thx[1]; + tmp[n+2, 1] := xys[2, 1]; + tmp[n+2, 2] := xys[2, 2]; + tmpthx[n+2] := thx[2]; + tmp[n+3, 1] := xys[3, 1]; + tmp[n+3, 2] := xys[3, 2]; + tmpthx[n+3] := thx[3]; + + if (not isarc) then + begin + tmp[0,1] := xys[n, 1]; (* wrap around to the real last point *) + tmp[0,2] := xys[n, 2]; + tmpthx[0] := thx[n]; + end + else + begin + tmp[0,1] := xys[0,1]; + tmp[0,2] := xys[0,2]; + tmpthx[0] := thx[0]; + end; + + n := n + 1; (* we supplied the 'last' point for the user *) + + for j := 0 to n+2 do + begin + xys[j,1] := tmp[j,1]; + xys[j,2] := tmp[j,2]; + thx[j] := tmpthx[j]; + end; (* for *) + end (* if closed *) +else + begin (* OPEN SPLINE *) + if (not isarc) then + begin + tmp[0,1] := 2 * xys[1, 1] - xys[2,1]; + tmp[0,2] := 2 * xys[1, 2] - xys[2,2]; + end + else + begin + tmp[0,1] := xys[0,1]; + tmp[0,2] := xys[0,2]; + end; + tmpthx[0] := thx[1]; + + for j := 1 to (n) do + begin + tmp[j, 1] := xys[j, 1]; + tmp[j, 2] := xys[j, 2]; + tmpthx[j] := thx[j]; + end; + + tmp[n+1, 1] := 2 * xys[n, 1] - xys[n-1,1]; + tmp[n+1, 2] := 2 * xys[n, 2] - xys[n-1,2]; + tmpthx[n+1] := thx[n]; + + tmp[n+2, 1] := tmp[n+1, 1]; + tmp[n+2, 2] := tmp[n+1, 2]; + tmpthx[n+2] := thx[n]; + + for j := 0 to n+2 do + begin + xys[j,1] := tmp[j,1]; + xys[j,2] := tmp[j,2]; + thx[j] := tmpthx[j]; + end; (* for *) + end; (* if open *) + +end; + + + +{-----------------------------------------------------} +(* adjust the list of control points so that we can use + * it for simple Catmull-Rom spline interpolation. + * Add any "phantom" vertices necessary so that the end + * conditions will be correct for interpolation + *) +procedure CRctlptadjust (isclosed : boolean; isarc : boolean; + var n: integer; (* INOUT *) + var xys: ControlPoints; (* INOUT *) + var thx: ThickAryType); (* INOUT *) +var j : integer; + tmp : ControlPoints; + tmpthx : ThickAryType; +begin (* ctlpt adjust*) +if (isclosed) then + begin +(* here, we have to supply the last 'real' point for the user, + and add three phantoms-- one before, and two after *) + + if (n = 2) then + begin + complain (ERRBAD); + writeln(logfile,'A closed spline requires more than 2 control points '); + writeln(logfile,'making a temporary fix in order to continue...'); + xys[3,1] := xys[1,1]; + xys[3,2] := xys[1,2]; + end; + + + for j := 1 to (n) do + begin + tmp[j, 1] := xys[j, 1]; + tmp[j, 2] := xys[j, 2]; + tmpthx[j] := thx[j]; + end; + (* the phantom vertices *) + tmp[n+1, 1] := xys[1, 1]; + tmp[n+1, 2] := xys[1, 2]; + tmpthx[n+1] := thx[1]; + tmp[n+2, 1] := xys[2, 1]; + tmp[n+2, 2] := xys[2, 2]; + tmpthx[n+2] := thx[2]; + tmp[n+3, 1] := xys[3, 1]; + tmp[n+3, 2] := xys[3, 2]; + tmpthx[n+3] := thx[3]; + + if (not isarc) then + begin + tmp[0,1] := xys[n, 1]; (* wrap around to the real last point *) + tmp[0,2] := xys[n, 2]; + tmpthx[0] := thx[n]; + end + else + begin + tmp[0,1] := xys[0,1]; + tmp[0,2] := xys[0,2]; + tmpthx[0] := thx[0]; + end; + n := n + 1; (* we supplied the 'last' point for the user *) + + for j := 0 to n+2 do + begin + xys[j,1] := tmp[j,1]; + xys[j,2] := tmp[j,2]; + thx[j] := tmpthx[j]; + end; (* for *) + end (* if closed *) +else + begin (* OPEN SPLINE *) + if (not isarc) then + begin + tmp[0,1] := xys[1, 1]; (* double the first point *) + tmp[0,2] := xys[1, 2]; + end + else + begin + tmp[0,1] := xys[0,1]; + tmp[0,2] := xys[0,2]; + end; + tmpthx[0] := thx[1]; + + for j := 1 to (n) do + begin + tmp[j, 1] := xys[j, 1]; + tmp[j, 2] := xys[j, 2]; + tmpthx[j] := thx[j]; + end; + + tmp[n+1, 1] := xys[n, 1]; (* and triple the last *) + tmp[n+1, 2] := xys[n, 2]; + tmpthx[n+1] := thx[n]; + tmp[n+2, 1] := xys[n, 1]; + tmp[n+2, 2] := xys[n, 2]; + tmpthx[n+2] := thx[n]; + + for j := 0 to n+2 do + begin + xys[j,1] := tmp[j,1]; + xys[j,2] := tmp[j,2]; + thx[j] := tmpthx[j]; + end; (* for *) + end; (* if open *) +end; (* ctlpt adjust *) + + + +{----------------------------------------------------------} + +procedure interpsplines (splinetype: SplineKind; + isclosed: boolean; + isanArc: boolean; + linepatt : LineStyle; + var basismatrix : Fourby4Matrix; (* IN *) + numctls: integer; + var arrayXY: ControlPoints; (* IN *) + var pointmatrix: SplineSegments; (* OUT *) + varythicks: boolean; + var thickmatrix: ThickAryType; (* IN *) + var TTmatrix: ThickAryType); (* OUT *) +label 32; +var xctl, yctl, { vectors of x, y posits of control points} + wctl : Oneby4Vector; {vector of thicknesses at each ctl pt} + t, incr: real; + Pi: integer; { P sub i } + i, currpt : integer; + theresolution : ScaledPts; + +begin (* interp splines*) + if ((not isclosed) and (isanArc)) then + numctls := numctls + 1; (* lie a little *) + + case (splinetype) of + + BSPL: Bctlptadjust (isclosed, isanArc, numctls, arrayXY, thickmatrix); + + CARD, + CATROM: CRctlptadjust (isclosed, isanArc, numctls, arrayXY, thickmatrix); + + INTBSPL: begin + if (isclosed) then + begin + Bctlptadjust (true, isanArc, numctls, arrayXY, thickmatrix); + invertsplvertices (numctls, true, arrayXY); + end + else + begin + invertsplvertices (numctls, false, arrayXY); + Bctlptadjust (false, isanArc, numctls, arrayXY, thickmatrix); + end; (* else *) + end; (* Interpolating Bsplines *) + end; + + if ((not isclosed) and (isanArc)) then + numctls := numctls - 1; (* UN-lie a little *) + + +(* this is the scheme: + * val := t-vector * Basis matrix * point matrix + * [t^3 t^2 t 1] * [[Ms]] * [Pi-1 Pi Pi+1 Pi+2] + * where "Pi-1" is "P sub (i-1)", etc. + * + * But we do this in a round about way: + * Point matrix * basis + * then * t-vector will yield the single value + * + * there are certainly faster ways to do this, + * but this is the easiest to understand + *) + + currpt := 1; + case linepatt of + solid : theresolution := MAXVECLENsp; + dotted, + dashed, + dotdash : theresolution := 3 * MAXVECLENsp; {###} + end; + + for Pi := 1 to (numctls - 1) do + begin + xctl[1] := float(arrayXY[Pi-1, 1]); + xctl[2] := float(arrayXY[Pi, 1]); + xctl[3] := float(arrayXY[Pi+1, 1]); + xctl[4] := float(arrayXY[Pi+2, 1]); + yctl[1] := float(arrayXY[Pi-1, 2]); + yctl[2] := float(arrayXY[Pi, 2]); + yctl[3] := float(arrayXY[Pi+1, 2]); + yctl[4] := float(arrayXY[Pi+2, 2]); + matXvector (basismatrix, xctl, xctl); + matXvector (basismatrix, yctl, yctl); + + (* compute the delta-t increment for this segment + based on a metric for subdivision *) + intervals := numsubdivisions (xctl, yctl, theresolution); + if ((linepatt = solid) and (intervals <= 2)) then + intervals := intervals * 2; + incr := 1.0 / intervals; + + (* avoid over-flowing the "pointmatrix" *) + if ((currpt + intervals - 1) >= MAXSPLINESEGS) then + begin + complain (ERRREALBAD); + writeln (logfile,'error: Too many spline segments required.'); + writeln (logfile,' Reducing the number of control points to get output.'); + goto 32; + end; + + t := 0.0; + while (t < 0.999999999) do + begin + pointmatrix[currpt, 1] := round (splinePosition (xctl, t)); + pointmatrix[currpt, 2] := round (splinePosition (yctl, t)); + + if (varythicks) then + begin + wctl[1] := float(thickmatrix[Pi-1]); + wctl[2] := float(thickmatrix[Pi ]); + wctl[3] := float(thickmatrix[Pi+1]); + wctl[4] := float(thickmatrix[Pi+2]); + matXvector (catrommtx, wctl, wctl); (* requires using Catmull-Rom *) + TTmatrix[currpt] := round (splinePosition (wctl, t)); + end; + + t := t + incr; + currpt := currpt + 1; + end; (* while loop *) + + + end; (* for loop *) + +32: + (* the END-condtion *) + pointmatrix[currpt, 1] := round (splinePosition (xctl, 1.0)); + pointmatrix[currpt, 2] := round (splinePosition (yctl, 1.0)); + if (varythicks) then + begin + wctl[1] := thickmatrix[numctls-2]; + wctl[2] := thickmatrix[numctls-1]; + wctl[3] := thickmatrix[numctls]; + wctl[4] := thickmatrix[numctls+1]; + matXvector (catrommtx, wctl, wctl); (* requires using Catmull-Rom *) + TTmatrix[currpt] := round (splinePosition (wctl, 1.0)); + end; + + lastPoint := currpt; + +end; (* interpsplines *) + + +{----------------------------------------------------------------} +procedure drawSpline (splinetype : SplineKind; + isclosed: boolean; + isanArc: boolean; + patt : LineStyle; + numctls: integer; + var arrayXY: ControlPoints; (* IN *) + var pointmatrix: SplineSegments; (* OUT *) + varythicks: boolean; + var thickmatrix: ThickAryType; (* IN *) + var TTmatrix: ThickAryType); (* OUT *) +begin + lastPoint := 0; + + + case (splinetype) of + CATROM : interpsplines (splinetype, isclosed, isanArc, patt, catrommtx, + numctls, arrayXY, pointmatrix, + varythicks, thickmatrix, TTmatrix); + + CARD : interpsplines (splinetype, isclosed, isanArc, patt, cardmtx, + numctls, arrayXY, pointmatrix, + varythicks, thickmatrix, TTmatrix); + + BSPL : interpsplines (splinetype, isclosed, isanArc, patt, bsplmtx, + numctls, arrayXY, pointmatrix, + varythicks, thickmatrix, TTmatrix); + + INTBSPL : interpsplines (splinetype, isclosed, isanArc, patt, bsplmtx, + numctls, arrayXY, pointmatrix, + varythicks, thickmatrix, TTmatrix); + end; (*Case *) +end; + + +(* &&module TeXtyl *) +{----------------------------------------------------------------} +(* rotate a (x,y) point about mx, my *) +procedure ptrotate (var x, y : integer; + mx, my: integer; + angle : real); +var tmpx, tmpy : integer; + cosa, sina : real; +begin + tmpx := x - mx; + tmpy := y - my; + cosa := cos(angle * DEGTORAD); + sina := sin(angle * DEGTORAD); + x := round(tmpx * cosa - tmpy * sina) + mx; + y := round(tmpx * sina + tmpy * cosa) + my; +end; + +{----------------------------------------------------------------} +(* transform two line points: scale, rotate and translate +*) +procedure xfmlinepts (var x1, y1, x2, y2 : ScaledPts; + offh, offv : ScaledPts; + midx, midy : ScaledPts; + scalefact : real; + theta : real; + dx, dy : ScaledPts; + sx, sy : real); +begin + if ((sx = 0.0) or (sy = 0.0)) then + begin + complain (ERRBAD); + writeln(logfile,'?? Some scale factor is Zero... continuing anyway'); + end; + (* scale about center of item*) + if ((sx <> 1.0) or (sy <> 1.0)) then + begin + x1 := round((x1 - midx) * sx) + midx; + x2 := round((x2 - midx) * sx) + midx; + y1 := round((y1 - midy) * sy) + midy; + y2 := round((y2 - midy) * sy) + midy; + end; + (* rotate if necessary *) + if (theta <> 0.0) then + begin (* rotate about the midpoint *) + ptrotate(x1, y1, midx, midy, theta); + ptrotate(x2, y2, midx, midy, theta); + end; + (* translate *) + x1 := (x1 + round(dx * scalefact) + offh); + x2 := (x2 + round(dx * scalefact) + offh); + y1 := (y1 + round(dy * scalefact) + offv); + y2 := (y2 + round(dy * scalefact) + offv); +end; (* xfmlinepts *) + +{----------------------------------------------------------------} +procedure xfmcontpts (var xpts : ControlPoints; xknots : integer; + offh, offv : ScaledPts; midx, midy : ScaledPts; + scalefact : real; + theta : real; dx, dy : ScaledPts; sx, sy : real); +var i : integer; +begin + (* scale about center of item *) + if ((sx <> 1.0) or (sy <> 1.0)) then + for i := 0 to xknots do + begin + xpts[i,1] := round((xpts[i,1] - midx) * sx) + midx; + xpts[i,2] := round((xpts[i,2] - midy) * sy) + midy; + end; + + if (theta <> 0.0) then + begin (* rotate about center *) + for i := 0 to xknots do + begin + ptrotate (xpts[i,1], xpts[i,2], midx, midy, theta); + end; + end; + (* translate *) + for i := 0 to xknots do + begin + xpts[i,1] := (xpts[i,1] + round(dx * scalefact) + offh); + xpts[i,2] := (xpts[i,2] + round(dy * scalefact) + offv); + end; +end; (* xfmcontpts *) + + +{----------------------------------------------------------------} +(* convert into DVI space and offset by H & V *) +procedure dvilinepts (var x1, y1, x2, y2 : ScaledPts; + offh, offv : ScaledPts); +begin + x1 := (x1 + offh); + x2 := (x2 + offh); + y1 := (y1 * (-1) + offv); + y2 := (y2 * (-1) + offv); +end; + +{----------------------------------------------------------------} +(* convert into DVI space and offset by H & V *) +procedure dvicontpts (var xpts : ControlPoints; xknots : integer; + offh, offv : ScaledPts); +var i : integer; +begin + for i := 0 to xknots do + begin + xpts[i,1] := (xpts[i,1] + offh); + xpts[i,2] := (xpts[i,2] * (-1) + offv); + end; +end; + +{----------------------------------------------------------------} +(* transform all the figure's elements according to the + top-level tranformation requirements in 1st Quadrant space. + then reset the toplevel's xfms. +*) +procedure toplevelxfm (toplev, curfig : pItem; recurlevel : integer); +var pi : pItem; + null1, null2 : ScaledPts; + old1, old2 : ScaledPts; + midx, midy : ScaledPts; +begin + with toplev^ do + begin + midy := (BBty - BBby) div 2; + midx := (BBrx - BBlx) div 2; + end; + pi := curfig^.body^.things; { if recur==0, this is same as toplev } + while (pi <> nil) do + begin + with pi^ do + begin + case (kind) of + Aline : begin + xfmlinepts (lx1, ly1, lx2, ly2, 0, 0, midx, midy, 1.0, + toplev^.figtheta, toplev^.fdx, toplev^.fdy, + toplev^.fsx, toplev^.fsy); + end; + Aspline : begin + xfmcontpts (spts, nsplknots, 0, 0, midx, midy, 1.0, + toplev^.figtheta, toplev^.fdx, toplev^.fdy, + toplev^.fsx, toplev^.fsy); + end; + Attspline : begin + xfmcontpts (ttpts, nttknots, 0, 0, midx, midy, 1.0, + toplev^.figtheta, toplev^.fdx, toplev^.fdy, + toplev^.fsx, toplev^.fsy); + end; + Aarc : begin + null1 := 0; null2 := 0; + old1 := acentx; old2 := acenty; + xfmlinepts (acentx, acenty, null1, null2, 0,0, midx, midy, 1.0, + toplev^.figtheta, toplev^.fdx, toplev^.fdy, + toplev^.fsx, toplev^.fsy); + + xfmcontpts (arcpts, narcknots + 1, 0, 0, old1, old2, 1.0, + toplev^.figtheta, + toplev^.fdx + (acentx - old1), + toplev^.fdy + (acenty - old2), + toplev^.fsx, toplev^.fsy); + end; + Alabel : begin + null1 := 0; null2 := 0; + xfmlinepts (labx, laby, null1, null2, 0, 0, midx, midy, 1.0, + toplev^.figtheta, toplev^.fdx, toplev^.fdy, + toplev^.fsx, toplev^.fsy); + end; + Abeam : ; (* not transformable *) + + Atieslur: ; (* not transformable *) + + Afigure : begin + toplevelxfm (toplev, pi, recurlevel + 1); + end; + end; (* case *) + end; (* with *) + pi := pi^.nextitem; + end; (* while *) + if (recurlevel = 0) then + begin (* reset the toplevel's xfms *) + with toplev^ do + begin + figtheta := 0.0; + fsx := 1.0; fsy := 1.0; + fdx := 0; fdy := 0; + end; + end; +end; + + +{----------------------------------------------------------------} +function scalefitfactor (actualwid, actualht, + goalwid, goalht: ScaledPts): real; +var sx, sy : real; +begin + sx := goalwid/actualwid; + sy := goalht/actualht; + if (sx < sy) then + scalefitfactor := sx + else + scalefitfactor := sy; +end; + + + +(* ---- The handlers for each primitive ---- + * The result of calling each handler is either immediate + * output to the buffer of the commands to produce the + * primitive, OR the primitive gets pushed onto a stack/list + * that defines a current 'figure' (set of prims) for + * output at a later time + * + * Look at linehandle for a basic idea of how the handlers + * work. the others follow pretty closely. + *) + + +{------------------------------------------------------------} +procedure linehandle (figdepth : integer; scalefact: real; + x1, y1, x2, y2 : ScaledPts; + dvih, dviv : ScaledPts; (* possible dvi-offsets *) + thk : VThickness; vk : VectKind; + patt : LineStyle; + minx, maxx, miny, maxy : ScaledPts; + tx, ty: ScaledPts; sx, sy, r : real); +var midx, midy : ScaledPts; + lineitem : pItem; +begin + midx := (minx + maxx) div 2; + midy := (miny + maxy) div 2; + + (* do local primitive -level transformations *) + xfmlinepts (x1, y1, x2, y2, dvih, dviv, + midx, midy, scalefact, r, tx, ty, sx, sy); + diff --git a/macros/latex209/contrib/textyl/psrc/textyl.pas.ae b/macros/latex209/contrib/textyl/psrc/textyl.pas.ae new file mode 100644 index 0000000000..bce0805fb6 --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/textyl.pas.ae @@ -0,0 +1,1000 @@ + if (figdepth = 0) then + begin (* ---- do the primitive by itself *) + (* re-transform it to the 4th Quadrant *) + dvilinepts (x1, y1, x2, y2, h, v); (* global h and v posit *) + IPUSH; + TylLine (x1, y1, x2, y2, thk, vk, patt); + IPOP; + end + else if (figdepth > 0) then + begin (* ---- Pack it and stack it *) + lineitem := NewItem (Aline); + with lineitem^ do + begin + BBlx := minx; BBby := miny; + BBrx := maxx; BBty := maxy; + lx1 := x1; ly1 := y1; + lx2 := x2; ly2 := y2; + itemthick := thk; + itemvec := vk; + itempatt := patt; + end; + pushItem (figdepth, lineitem); + end + else if (figdepth < 0) then + begin (* ---- just do it right away without any PUSH/POP pair *) + (* this is the case when we are unpacking a figure for + * immediate output + *) + TylLine (x1, y1, x2, y2, thk, vk, patt); + end; +end; (* linehandle *) + + +(* --- Simple Splines -----*) +{-----------------------------------------------------} +procedure splinehandle (figdepth : integer; scalefact : real; + thetype : SplineKind; isclosed : boolean; + markdiam : integer; + var contpts : ControlPoints; + nknots : integer; + dvih, dviv : ScaledPts; (* possible dvi-offsets *) + thk : VThickness; vec : VectKind; + patt : LineStyle; + minx, maxx, miny, maxy : ScaledPts; + tx, ty : ScaledPts; sx, sy, r : real); +var midx, midy : ScaledPts; + splineitem : pItem; + i : integer; +begin + midx := (minx + maxx) div 2; + midy := (miny + maxy) div 2; + + xfmcontpts (contpts, nknots, dvih, dviv, midx, midy, + scalefact, r, tx, ty, sx, sy); + + if (figdepth = 0) then + begin (* ---- do the primitive *) + (* transform to 4th quad *) + dvicontpts (contpts, nknots, h, v); + IPUSH; + TylSpline (thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam); + IPOP; + end + else if (figdepth > 0) then + begin + splineitem := NewItem (Aspline); + with splineitem^ do + begin + BBlx := minx; BBby := miny; + BBrx := maxx; BBty := maxy; + itemthick := thk; + itemvec := vec; + itempatt := patt; + nsplknots := nknots; + spltype := thetype; + sclosed := isclosed; + dosmarks := markdiam; + for i := 1 to nknots do + begin + spts[i,1] := contpts[i,1]; + spts[i,2] := contpts[i,2]; + end; + end; + pushItem (figdepth, splineitem); + end + else if (figdepth < 0) then + begin + TylSpline (thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam); + end; +end; (* splinehandle *) + + +(* --- Variable thickness splines ----- *) +{-----------------------------------------------------} +procedure ttsplhandle (figdepth : integer; scalefact : real; + thetype : SplineKind; isclosed : boolean; + markdiam : integer; + contpts : ControlPoints; + ttks : ThickAryType; + nknots : integer; + dvih, dviv : ScaledPts; (* possible dvi-offsets *) + vec : VectKind; + patt : LineStyle; + minx, maxx, miny, maxy : ScaledPts; + tx, ty : ScaledPts; sx, sy, r : real); +var midx, midy : ScaledPts; + ttsplitem : pItem; + i : integer; +begin + midx := (minx + maxx) div 2; + midy := (miny + maxy) div 2; + + xfmcontpts (contpts, nknots, dvih, dviv, midx, midy, + scalefact, r, tx, ty, sx, sy); + + if (figdepth = 0) then + begin + (* transform to 4th quad *) + dvicontpts (contpts, nknots, h, v); + IPUSH; + TylThickThinSpline (thetype, isclosed, contpts, ttks, nknots, vec, patt, markdiam); + IPOP; + end + else if (figdepth > 0) then + begin + ttsplitem := NewItem (Attspline); + with ttsplitem^ do + begin + BBlx := minx; BBby := miny; + BBrx := maxx; BBty := maxy; + itemvec := vec; + itempatt := patt; + nttknots := nknots; + tspltype := thetype; + dottmarks := markdiam; + tclosed := isclosed; + for i := 1 to nknots do + begin + ttpts[i,1] := contpts[i,1]; + ttpts[i,2] := contpts[i,2]; + ttarry[i] := ttks[i]; + end; + end; (* ttsplitem *) + pushItem (figdepth, ttsplitem); + end + else if (figdepth < 0) then + begin + TylThickThinSpline (thetype, isclosed, contpts, ttks, nknots, vec, patt, markdiam); + end; + +end; (* ttsplhandle *) + + +(* ---- Musical Beams ---- *) +{-----------------------------------------------------} +procedure beamhandle (depth, siz : integer; bk : BeamKind; + x1, y1, x2, y2 : ScaledPts); +var bmitem : pItem; +begin + if (depth = 0) then + begin + dvilinepts (x1, y1, x2, y2, h, v); + IPUSH; + TylBeam (x1, y1, x2, y2, siz, bk); + IPOP; + end + else if (depth > 0) then + begin + bmitem := NewItem (Abeam); + with bmitem^ do + begin + BBlx := min(x1, x2); BBby := min(y1, y2); + BBrx := max(x1, x2); BBty := max(y1, y2); + bx1 := x1; by1 := y1; + bx2 := x2; by2 := y2; + staf := siz; + bkind := bk; + end; (* with *) + pushItem (depth, bmitem); + end + else if (depth < 0) then + begin + TylBeam (x1, y1, x2, y2, siz, bk); + end; (* else *) +end; (* beamhandle *) + + +(* ---- Musical Ties and Slurs ----- *) +{-----------------------------------------------------} +procedure tieslurhandle (depth: integer; pts : ControlPoints; + numk : integer; minthick, maxthick : VThickness); +var tsitem : pItem; + i : integer; +begin +if (depth = 0) then + begin + dvicontpts (pts, numk, h, v); + IPUSH; + TylTieSlur (pts, numk, minthick, maxthick); + IPOP; + end +else if (depth > 0) then + begin + tsitem := NewItem (Atieslur); + with tsitem^ do + begin + ntknots := numk; + for i := 1 to numk do + begin + tspts[i,1] := pts[i,1]; + tspts[i,2] := pts[i,2]; + end; + minth := minthick; + maxth := maxthick; + end; (* with *) + pushItem (depth, tsitem); + end +else if (depth < 0) then + begin + TylTieSlur (pts, numk, minthick, maxthick); + end; (* else *) +end; (* tieslurhandle *) + + +{---------------------------------------------------------} +procedure arccirclehandle (figdepth : integer; scalefact : real; + cx, cy : ScaledPts; + radius : ScaledPts; + ang1, ang2 : integer; + var contpts : ControlPoints; (* IN *) + nknots : integer; + dvih, dviv : ScaledPts; (* possible dvi-offsets *) + thk : VThickness; vec : VectKind; + patt : LineStyle; + minx, maxx, miny, maxy : ScaledPts; + tx, ty : ScaledPts; sx, sy, r : real); + +var midx, midy : ScaledPts; + middlex, middley : ScaledPts; + arcitem : pItem; + i : integer; + isclosedarc : boolean; + +begin + midx := cx; middlex := (minx + maxx) div 2; + midy := cy; middley := (miny + maxy) div 2; + isclosedarc := (ang1 = ang2); +{ + if (isclosedarc) then + maxspanlen := round ((360.0 / 16.0) * DEGTORAD * radius) + else + maxspanlen := round ((abs(ang2 - ang1) / 16.0) * DEGTORAD * radius); +{ } + + + xfmcontpts (contpts, nknots+1, dvih, dviv, midx, midy, + scalefact, r, tx, ty, sx, sy); + + if (figdepth = 0) then + begin (* ---- just do the primitive *) + (* transform to 4th quad *) + dvicontpts (contpts, nknots+1, h, v); + IPUSH; + doTylArc (isclosedarc, + contpts, nknots, thk, vec, patt); + IPOP; + end + else if (figdepth > 0) then + begin + arcitem := NewItem (Aarc); + with arcitem^ do + begin + BBlx := minx; BBby := miny; + BBrx := maxx; BBty := maxy; + itemthick := thk; + itemvec := vec; + itempatt := patt; + narcknots := nknots; + acentx := cx; + acenty := cy; + aradius := radius; + firstang := ang1; + lastang := ang2; + for i := 0 to nknots+1 do + begin + arcpts[i,1] := contpts[i,1]; + arcpts[i,2] := contpts[i,2]; + end; + end; + pushItem (figdepth, arcitem); + end + else if (figdepth < 0) then + begin + doTylArc (isclosedarc, contpts, nknots, thk, vec, patt); + end; +end; (* arccirclehandle *) + + + +{---------------------------------------------------------} +procedure labelhandle (depth : integer; scalefact: real; + lax, lay : ScaledPts; + dvih, dviv : ScaledPts; (* possible dvi-offsets *) + style : integer; + phrase : strng; + tx, ty : ScaledPts); +var labitem : pItem; + null1, null2 : ScaledPts; +begin +(* xfm the label point if necessary *) + lax := lax + round(tx * scalefact); + lay := lay + round(ty * scalefact); + + if (depth = 0) then + begin + null1 := 0; null2 := 0; + dvilinepts (lax, lay, null1, null2, h, v); + IPUSH; + TylLabel (lax, lay, style, phrase.str, phrase.len); + IPOP; + end + else if (depth > 0) then + begin + labitem := NewItem (Alabel); + with labitem^ do + begin + labx := lax; + laby := lay; + fontstyle := style; + strcopy (phrase.str, labeltext.str, phrase.len); + labeltext.len := phrase.len; + end; + pushItem (depth, labitem); + end + else if (depth < 0) then + begin + TylLabel (lax, lay, style, phrase.str, phrase.len); + end; +end; + + +(* #### Insert new handlers here for new "primitives" + i.e., names callable from the \special[tyl ...] level +*) + + + +{----------------------------------------------------------------} +(* transform the current bbox coordinates, and output the new one *) +procedure newbbox (var minx, maxx, miny, maxy : ScaledPts; + midx, midy : ScaledPts; + sx, sy, rot : real; tx, ty : ScaledPts); +var + (* coords of full bbox for transformation [n/s][e/w][x/y] *) + nex, ney, sex, sey, swx, swy, nwx, nwy: ScaledPts; + temp1, temp2 : integer; +begin + (* describe and transform the bbox *) + nwx := round (minx * sx); nex := round (maxx * sx); + sex := round (maxx * sx); swx := round (minx * sx); + ney := round (maxy * sy); nwy := round (maxy * sy); + swy := round (miny * sy); sey := round (miny * sy); + + ptrotate (nex, ney, midx, midy, rot); + ptrotate (sex, sey, midx, midy, rot); + ptrotate (swx, swy, midx, midy, rot); + ptrotate (nwx, nwy, midx, midy, rot); + + nex := nex + tx; sex := sex + tx; + swx := swx + tx; nwx := nwx + tx; + ney := ney + ty; sey := sey + ty; + swy := swy + ty; nwy := nwy + ty; + (* now find the actual extents of the bbox *) + temp1 := min (nex, nwx); + temp2 := min (swx, sex); + minx := min (temp1, temp2); + + temp1 := min (ney, nwy); + temp2 := min (swy, sey); + miny := min (temp1, temp2); + + temp1 := max (nex, nwx); + temp2 := max (swx, sex); + maxx := max (temp1, temp2); + + temp1 := max (ney, nwy); + temp2 := max (swy, sey); + maxy := max (temp1, temp2); +end; + + +{-----------------------------------------------} +(* find the bounding box of the list of primitives + and/or sub-figures in this Item *) + +procedure findBBox (blot : pItem; + var mnx, mxx, mny, mxy : ScaledPts); +var + pi : pItem; + bmnx, bmxx, bmny, bmxy, midx, midy : ScaledPts; (* bbox [min/max][x/y] *) + tmnx, tmxx, tmny, tmxy : ScaledPts; (* temporary, in case of recursion *) + null1, null2 : ScaledPts; + prescale, postscale : real; + old1, old2 : ScaledPts; +begin + bmnx := TWO24; bmny := TWO24; + bmxx := -TWO24; bmxy :=-TWO24; + if (blot^.kind = Afigure) then + begin (* afigure *) + pi := blot^.body^.things; + while (pi <> nil) do + begin (* find the current bbox of the list of items here *) + if (pi^.kind = Afigure) then + begin (* recur *) + findBBox (pi, tmnx, tmxx, tmny, tmxy); + bmnx := min (bmnx, tmnx); + bmny := min (bmny, tmny); + bmxx := max (bmxx, tmxx); + bmxy := max (bmxy, tmxy); + end + else + begin + bmnx := min (bmnx, pi^.BBlx); + bmny := min (bmny, pi^.BBby); + bmxx := max (bmxx, pi^.BBrx); + bmxy := max (bmxy, pi^.BBty); + end; + pi := pi^.nextitem; + end; (* while *) + (* now transform the items inside, AND the bbox *) + pi := blot^.body^.things; + midx := (bmnx + bmxx) div 2; + midy := (bmny + bmxy) div 2; + (* now take care of any pre and post size requirements *) + (* see also the "figurehandle" proc. *) + with blot^ do + begin +(* ### Keep this scaling biz here, too, for now. May blast it later *) + if ((preWid <> 0) and (preHt <> 0)) then + begin + prescale := scalefitfactor ((bmxx - bmnx), (bmxy - bmny), preWid, preHt); + fsx := fsx * prescale; + fsy := fsy * prescale; + end; + if ((postWid <> 0) and (postHt <> 0)) then + begin + postscale := scalefitfactor ((bmxx - bmnx), (bmxy - bmny), postWid, postHt); + fsx := fsx * postscale; + fsy := fsy * postscale; + end; + +(* the actual scale-up is taken care of later in this proc. *) + end; (* with *) + while (pi <> nil) do + begin + with pi^ do + begin + case (kind) of + Aline : begin + xfmlinepts (lx1, ly1, lx2, ly2, 0, 0, midx, midy, 1.0, + blot^.figtheta, blot^.fdx, blot^.fdy, + blot^.fsx, blot^.fsy); + end; + Aspline : begin + xfmcontpts (spts, nsplknots, 0, 0, midx, midy, 1.0, + blot^.figtheta, blot^.fdx, blot^.fdy, + blot^.fsx, blot^.fsy); + end; + Attspline : begin + xfmcontpts (ttpts, nttknots, 0, 0, midx, midy, 1.0, + blot^.figtheta, blot^.fdx, blot^.fdy, + blot^.fsx, blot^.fsy); + end; + Aarc : begin + null1 := 0; null2 := 0; + old1 := acentx; old2 := acenty; + xfmlinepts (acentx, acenty, null1, null2, 0,0, midx, midy, 1.0, + blot^.figtheta, blot^.fdx, blot^.fdy, + blot^.fsx, blot^.fsy); + xfmcontpts (arcpts, narcknots + 1, 0, 0, old1, old2, 1.0, + blot^.figtheta, + blot^.fdx + (acentx - old1), + blot^.fdy + (acenty - old2), + blot^.fsx, blot^.fsy); + end; + Alabel : begin + null1 := 0; null2 := 0; + xfmlinepts (labx, laby, null1, null2, 0,0, midx, midy, 1.0, + blot^.figtheta, blot^.fdx, blot^.fdy, + blot^.fsx, blot^.fsy); + end; + Abeam : ; (* not transformable *) + + Atieslur: ; (* not transformable *) + Afigure : ; (* do not need to re-transform *) + end; (* case *) + end; (* with *) + pi := pi^.nextitem; + end; (* while *) + (* transform the bbox, and re-find the new bbox *) + newbbox (bmnx, bmxx, bmny, bmxy, midx, midy, blot^.fsx, blot^.fsy, + blot^.figtheta, blot^.fdx, blot^.fdy); + mnx := bmnx; mny := bmny; + mxx := bmxx; mxy := bmxy; + end (* if *) + else (* some other primitive *) + begin + mnx := blot^.BBlx; mny := blot^.BBby; + mxx := blot^.BBrx; mxy := blot^.BBty; + end; (* else *) +end; (* findBBox *) + + +{---------------------------------------------------------} +(* traverse the list, determining the current bounding box for + * the items. We need this to find the mid-point + * for doing any remaining rotations + *) +procedure traverse (thefig, theitem : pItem); +var + minx, maxx, miny, maxy : ScaledPts; + curminx, curmaxx, curminy, curmaxy : ScaledPts; +begin + minx := TWO24; maxx := -TWO24; + miny := TWO24; maxy := -TWO24; + + while (theitem <> nil) do + begin + if (theitem^.kind = Afigure) then + begin (* recur *) + findBBox (theitem, curminx, curmaxx, curminy, curmaxy); + with theitem^ do + begin + BBlx := curminx; BBby := curminy; + BBrx := curmaxx; BBty := curmaxy; + (* reset the symbol's parameters since all the + primitives in it have now been transformed + according to the previous specifications *) + figtheta := 0.0; + fsx := 1.0; fsy := 1.0; + fdx := 0; fdy := 0; + preWid := 0; preHt := 0; + postWid := 0; postHt := 0; + end; (* with *) + minx := min (minx, curminx); miny := min (miny, curminy); + maxx := max (maxx, curmaxx); maxy := max (maxy, curmaxy); + end (* if a figure/symbol*) + else + begin (* a primitive *) + with theitem^ do + begin + minx := min (minx, BBlx); miny := min (miny, BBby); + maxx := max (maxx, BBrx); maxy := max (maxy, BBty); + end; (* with *) + end; (* else *) + theitem := theitem^.nextitem; + end; (* while *) + + with thefig^ do + begin (* set the bounding box for this upper-level symbol defn *) + BBlx := minx; + BBby := miny; + BBrx := maxx; + BBty := maxy; + end; (* with *) +end; (* traverse *) + +(* ----- Figure symbols ----- *) +{---------------------------------------------------} +procedure figurehandle (globalsymlist, symbollist : pItem; dopush : integer); +const DoItNow = -1; + NoScale = 1; +var pi, curfig : pItem; + midx, midy : ScaledPts; + null1, null2 : ScaledPts; + prescale, postscale : real; + tmnx, tmny, tmxx, tmxy : ScaledPts; +begin (* figurehandle *) + + (* PUSH. traverse the lists (recursively if necessary) and + * compute the transformed points. + * Convert to 4th quadrant and offset by H & V. + * We can do this destructively here + * since we're going to output them right away anyhow. + * Then call each respective primitive handler with a level + * of -1 to indicate to do its job immediately. + * POP. + *) + curfig := symbollist; + pi := curfig^.body^.things; + (* find and set the bounding box for + the figure's sub-symbols and primitives *) + if (dopush > 0) then + traverse (curfig, pi); + + (* We eventually transform the items + to 4th Quadrant DVI space and output them! *) + + pi := curfig^.body^.things; + + midy := (globalsymlist^.BBby + globalsymlist^.BBty) div 2; + midx := (globalsymlist^.BBlx + globalsymlist^.BBrx) div 2; + + if (dopush > 0) then + begin (* the top-level figure for outputting *) + + (* convert the bounding box because we are about to enter + into DVI space, and all calls to handlers hereafter + are in terms of DVI coordinates *) + + with globalsymlist^ do + begin + +(* Since there were external specifications about this figure, + fit the current figure's actual size to the + "pre" size (specified by W marker) and/or to the + "post" size (specified by the F marker). + We do this by simple scaling, *without* changing the midpoint + of the bounding box, just its extents + *) + if ((preWid <> 0) and (preHt <> 0)) then + begin + prescale := scalefitfactor ((BBrx - BBlx), (BBty - BBby), preWid, preHt); + fsx := fsx * prescale; + fsy := fsy * prescale; + end; + if ((postWid <> 0) and (postHt <> 0)) then + begin + postscale := scalefitfactor ((BBrx - BBlx), (BBty - BBby), postWid, postHt); + fsx := fsx * postscale; + fsy := fsy * postscale; + end; + tmnx := BBlx; tmny := BBby; tmxx := BBrx; tmxy := BBty; + xfmlinepts (tmnx, tmny, tmxx, tmxy, 0,0, midx, midy, 1.0, + 0.0, 0, 0, fsx, fsy); + + toplevelxfm (globalsymlist, globalsymlist, 0); + + dviBBlx := tmnx; + dviBBrx := tmxx; + dviBBby := tmny; + dviBBty := tmxy; + + xfmlinepts (dviBBlx, dviBBby, dviBBrx, dviBBty, 0,0, + midx, midy, 1.0, 0.0, + - (tmnx - BBlx), - (tmny - BBby), + 1.0, 1.0); + + fdx := fdx - (tmnx - BBlx); + fdy := fdy - (tmny - BBby); + end; + + dvilinepts (dviBBlx, dviBBby, dviBBrx, dviBBty, h, v); + pgfigurenum := pgfigurenum + 1; + + (* We are ready to output the figure to the page *) + writeln(logfile); + write(logfile,'Figure #',pgfigurenum:0,' on page ',currpagenum:0,' is approx. '); +{ write(logfile,((globalsymlist^.BBty - globalsymlist^.BBby) div SPPERPT):0,' pts high and '); + writeln(logfile,((globalsymlist^.BBrx - globalsymlist^.BBlx) div SPPERPT):0,' pts wide (actual size)'); +} + write(logfile,((tmxy - tmny) div SPPERPT):0,' pts high and '); + writeln(logfile,((tmxx - tmnx) div SPPERPT):0,' pts wide (actual size)'); + IPUSH; + + end; + + while (pi <> nil) do + begin + with pi^ do + begin + case (kind) of + Aline : begin + dvilinepts (lx1, ly1, lx2, ly2, h, v); (* DVI h and v posit *) + with globalsymlist^ do + linehandle (DoItNow, NoScale, + pi^.lx1, pi^.ly1, pi^.lx2, pi^.ly2, + 0, 0, + pi^.itemthick, pi^.itemvec, pi^.itempatt, + dviBBlx, dviBBrx, dviBBby, dviBBty, + fdx, -fdy, fsx, fsy, -figtheta); + end; (* Aline *) + + Aspline : begin + dvicontpts (spts, nsplknots, h, v); + with globalsymlist^ do + splinehandle (DoItNow, NoScale, pi^.spltype, + pi^.sclosed, pi^.dosmarks, + pi^.spts, pi^.nsplknots, + 0, 0, + pi^.itemthick, pi^.itemvec, pi^.itempatt, + dviBBlx, dviBBrx, dviBBby, dviBBty, + fdx, -fdy, fsx, fsy, -figtheta); + end; (* Aspline *) + + Attspline : begin + dvicontpts (ttpts, nttknots, h, v); + with globalsymlist^ do + ttsplhandle (DoItNow, NoScale, pi^.tspltype, + pi^.tclosed, pi^.dottmarks, + pi^.ttpts, pi^.ttarry, pi^.nttknots, + 0, 0, + pi^.itemvec, pi^.itempatt, + dviBBlx, dviBBrx, dviBBby, dviBBty, + fdx, -fdy, fsx, fsy, -figtheta); + end; (* Attspline *) + + Abeam : begin + dvilinepts (bx1, by1, bx2, by2, h, v); + beamhandle (DoItNow, staf, bkind, bx1, by1, bx2, by2); + end; (* Abeam *) + + Atieslur : begin + dvicontpts (tspts, ntknots, h, v); + tieslurhandle (DoItNow, tspts, ntknots, minth, maxth); + end; (* a tie or slur *) + + Aarc : begin + dvicontpts (arcpts, narcknots + 1, h, v); + with globalsymlist^ do + arccirclehandle (DoItNow, NoScale, + pi^.acentx, pi^.acenty, + pi^.aradius, + pi^.firstang, pi^.lastang, + pi^.arcpts, pi^.narcknots, + 0, 0, + pi^.itemthick, pi^.itemvec, pi^.itempatt, + dviBBlx, dviBBrx, dviBBby, dviBBty, + fdx, -fdy, fsx, fsy, -figtheta); + end; (* arc *) + Alabel : begin + null1 := 0; null2 := 0; + dvilinepts (labx, laby, null1, null2, h, v); + with globalsymlist^ do + labelhandle (DoItNow, NoScale, + pi^.labx, pi^.laby, + 0, 0, + pi^.fontstyle, pi^.labeltext, + fdx, -fdy); + end; (* label *) + + Afigure : begin (* recur *) + figurehandle (globalsymlist, pi, 0); + end; (* another symbol *) + + end; (* case *) + end; (* with *) + pi := pi^.nextitem; + end; (* while *) + if (dopush > 0) then + begin + IPOP; + end; +end; (* figurehandle *) + + + +(* %%% *) +{-----------------------------------------------------} +procedure mainhandlespecials (specnum, numpbytes : integer); +(* specnum is the DVI-number of the special + * numpbytes is the number of parameter bytes + *) +label 888; +const PARSLEN = 50; (* Length of the byte-string-cache *) + EMPTY = 0; +type charset = set of char; +var siz, numknots : integer; (* Lots of temp vars that we use *) + x1, y1, x2, y2 : integer; + sx100, sy100 : real; + transx, transy : ScaledPts; + rot : real; + SPscale : real; + cpts : ControlPoints; + thk : VThickness; + patt : LineStyle; + TTary : ThickAryType; + vk : VectKind; + bk : BeamKind; + markdiam : integer; + radius, ang1, ang2 : integer; + phrase : strng; + style : integer; + nam : strng; + sysnam : strng; (* the first parameter of the \special *) + let : char; + i, gotten : integer; + b : OctByt; + pi : pItem; + minx, miny, maxx, maxy : ScaledPts; + maxthk, minthk : integer; + + tylnam, + beginfigurenam, (* names used for string to string comparisons *) + endfigurenam, + linenam, + splinenam, + ttsplnam, + beamnam, + tieslurnam, + arcnam, + labelnam, + paramnam {internal} : charstring; + + splinetype : SplineKind; + isclosedspline : boolean; + + parsearray : array [1..PARSLEN] of OctByt; (* cache of bytes to run through *) + parsposit, parsmax : integer; (* current and max position in cache *) + usingstream : boolean; (* whether we read/parse using cache or from file *) + + +(*-------------------------------------------------------------- + These procedures depend on the correct ordering of + GETs with respect to the number of bytes read in so far. + precond: byte "b" has been read and gotten < numpbytes + postcond: byte "b" has been read iff gotten < numpbytes. + If your impl. definition of READ is non-standard, you will + have to dink with the ordering and be really careful of + keeping track of 'gotten' and 'numpbytes' variables +--------------------------------------------------------------*) + + function nextpbyte : integer; + begin + if (usingstream) then + begin + if (gotten < numpbytes) then + begin + nextpbyte := Dget1byte; + gotten := gotten + 1; + end + else + nextpbyte := EMPTY; + end + else + begin (* not using stream *) + if (parsposit <= parsmax) then + begin + nextpbyte := parsearray[parsposit]; + parsposit := parsposit + 1; + end + else + begin (* at end of parse array, so read from stream now *) + usingstream := true; + if (gotten < numpbytes) then + begin + nextpbyte := Dget1byte; + gotten := gotten + 1; + end + else + nextpbyte := EMPTY; + end; + end; (* else *) + end; + +(* !!!!! Make sure all these predicates jive correctly with + the key-letter definitions *) +{__________________________________________________________________} + function isanumber (b : integer) : boolean; + begin + isanumber := ((b >= xord['0']) and (b <= xord['9'])); + end; + + function isaletter (b : integer) : boolean; + begin + isaletter := (((b >= xord['A']) and (b <= xord['Z'])) or + ((b >= xord['a']) and (b <= xord['z'])) or + (b = xord['@']) or + (b = xord['"']) ); + end; + + function isaspace (b : integer) : boolean; + begin + isaspace := ((b = xord[' ']) or + (b = CR) or + (b = LF) or + (b = HT) or + (b = FF)); + end; + + function isdelimiter (b : integer) : boolean; + begin + (* not a key-letter *) + isdelimiter := (((b < xord['A']) or (b > xord['Z'])) and + ((b < xord['a']) or (b > xord['z'])) and + (b <> xord['@']) and + (b <> xord['"']) ); + end; + + function isnotnull (b : integer) : boolean; + begin + isnotnull := (b <> EMPTY); + end; + + +{__________________________________________________________________} + function getnumber : integer; + var n : integer; + isneg : boolean; + begin + n := 0; + isneg := false; + while ( (isnotnull (b)) and + (not (isanumber (b)))) do + begin (* not a numeral *) + if (b = xord['-']) then + isneg := true; + b := nextpbyte; + end; + + while (isaspace (b)) do (* Skip spaces *) + b := nextpbyte; + + while ( (isnotnull (b)) and + isanumber (b)) do + begin (* a numeral *) + n := n * 10 + (b - xord['0']); + b := nextpbyte; + end; + + if ((gotten = numpbytes) and + isanumber (b)) then + begin (* end condition *) + n := n * 10 + (b - xord['0']); + end; + + if (isneg) then + getnumber := -(n) + else + getnumber := n; + end; +{__________________________________________________________________} + + function getletter : char; + var k : char; + begin + k := ' '; + while ( (isnotnull (b)) and + (isdelimiter (b) and not (isaspace (b)))) do + begin (* non letter *) + b := nextpbyte; + end; + + if ( (isnotnull (b)) and + ( isaletter (b) or isaspace (b) + and not (isanumber (b)))) then + begin + k := xchr[b]; + b := nextpbyte; + end; + getletter := k; + end; +{__________________________________________________________________} + + function getanything : char; + var k : char; + begin + k := ' '; + while (not (isnotnull (b))) do + begin (* not usable *) + b := nextpbyte; + end; + + if (isnotnull (b)) then + begin + k := xchr[b]; + b := nextpbyte; + end; + getanything := k; + end; + +{**************************************************** + The following routines look for key - letter tokens + that indicate certain attributes for a primitive. + +Currently, the letters used are: + S for scaled-points measurement + P for printers points + M millimeters measurement + C use a Circular vector for drawing + H Horizontal-pen vector + V Vertical vector + B B-spline + I Interpolating B-spline + K Catmull-Rom spline + D Cardinal spline + U Open spline + O closed spline + X put marks on spline control pts + T Transformation marker + R Regular beam characters + G Grace Beam characters + @ Specify center-point for arc/circle + L Line-style + F for beginfigure: Fit figure to wid/ht + W for beginfigure: figure was created at this wid & ht +**************************************************} + + +{__________________________________________________________________} diff --git a/macros/latex209/contrib/textyl/psrc/textyl.pas.af b/macros/latex209/contrib/textyl/psrc/textyl.pas.af new file mode 100644 index 0000000000..76ecf19c0a --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/textyl.pas.af @@ -0,0 +1,1000 @@ + procedure gettransforms (var sc1, sc2, r : real; + var tr1, tr2 : integer); + label 22; + var i : integer; + dun : boolean; + begin + sc1 := 1.0; sc2 := 1.0; + tr1 := 0; tr2 := 0; + r := 0.0; + i := parsposit - 1; + if (i < 1) then + begin + goto 22; (* exit with defaults *) + end; + dun := false; + while ((i < parsmax) and not dun) do + begin + if (isaletter(parsearray[i])) then + begin + if ((parsearray[i] = xord['t']) or + (parsearray[i] = xord['T'])) then + begin + if (isdelimiter(parsearray[i+1]) and + isdelimiter(parsearray[i-1])) then + begin (* get transform parameters *) + sc1 := getnumber / 100.0; + sc2 := getnumber / 100.0; + tr1 := getnumber; + tr2 := getnumber; + r := float(getnumber); (* degrees about primitive center *) + if (r < 0.0) then + r := r + 360.0; + dun := true; + end; + end; + end; + i := i + 1; + end; (* while *) +22: + end; (* gettransforms *) + +{__________________________________________________________________} + function findmarker (markset : charset) : integer; + label 1111; + var i, sym : integer; + dun : boolean; + begin + i := parsposit - 1; + sym := EMPTY; + if (i < 1) then + goto 1111; + dun := false; + while ((i < parsmax) and not dun) do + begin + if (isaletter(parsearray[i])) then + begin + if (xchr[ parsearray[i] ] in markset) then + begin + if (isdelimiter (parsearray[i+1]) and + isdelimiter (parsearray[i-1])) then + begin + sym := xord[tolowercase(xchr[parsearray[i]])]; + dun := true; + end; + end; + end; (* if a letter *) + i := i + 1; + end; (* while *) +1111: findmarker := sym; + end; + + + + function findscale : integer; + begin + findscale := findmarker(['s','S','p','P','m','M']); + end; + + function findvectkind : integer; + begin + findvectkind := findmarker(['c','C','h','H','v','V']); + end; + + function findlinestyle : integer; + begin + findlinestyle := findmarker(['l','L']); + end; + + function findbeamkind : integer; + begin + findbeamkind := findmarker(['r','R','g','G']); + end; + + function findsplinekind : integer; + begin + findsplinekind := findmarker(['b','B','i','I','k','K','d','D']); + end; + + function findsplclosure : integer; + begin + findsplclosure := findmarker(['o','O','u','U']); + end; + + function findatsign : integer; + begin + findatsign := findmarker(['@']); + end; + + function finddotmark : integer; + begin + finddotmark := findmarker(['x','X']); + end; + + function findfigdimens : integer; + begin + findfigdimens := findmarker(['w','W']); + end; + + function findfitsizes : integer; + begin + findfitsizes := findmarker(['f','F']); + end; + + + {_________________________________________________} + function thescaleof (scal : integer) : real; + begin + if (scal = xord['s']) then + thescaleof := 1 * magfactor + else if (scal = xord['p']) then + thescaleof := SPPERPT * magfactor + else if (scal = xord['m']) then + thescaleof := SPPERMM * magfactor + else if (scal = EMPTY) then + thescaleof := SPPERPT * magfactor; + end; + + + function thevectorof (vkin : integer) : VectKind; + begin + if (vkin = xord['c']) then + thevectorof := VKCirc + else if (vkin = xord['v']) then + thevectorof := VKVert + else if (vkin = xord['h']) then + thevectorof := VKHort + else if (vkin = EMPTY) then + thevectorof := VKCirc; + end; + + function thestyleof (linest : integer) : LineStyle; + begin + if ((linest > 3) or + (linest < 0)) then linest := 0; + case linest of + 0 : thestyleof := solid; + 1 : thestyleof := dotted; + 2 : thestyleof := dashed; + 3 : thestyleof := dotdash; + end; + end; + + + + +(* -----!!!!!!!!!!!! HandleSpecials !!!!!!!!!!!!!------ *) +begin + tylnam := 'tyl'; + beginfigurenam := 'beginfigure'; + endfigurenam := 'endfigure'; + linenam := 'line'; + splinenam := 'spline'; + ttsplnam := 'ttspline'; + beamnam := 'beam'; + tieslurnam := 'tieslur'; + arcnam := 'arc'; + labelnam := 'label'; + paramnam := 'param'; + usingstream := true; (* getting bytes from dvifile *) + + specstart := DVIMark - (specnum - 239 + 1) - 1; + + ourxpos := h; ourypos := v; (* note the global DVI (h,v) coords *) + i := 1; + + b := Dget1byte; (* prime the reading scheme *) + gotten := (specnum - 239 + 1); + + while (isaspace(b)) do + b := nextpbyte; + + let := getletter; + while (let <> ' ') do (* get the name of the system --- Hopefully 'tyl' *) + begin + sysnam.str[i] := tolowercase(let); + sysnam.len := i; + i := i + 1; + let := getletter; + end; + + sysnam.str[i] := chr(32); (* end of string *) + + if (not streq (sysnam.str, tylnam, 3)) then (* TeXtyl doesnt know about this special *) + begin + write (logfile,'The special: '); + writestrng(sysnam,true); + writeln(logfile,' is not tyl-able. Skipping...'); + while (gotten < numpbytes) do + b := nextpbyte; + goto 888; + end; + +(* OTHERWISE: all is okay. Lets look for a primitive to tyl *) + + while (isdelimiter(b)) do + begin + b := nextpbyte; + end; + i := 1; + let := getletter; {xchr[b];} + while (not (isdelimiter(xord[let]))) do (* get the name of the primitive *) + begin + nam.str[i] := tolowercase(let); + nam.len := i; + i := i + 1; + let := getletter; + end; + + nam.str[i] := chr(32); (* end of string *) + + + let := xchr[b]; + +(* Now, fill the parse array with bytes so that we can get + the given parameters, and infer the defaulted params *) + + parsmax := min (PARSLEN, ((numpbytes - gotten) + 1)); + + if (parsmax > 1) then + begin + parsearray[1] := xord[' ']; (* we need this *) + parsearray[2] := b; (* start filling *) + for i := 3 to parsmax do + begin (* fill rest *) + parsearray[i] := nextpbyte; + end; + parsposit := 1; + usingstream := false; (* now we look at bytes in parse array *) + b := nextpbyte; (* start it *) + end + else + begin + usingstream := true; + parsposit := -1; (* undefined *) + end; + + (* --- BEGINFIGURE ---- *) + if streq(nam.str, beginfigurenam, 3) then + begin + multifigure := multifigure + 1; + i := findscale; + SPscale := thescaleof (i); + + gettransforms (sx100, sy100, rot, transx, transy); + (* store all the primitives on pageitems, and dont output + them until we get a endfigure. this way, we can take + care of dealing with all the primitives according to + some global tranformation for the whole figure *) + pi := NewItem (Afigure); + with pi^ do + begin + figtheta := rot; + fsx := sx100; fsy := sy100; + fdx := round (transx * SPscale); + fdy := round (transy * SPscale); + depthnumber := multifigure; (* we're at a new level *) + i := findfigdimens; + if (i <> EMPTY) then + begin + preWid := round (getnumber * SPscale); + preHt := round (getnumber * SPscale); + end; + i := findfitsizes; + if (i <> EMPTY) then + begin + postWid := round (getnumber * SPscale); + postHt := round (getnumber * SPscale); + end; + end; (* with *) + BackupInBuf (DVIMark - specstart); + pushItem (multifigure - 1, pi); + goto 888; + end; + (* ---- ENDFIGURE ---- *) + if streq(nam.str, endfigurenam, 3) then + begin + multifigure := multifigure - 1; + if (multifigure < 0) then + begin + complain (ERRBAD); + write(logfile,'Warning: Too many "endfigure"s !'); + multifigure := 0; + end; + BackupInBuf (DVIMark - specstart); + + if (multifigure = 0) then + begin + (* go do our set of figures (within figures...) *) + figurehandle (pageitems, pageitems, 1); + dispose (pageitems); (* ### should maybe garbage collect here *) + pageitems := nil; + end; (* if *) + goto 888; + end; + + (* --- LINE --- *) + if streq(nam.str, linenam, 3) then + begin + i := findscale; + SPscale := thescaleof(i); + + gettransforms (sx100, sy100, rot, transx, transy); + thk := getnumber; (* get the vector thickness *) + if (thk < 1) then + begin + complain (ERRBAD); + writeln(logfile,'?? Thickness not found. Setting to 1'); + thk := 1; + end; + i := findvectkind; + vk := thevectorof (i); + + i := findlinestyle; + if (i <> EMPTY) then + patt := thestyleof (getnumber) + else + patt := solid; + + x1 := round (getnumber * SPscale); + y1 := round (getnumber * SPscale); + x2 := round (getnumber * SPscale); + y2 := round (getnumber * SPscale); + + minx := min (x1, x2); + maxx := max (x1, x2); + miny := min (y1, y2); + maxy := max (y1, y2); + + BackupInBuf (DVIMark - (specstart)); + cmd1byte (OURFONTFLAG); + linehandle (multifigure, SPscale, x1, y1, x2, y2, 0, 0, thk, vk, patt, + minx, maxx, miny, maxy, + transx, transy, sx100, sy100, rot); + end (* line *) + (* ---- THE SPLINES ---- *) +else if (streq(nam.str, splinenam, 3) or + streq(nam.str, ttsplnam,3)) then + begin + i := findscale; + SPscale := thescaleof (i); + + gettransforms (sx100, sy100, rot, transx, transy); + + if streq(nam.str, splinenam, 3) then + begin + thk := getnumber; + if (thk < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Spline Thickness not found. Setting to 1'); + thk := 1; + end; + end; + i := findvectkind; + vk := thevectorof (i); + + i := findlinestyle; + if (i <> EMPTY) then + patt := thestyleof (getnumber) + else + patt := solid; + + i := findsplinekind; + if (i = xord['b']) then + splinetype := BSPL + else if (i = xord['i']) then + splinetype := INTBSPL + else if (i = xord['k']) then + splinetype := CATROM + else if (i = xord['d']) then + splinetype := CARD + else if (i = EMPTY) then + splinetype := CATROM; + + i := findsplclosure; + if (i = xord['o']) then + isclosedspline := true + else if (i = xord['u']) then + isclosedspline := false + else if (i = EMPTY) then + isclosedspline := false; + + i := finddotmark; + if (i = xord['x']) then + markdiam := getnumber + else if (i = EMPTY) then + markdiam := 0; + + numknots := min (getnumber, MAXCTLPTS); + if (numknots < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Number of spline/ttspline knot points not found. Setting to 1'); + numknots := 1; + end; + + minx := TWO24; miny := TWO24; + maxx := -TWO24; maxy := -TWO24; + + for i := 0 to (numknots + 3) do + begin + cpts[i,1] := 0; + cpts[i,2] := 0; + end; (* for *) + + for i := 1 to numknots do + begin + x1 := round (getnumber * SPscale); + cpts[i,1] := x1; + if (x1 < minx) then + minx := x1; + if (x1 > maxx) then + maxx := x1; + y1 := round (getnumber * SPscale); + cpts[i,2] := y1; + if (y1 < miny) then + miny := y1; + if (y1 > maxy) then + maxy := y1; + end; (* for *) + + if streq(nam.str, ttsplnam, 3) then + begin + for i := 1 to numknots do + begin + TTary[i] := getnumber; + end; + end; + + BackupInBuf (DVIMark - (specstart)); + cmd1byte (OURFONTFLAG); + + if streq(nam.str, splinenam, 3) then + splinehandle (multifigure, SPscale, splinetype, isclosedspline, + markdiam, cpts, numknots, + 0, 0, thk, vk, patt, minx, maxx, miny, maxy, + transx, transy, sx100, sy100, rot) + else + ttsplhandle (multifigure, SPscale, splinetype, isclosedspline, + markdiam, cpts, TTary, numknots, + 0, 0, vk, patt, minx, maxx, miny, maxy, + transx, transy, sx100, sy100, rot); + end (* splines *) + (* --- BEAMS ---- *) + else if streq(nam.str, beamnam, 4) then + begin + i := findscale; + SPscale := thescaleof (i); + + (* no transforms *) + + siz := getnumber; (* the staffsize *) + i := findbeamkind; + if (i = xord['g']) then + bk := grace + else if (i = xord['r']) then + bk := regular + else if (i = EMPTY) then + bk := regular; + + x1 := round (getnumber * SPscale); + y1 := round (getnumber * SPscale); + x2 := round (getnumber * SPscale); + y2 := round (getnumber * SPscale); + + BackupInBuf (DVIMark - (specstart)); + cmd1byte (OURFONTFLAG); + + beamhandle (multifigure, siz, bk, x1, y1, x2, y2); + end (* beam *) + (* ---- TIES AND SLURS ---- *) + else if streq(nam.str, tieslurnam, 3) then + begin + i := findscale; + SPscale := thescaleof (i); + + minthk := getnumber; + if (minthk < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Tie/Slur Min Thickness not found. Setting to 1'); + minthk := 1; + end; + + maxthk := getnumber; + if (maxthk < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Tie/Slur MaxThickness not found. Setting to 1'); + maxthk := 1; + end; + + numknots := min (getnumber, MAXCTLPTS); + if (numknots < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Tie/Slur Number of knot points not found. Setting to 1. Should be 5'); + numknots := 1; + end; + for i := 1 to numknots do + begin + cpts[i,1] := round (getnumber * SPscale); + cpts[i,2] := round (getnumber * SPscale); + end; (* for *) + BackupInBuf (DVIMark - (specstart)); + cmd1byte (OURFONTFLAG); + + tieslurhandle (multifigure, cpts, numknots, minthk, maxthk); + end (* ties and slurs *) + (* --------- ARCS and CIRCLES --------- *) + else if streq (nam.str, arcnam, 3) then + begin + i := findscale; + SPscale := thescaleof (i); + + gettransforms (sx100, sy100, rot, transx, transy); + + thk := getnumber; + if (thk < 1) then + begin + complain (ERRBAD); + writeln(logfile,'Arc Thickness not found. Setting to 1'); + thk := 1; + end; + i := findvectkind; + vk := thevectorof (i); + + i := findlinestyle; + if (i <> EMPTY) then + patt := thestyleof (getnumber) + else + patt := solid; + + radius := round (getnumber * SPscale); + if (radius = 0) then + radius := round(1 * SPscale); + i := findatsign; + if (i <> EMPTY) then + begin + x2 := round (getnumber * SPscale); + y2 := round (getnumber * SPscale); + end + else + begin + x2 := 0; y2 := 0; (* assume center at origin *) + end; + + ang1 := getnumber; + if (abs(ang1) > 360) then + ang1 := ang1 mod 360; + ang2 := getnumber; + if (abs(ang2) > 360) then + ang2 := ang2 mod 360; + + minx := TWO24; miny := TWO24; + maxx := -TWO24; maxy := -TWO24; + + if (ang1 = ang2) then + begin (* a circle *) + defineCircleCpts (radius,x2,y2, cpts, numknots); + end + else + begin (* a real arc *) + definearcpts (radius, x2,y2, ang1, ang2, cpts, numknots); + end; + + for i := 1 to numknots do + begin + x1 := cpts[i,1]; + if (x1 < minx) then + minx := x1; + if (x1 > maxx) then + maxx := x1; + + y1 := cpts[i,2]; + if (y1 < miny) then + miny := y1; + if (y1 > maxy) then + maxy := y1; + end; (* for *) + + BackupInBuf (DVIMark - (specstart)); + cmd1byte (OURFONTFLAG); + + arccirclehandle (multifigure, SPscale, x2, y2, + radius, ang1, ang2, + cpts, numknots, + 0, 0, thk, vk, patt, minx, maxx, miny, maxy, + transx, transy, sx100, sy100, rot) + + end (* arc and circle *) + (* ---------- LABELS --------------*) + else if streq (nam.str, labelnam, 3) then + begin + i := findscale; + SPscale := thescaleof (i); + + style := getnumber; (* font style number *) + if ((style < 1) or (style > MAXLABELFONTS)) then + begin + complain (ERRBAD); + writeln(logfile,'Label style bad? Setting to Style 1'); + style := 1; + end; + + x1 := round (getnumber * SPscale); + y1 := round (getnumber * SPscale); + + let := getletter; + while (let <> '"') do + begin + let := getletter; + end; + i := 0; + let := getanything; (* get next letter or whatever *) + while (let <> '"') do + begin (* get the label phrase *) + i := i + 1; + phrase.str[i] := let; + let := getanything; (* getletter;*) + end; + + phrase.str[i+1] := chr(32); + + phrase.len := i; + + BackupInBuf (DVIMark - specstart); + cmd1byte (OURFONTFLAG); + labelhandle (multifigure, SPscale, x1, y1, 0, 0, style, phrase, 0, 0); + end (* label *) + + (* --------- INTERNAL PARAM -------*) + else if streq (nam.str, paramnam, 3) then + begin + i := getnumber; (* addressable param number *) + + begin + writeln (logfile,' I do not know what internal parameter #',i:0,' is'); + end; (* else *) + BackupInBuf (DVIMark - (specstart)); + end (* Internal param *) + + (* ============== NONE OF THE ABOVE ============== *) + else + begin + complain (ERRNOTBAD); + write (logfile,'Sorry, I don''t know how to tyl '); + writestrng (nam,true); + + while (gotten < numpbytes) do + begin + b := nextpbyte; + end; + end; + 888: + (* make sure that we used up all the bytes in this special *) + if (gotten < numpbytes) then + begin + while (gotten < numpbytes) do + begin (* slurp up excess *) + b := Dgrabbyte; + gotten := gotten + 1; + end; + end; (* if *) + end; (* mainhandlespecials *) + + + (* ================================================== + + The routines below assume coordinates are already in + 4th Quadrant DVI-space + + =====================================================*) + + + + {-----------------------------------------------------} + (* returns 0 if dy.dx not in font + 1 if ok + 2 if ok and caller should use two of the "code"s + coding scheme requires 0<= [dx, dy] <= 16 + AND that max(dx, abs(dy)) is in [0,1,2,4,8,16] + *) +function outvector (dx, dy : integer; var code : integer) : integer; + label 99; + var c : integer; + result : integer; + begin + if (dx < 0) then + begin + outvector := 0; + goto 99; + end; + + result := 0; (* init for potential failure *) + code := (-1); + if (dy < 0) then + begin + c := 160 + dy + dx - 9*max (dx, -dy); + end + else + begin + c := 160 + dy - dx - 7*max (dx, dy); + end; + + (* here translate to OUR coding scheme + and return the correct number + this is needed because "c" thinks the char range + is 0 to 160, while we have only 128 chars *) + + if (c = 0) then (* special cases *) + begin + code := 63; + result := 2; + end + else if (c = 64) then + begin + code := 95; + result := 2; + end + else + begin (* regular ones *) + result := 1; (* just one char is fine *) + if (c in [1..63]) then + code := c - 1 + else if (c in [80..112]) then + code := c - 17 + else if (c in [120..136]) then + code := c - 24 + else if (c in [140..148]) then + code := c - 27 + else if (c in [150..154]) then + code := c - 28 + else if (c = 160) then + code := 127; (* c - 33 *) + end; + 99: + outvector := result; + end; + + + + (* take care of a Manhattan (horizontal /vertical) line *) + {----------------------------------------------------------} +procedure hvline (lx, by, rx, ty, fontindex : integer); + var t, rth, x, y, width, height : integer; + begin + rth := VFontTable[fontindex]^.PenSize; (* thickness of vector in sp *) + if (lx = rx) then + begin (* Vertical line *) + if (ty > by) then + begin + t := by; by := ty; ty := t; (* swap *) + end; + x := round (lx - (rth / 2.0)); + y := by; + width := rth; + height := by - ty; + end + else + begin (* Horizontal line *) + if (ty < by) then + begin + t := by; by := ty; ty := t; (* swap *) + end; + if (lx > rx) then + begin + t := lx; lx := rx; rx := t; (* swap *) + end; + x := lx; + + y := (by + (rth div 2)); (* + rth for {h,v}-space *) + width := rx - lx; + height := rth; + end; + + isetpos (x, y); + cmd1byte (PUTRULE); + cmd4byte (height); + cmd4byte (width); + + (* output two dots on ends of the rules + at lx, by and rx, ty *) + (* the font has already been set before these calls *) + Tyldot (lx, by); + Tyldot (rx, ty); + isetpos (rx, ty); + end; + + + {------------------------------------------------------------} +procedure diagonal (xl, yb, xr, yt : ScaledPts; fontindex: integer); + var t, curx, cury, dx, dy, code : integer; + slope : real; + mxveclen : ScaledPts; + sptovecs : real; + rho : ScaledPts; + + {......................................} + (* compute maximum length vector character that we can use *) + + procedure getincr (var outdx, outdy : integer); + label 99; + var radius, x, y : integer; + sign : integer; + q : real; + + begin (* getincr *) + radius := mxveclen; (* radius of semi-square *) + (* make sure the pt is outside of the semi-square, + scaling down radius if necessary *) + while ( ((xr - curx) < radius) and + (abs (yt - cury) < radius)) do + begin + radius := radius div 2; + end; + if (slope < 0.0) then (* <0 since in 4th quad by now*) + sign := -1 + else + sign := +1; + if (xr = curx) then + begin + outdx := 0; + outdy := sign * radius; + goto 99; + end; + if (yt = cury) then + begin + outdx := abs (radius); + outdy := 0; + goto 99; + end; + + (* compute the intersection with the semi-square, + choose whichever slope is best *) + if (abs (slope) < 1.0) then + begin (* mostly horizontal *) + outdx := abs (radius); + y := yb + round ((curx + abs(radius) - xl) * slope); + outdy := y - cury; + end + else + begin (* mostly vertical *) + x := xl + round ((cury + (sign * radius) - yb) / slope); + outdx := x - curx; + outdy := sign * radius; + end; + + if (abs (outdy) > abs (yt - cury)) then + begin (* truncate *) + outdy := yt - cury; + end; + if (outdx > (xr - curx)) then + begin (* truncate *) + outdx := xr - curx; + end; + if (outdx < 0) then + begin + outdx := 0; + end; + + (* method to find the exact intersection of the line segment + with the semi-circle, used + to determine the x and y values:: + we do this by using the arctangent of the slope as + the angle 'a' from the x-axis. Then use the relation + y = r cos a, and x = r sin a + we can be smart about all this trig stuff by using + the relation : + sin (arctan a) = 1/sqrt(1 + a^2) + cos (arctan a) = a/sqrt(1 + a^2) + Thus: + q := (1.0 / sqrt (slope * slope + 1.0)); + outdx := round (q * radius); + outdy := round (q * radius * slope); + + Unfortunately, we cannot access the Vector Font + coding scheme because the outdx, outdy 's produced + here do no conform to the condition + max (dx, abs(dy)) in [0,1,2,4,8,16] + when converted to vector-font sizes with + sptovecs (see the 'diagonal' proc.). + *) + + 99: + end; (* getincr *) + {.......................................} + + begin (* DIAGONAL *) + if (xr <> xl) then + slope := (yt - yb) / (xr - xl) + else + slope := BIGREAL; (* some illegal value *) + + if (xl > xr) then + begin + t := xl; xl := xr; xr := t; + t := yb; yb := yt; yt := t; + end; (* swap *) + + curx := xl; + cury := yb; + mxveclen := (VFontTable[fontindex]^.MaxVectLen); + rho := mxveclen div 16; (* minimum radius of vector fonts *) + if (rho = 0) then + begin + complain (ERRREALBAD); + writeln(logfile,'Diagonal: Min radius of vector font is zero. setting to 1'); + rho := 1; + end; + + if ((abs(xl - xr) <= rho) and + (abs(yb - yt) <= rho)) then + begin (* pretty much a null line *) + Tyldot (xl, yb); + end + else + begin + sptovecs := 1.0 / rho; (* conversion for scaled pts to vectorfont units *) + + code := -1; (* initialize to a bogus number *) + + (* this conditional really has to have "or" + instead of "and", because of lines that are + *nearly* horizontal or vertical + *) + while (((xr - curx) >= rho) or (abs(yt - cury) >= rho)) do + begin + (* Get the approximate incremental amount. We use this dy/dx + pair in order to index into our vector font coding scheme *) + + getincr (dx, dy); + + (* Get the vector character code corresponding to this + approximate incremental amount *) + t := outvector (round (dx * sptovecs), + round (dy * sptovecs), + code); + (* Now that we have the character code, go find out its actual + physical dimensions for the real dy/dx amounts *) + if (dy > 0) then + dy := VFontTable[fontindex]^.FontInfo[code].Cdp + else + dy := -(VFontTable[fontindex]^.FontInfo[code].Cht); + + dx := VFontTable[fontindex]^.FontInfo[code].Cwd; + + case (t) of + 0: begin + complain (ERRREALBAD); + writeln (logfile,'Error in Diagonal:: bad dydx'); + end; + + 1: begin + isetpos (curx, cury); + iputchar (code); + end; + + 2: begin + isetpos (curx, cury); + iputchar (code); + isetpos (curx + (dx div 2), cury + (dy div 2)); + iputchar (code); + end; + end; (* case *) + + curx := curx + dx; + cury := cury + dy; + end; (* while *) + + if ((code >= 0) and + (((xr - curx) >= rho) and (abs(yt - cury) >= rho))) then + begin + iputchar (code); + end; + end; (* not null line *) + end; + + +{-------------------------------------------------------} diff --git a/macros/latex209/contrib/textyl/psrc/textyl.pas.ag b/macros/latex209/contrib/textyl/psrc/textyl.pas.ag new file mode 100644 index 0000000000..1a6d2731ef --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/textyl.pas.ag @@ -0,0 +1,1000 @@ +procedure tylBrokenLine (x0, y0, x1, y1, fontindex : integer; + line_type: LineStyle); +label 10; +var useXaxis: boolean; + a0, b0, a1, b1: integer; + a2, a3, b2, b3, K, gap, dot, dash: integer; + s, z, fit: real; + J, frame, T: integer; + Dotgap, Dotdot: integer; + Dashgap, Dashdash: integer; + DDotgap, DDotdot, DDotdash: integer; + a1ma0 : integer; + +{.........................................................} + procedure spread (lt : LineStyle; extra, T : integer); + label 20; + begin + if (T = 0) then + begin { only partial frame fits } + if (useXaxis) then + diagonal (a0, b0, a1, b1, fontindex) + else + diagonal (b0, a0, b1, a1, fontindex); + goto 20; { exit } + end; + J := 0; + s := float (b1 - b0)/float(a1 - a0); + z := float (extra)/float(T); + case lt of + dotted : repeat a2 := a0 + J*frame; + if (extra > 0) then a2 := a2 + round(J*z); + a3 := a2 + dot; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + end; + J := J + 1; + until (a3 >= a1); + dashed : repeat a2 := a0 + J*frame; + if (extra > 0) then a2 := a2 + round(J*z); + a3 := a2 + dash; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + end; + J := J + 1; + until (a3 >= a1); + dotdash : repeat a2 := a0 + J*frame; + if (extra > 0) then a2 := a2 + round(J*z); + a3 := a2 + dash; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + a2 := a3 + gap; + if (extra > 0) then a2 := a2 + round(z*0.5); + a3 := a2 + dot; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + end; + end; + J := J + 1; + until (a3 >= a1); + end; + 20: + end; { spread } + +{......................................................} + procedure balance (lt : LineStyle; extra, T : integer); + label 30; + begin + if (T = 0) then + begin { only partial frame fits } + if (useXaxis) then + diagonal (a0, b0, a1, b1, fontindex) + else + diagonal (b0, a0, b1, a1, fontindex); + goto 30; { exit } + end; + J := 0; + s := float(b1 - b0)/float(a1 - a0); + case lt of + dashed : repeat a2 := a0 + J*frame - extra div 2; + a3 := a2 + dash; + if (J = 0) then a2 := a0; + if (a3 > a1) then a3 := a1; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + end; + J := J + 1; + until (a3 >= a1); + dotdash : repeat a2 := a0 + J*frame - extra div 2; + a3 := a2 + dash; + if (J = 0) then a2 := a0; + if (a3 > a1) then a3 := a1; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + a2 := a3 + gap; + a3 := a2 + dot; + b2 := round(s*(a2-a0) + b0); + b3 := round(s*(a3-a0) + b0); + if (a3 <= a1) then + begin + if (useXaxis) then + diagonal (a2, b2, a3, b3, fontindex) + else + diagonal (b2, a2, b3, a3, fontindex); + end; + end; + J := J + 1; + until (a3 >= a1); + end; + 30: + end; { balance } + +{......................................................} + function project (I : integer) : integer; + var K : integer; { gives the projection of lengths onto axes } + begin + K := round(I*float(abs(a1-a0))/s); + if K = 0 then K := 1; + project := K; + end; +{......................................................} + procedure setlengths (findex :integer); + (* sets the "optimal" sizes for textured lines *) + var penrad : integer; + siz : VThickness; + begin + penrad := VFontTable[findex]^.PenSize; + siz := VFontTable[findex]^.psize; + + Dotdot := penrad div siz; Dotgap := 6 * penrad; + Dashdash := 6 * penrad; Dashgap := 6 * penrad; + DDotdash := 6 * penrad; DDotgap := 4 * penrad; + DDotdot := penrad div siz; + end; +{........................................} +procedure setframesize; +begin + case line_type of { length of frame depends on type of broken line } + solid : frame := 0; + dotted : frame := gap + dot; + dashed : frame := gap + dash; + dotdash : frame := 2*gap + dot + dash; + end; +end; + +{.................................................} +begin (* TylBrokenLine *) +if ((x0 = x1) and (y0 = y1)) then + begin + diagonal (x0, y0, x1, y1, fontindex); { null line } + goto 10; + end; + + setlengths (fontindex); + +if (abs (y1-y0) > abs(x1-x0)) then { longer axis is used as base } + begin + useXaxis := false; + a0 := y0; b0 := x0; + a1 := y1; b1 := x1; + end +else + begin + useXaxis := true; + a0 := x0; b0 := y0; + a1 := x1; b1 := y1; + end; +{ the distance between a0 and a1 is now greater than that between b0 and b1. } + +{ redefine distances as integral units along axes } + s := distance (float(a0),float(b0),float(a1),float(b1)); + + case line_type of + solid: ; + dotted: + begin + gap := project(Dotgap); + dot := project(Dotdot); + end; + dashed: + begin + gap := project(Dashgap); + dash := project(Dashdash); + end; + dotdash: + begin + gap := project(DDotgap); + dot := project(DDotdot); + dash := project(DDotdash); + end; + end; + + { ensure direction of line is from smaller to + larger along the longer axis } + if (a0 > a1) then + begin + J := a0; a0 := a1; a1 := J; + J := b0; b0 := b1; b1 := J; + end; + + setframesize; + + a1ma0 := a1 - a0; + + { fit is the number of frames that fit in line } + if (frame <> 0) then + begin + fit := (float(a1ma0) / float(frame)); + end + else + fit := 1.0; + + if (fit >= 1.0) then + T := round (fit) + else + begin + (* change frame elements (dot, dash, gap) since frame is too large *) + case line_type of + dotted : begin + gap := gap - (frame - a1ma0); + if (gap < dot) then + begin + goto 10; (* exit *) + end; + setframesize; + end; + + dashed, + dotdash : begin + (* idea:decrease gap; if too small then shrink dash and refigure gap*) + if ((frame - a1ma0) > (gap div 2)) then + begin + dash := round (dash * fit * 0.80); + gap := round (gap * fit); + setframesize; + end; + gap := gap - (frame - a1ma0); + if (line_type = dotdash) then + gap := gap div 2; + if (gap < dot) then + begin + goto 10; (* exit *) + end; + setframesize; + end; + end; (* case *) + T := 1; (* NOW it will fit *) + end; (* else *) + + + case line_type of + solid : begin + if (useXaxis) then + diagonal (a0, b0, a1, b1, fontindex) + else + diagonal (b0, a0, b1, a1, fontindex); + end; + + dotted : begin { dotted lines begin and end on a dot } + if ((T*frame + dot) = a1ma0) then + spread(dotted, 0, T) + else if ((T*frame + dot) > a1ma0) then + begin +{ gap := gap - ((T*frame+dot)-a1ma0); +{} + spread(dotted, a1ma0 - T*frame - dot, T); + +{ spread(dotted, a1ma0 - (T-1)*frame - dot, T-1); +{} + end + else + spread(dotted, a1ma0 - T*frame - dot, T); + end; + + dashed : begin + { dashed lines begin and end on dash : + the beginning and ending dashes are at least half + the dash length long. } + if ((T*frame + dash) = a1ma0) then + spread(dashed, 0, T) + else if ((T*frame + dash) > a1ma0) then + balance(dashed, T*frame + dash - a1ma0, T) + else spread(dashed, a1ma0 - T*frame - dash, T); + end; + + dotdash : begin { if ending on a dash then beginning and ending + dashes are half the dash length long - final + dots are full dot length } + if ((T*frame + dash) = a1ma0) then + spread(dotdash, 0, T) + else if ((T*frame + dash + gap + dot) = a1ma0) then + spread(dotdash, 0, T) + else if ((T*frame + dash) > a1ma0) then + balance(dotdash, T*frame + dash - a1ma0, T) + else if ((T*frame + dash + gap + dot) > a1ma0) then + spread(dotdash, a1ma0 - T*frame - dash, T) + else spread(dotdash, a1ma0 - T*frame - dash - gap - dot, T); + end; + end; +10: + end; + + + +{-------------------------------------------------------} +procedure clampthickness (var thic : VThickness); + begin + (* #### this is just a simple clamp + really should be something like: + while not (thic in set_of_appropriate_thicknesses) do + modify thic and try again + *) + if (thic <= LoVThick ) then + thic := LoVThick + 1; + while ((not (thic in [1,2,3,4,5,6,7,8,9,10,11,12])) and + (thic <= HiVThick)) do + thic := thic + 1; + + if (thic > HiVThick) then + thic := HiVThick; + end; + +{----------------------------------------------------------} +procedure slurclamp (var thic : ThickAryType; totpts : integer); + (* this post-clamps the sampled thicknesses calculated over the + whole of the spline *) + + var i : integer; + oneseventh : integer; + middle : integer; + startval, endval: integer; + deltaval, val, incrval, alpha, alphaincr: real; + + begin + { $$ NOTE:: How does the ttspline interpolation of thicknesses + compare to the below results?? Can we avoid having it done + elsewhere and concentrate on it here?? } + + oneseventh := round (totpts / 7.0); + for i := 1 to oneseventh do + begin + thic[i] := thic[1]; + end; + for i := 6*oneseventh to totpts do + begin + thic[i] := thic[totpts]; + end; + + middle := round (totpts / 2.0); + for i := 3*oneseventh to 4*oneseventh do + begin + thic[i] := thic[middle]; + end; + + startval := thic[oneseventh - 1]; + endval := thic[3*oneseventh + 1]; + deltaval := (2*(endval - startval))/(2*oneseventh); + alphaincr := PI / (2 * oneseventh + 1); + alpha := PI; + val := float(startval); + for i := oneseventh to (3*oneseventh - 1) do + begin (* interpolate: ease in from minthick to middlethickness *) + alpha := alpha + alphaincr; + incrval := ((cos (alpha) + 1.0) / 2.0) * deltaval; + val := val + incrval; + thic[i] := round(val); + end; + + startval := thic[4*oneseventh - 1]; + endval := thic[6*oneseventh + 1]; + deltaval := (2*(endval - startval))/(2*oneseventh); + alphaincr := PI / (2 * oneseventh + 1); + alpha := 0.0; + val := float(startval); + for i := (4*oneseventh + 1) to 6*oneseventh do + begin (* ease out from middle thickness to min thick at far end *) + alpha := alpha + alphaincr; + incrval := ((cos (alpha) + 1.0) / 2.0) * deltaval; + val := val + incrval; + thic[i] := round(val); + end; + end; + +{-------------------------------------------------------} +procedure layline (xl, yb, xr, yt, fontindex : integer; + pattern : LineStyle; useVecfontOnly : boolean); + var t: integer; + begin + if (xr < xl) then + begin + t := xr; xr := xl; xl := t; + t := yb; yb := yt; yt := t; + end; + + isetfont (VFontTable[fontindex]^.DVIFontNum); + + (* we may want to require using a vector font only, + instead of a combination of vectors and TeX-rules. + It may look better this way. + *) + if (useVecfontOnly) then + begin + tylBrokenLine (xl, yb, xr, yt, fontindex, pattern); + end + else + begin (* be smart about the lines *) + if ((xl = xr) and (yb = yt)) or + ((xl <> xr) and (yb <> yt)) then (* Null or diagonal lines *) + begin + if (pattern = solid) then + diagonal (xl, yb, xr, yt, fontindex) + else + tylBrokenLine (xl, yb, xr, yt, fontindex, pattern); + end + else + begin +{ if (pattern = solid) then + hvline (xl, yb, xr, yt, fontindex) (* make use of rules *) + else +USENORULES } + tylBrokenLine (xl, yb, xr, yt, fontindex, pattern); + end + end; + + end; + + + +{------------------------------------------------------} +procedure layAspline (thetype : SplineKind; + isclosed : boolean; + isanArc: boolean; + domarks : integer; + var cpts : ControlPoints; + numpts : integer; + thick: VThickness; + vkind : VectKind; + patt : LineStyle); + const DontDoThicks = false; + VectorsOnly = true; + var pointList: SplineSegments; + i, xs, ys : integer; + tt1, tt2 : ThickAryType; + F: VecIndex; + begin + + clampthickness (thick); + for i := 0 to (numpts + 3) do + tt1[i] := thick; + + (* do any marks if necessary to show the control points *) + if (domarks > 0) then + begin + F := GetVectFont (domarks, VKCirc); + isetfont (VFontTable[F]^.DVIFontNum); + for i := 1 to numpts do + begin + Tyldot (cpts[i,1], cpts[i,2]); + end; + end; + + drawSpline (thetype, isclosed, isanArc, patt, + numpts, cpts, pointList, DontDoThicks, tt1, tt2); + + + F := GetVectFont (thick, vkind); + xs := pointList[1, 1]; + ys := pointList[1, 2]; + + for i := 2 to lastPoint do + begin + layline (xs, ys, pointList[i, 1], pointList[i, 2], F, patt, VectorsOnly); + xs := pointList[i, 1]; + ys := pointList[i, 2]; + end; + if (isclosed) then (* complete the motion *) + layline (pointList[lastPoint,1], pointList[lastPoint,2], + pointList[1,1], pointList[1,2], F, patt, VectorsOnly); + end; + + +{-----------------------------------------------------} +procedure layNspline (thetype : SplineKind; + isclosed : boolean; + isitaslur : boolean; + domarks : integer; + var cpts : ControlPoints; + numpts : integer; + var thickmatrix : ThickAryType; + vkind : VectKind; + patt : LineStyle); + const NotAnArc = false; + DoThicksToo = true; + VectorsOnly = true; + var pointList: SplineSegments; + i, xs, ys : integer; + ts : VThickness; + tt : ThickAryType; + F : VecIndex; + begin + (* do any marks if necessary to show the control points *) + if (domarks > 0) then + begin + F := GetVectFont (domarks, VKCirc); + isetfont (VFontTable[F]^.DVIFontNum); + for i := 1 to numpts do + begin + Tyldot (cpts[i,1], cpts[i,2]); + end; + end; + + drawSpline (thetype, isclosed, NotAnArc, patt, + numpts, cpts, pointList, + DoThicksToo, thickmatrix, tt); + if ((isitaslur) and (not skiptsclamp)) then + begin + slurclamp(tt, lastPoint); (* which kind of clamping to use *) + end; + + xs := pointList[1, 1]; + ys := pointList[1, 2]; + ts := tt[1]; + + for i := 2 to lastPoint do + begin + clampthickness (ts); + F := GetVectFont (ts, vkind); + layline (xs, ys, pointList[i, 1], pointList[i, 2], F, patt, VectorsOnly); + xs := pointList[i, 1]; + ys := pointList[i, 2]; + ts := tt[i]; + end; + if (isclosed) then + begin + ts := tt[lastPoint]; + clampthickness(ts); + F := GetVectFont (ts, vkind); + layline (pointList[lastPoint,1], pointList[lastPoint,2], + pointList[1,1], pointList[1,2], F, patt, VectorsOnly); + end; + end; + + + +{-----------------------------------------------------} +procedure TylBeam (* fromx, fromy, tox, toy: ScaledPts; + staffsize : integer; kind : BeamKind *); + + begin + + end; (* TylBeam *) + + +{-------------------------------------------------------} +procedure TylLine (* xl, yb, xr, yt: ScaledPoints; + thickness: VThickness; + vec: VectKind; patt : LineStyle *); + const dontCare = false; + var findex: VecIndex; + begin + clampthickness (thickness); + findex := GetVectFont (thickness, vec); + layline (xl, yb, xr, yt, findex, patt, dontCare); + end; + + +{-----------------------------------------------------} +procedure TylThickThinSpline (* thetype : SplineKind; isclosed : boolean; + var KnotArray: ControlPoints; + var ThikThinAry: ThickAryType; + numknots: integer; + vec: VectKind; + patt : LineStyle; domarks : integer *); + const NotAnArc = false; + begin + layNspline (thetype, isclosed, NotAnArc, domarks, KnotArray, numknots, + ThikThinAry, vec, patt); + end; + +{----------------------------------------------------} +procedure TylSpline (* thetype : SplineKind; isclosed : boolean; + var KnotArray: ControlPoints; numknots: integer; + thick: VThickness; vec: VectKind; patt : LineStyle; domarks : integer*); + const NotAnArc = false; + begin + layAspline (thetype, isclosed, NotAnArc, domarks, KnotArray, numknots, + thick, vec, patt); + end; + +{-----------------------------------------------------} +procedure TylTieSlur (* KnotArray: ControlPoints; + numknots: integer; + minthick, maxthick: VThickness *); + const ItsASlur = true; + NotClosed = false; + var ourttarray : ThickAryType; + one7th : real; + val : VThickness; + begin + + clampthickness (minthick); + clampthickness (maxthick); + if (numknots <> 5) then + writeln ('TieSlur needs 5 control points '); + one7th := 1.0/7.0; + val := round (one7th * (maxthick - minthick)); + ourttarray[1] := minthick; + ourttarray[2] := minthick + val; + ourttarray[3] := maxthick; + ourttarray[4] := minthick + val; + ourttarray[5] := minthick; + + layNspline (CATROM, NotClosed, ItsASlur, 0, KnotArray, numknots, ourttarray, + VKCirc, solid); + end; + + +{-------------------------------------------------------} +procedure doTylArc (* iscircle : boolean; + var apts : ControlPoints; + numknots : integer; + thick : VThickness; + vec : VectKind; + patt : LineStyle *); + + const ItsAnArc = true; + begin + + layAspline (BSPL, iscircle, ItsAnArc, 0, apts, numknots, thick, vec, patt); + end; + +{-----------------------------------------------------------} +procedure TylArc (* radius : ScaledPts; centx, centy : ScaledPts; + firstangle, secondangle : integer; + thick : VThickness; vec : VectKind; patt : LineStyle *); + var apts : ControlPoints; + numknots : integer; + iscircle : boolean; + begin + iscircle := (firstangle = secondangle); + if iscircle then + begin + { maxspan := round ((360.0 / 16.0) * DEGTORAD * radius); + {} + defineCircleCpts (radius, centx, centy, apts, numknots); + end + else + begin + { maxspan := round ((abs (secondangle - firstangle) / 16.0) * DEGTORAD * radius); +{ } + definearcpts (radius, centx, centy, + firstangle, secondangle, apts, numknots); + end; + + doTylArc (iscircle, apts, numknots, thick, vec, patt); + + end; + +{-----------------------------------------------------------} +procedure TylLabel (* xpos, ypos : ScaledPts; + fontstyle : integer; + phrase : charstring; + phraselen : integer *); +var findex : integer; + c : integer; + spaceover : integer; + +begin +if ((fontstyle < 1) or (fontstyle > MAXLABELFONTS)) then + begin + complain (ERRREALBAD); + writeln(logfile,'Unexpected bad fontstyle in TylLabel: ',fontstyle:0,'?'); + jumpout; + end; +findex := GetLabFont (fontstyle); +isetpos (xpos, ypos); +IPUSH; +isetfont (LFontTable[findex]^.DVIFontNum); +spaceover := LFontTable[findex]^.spacewidth; +for c := 1 to phraselen do + begin + if (phrase[c] <> xchr[32]) then + begin + cmd1byte (SET1); + cmd1byte (xord[ phrase[ c ]]); + end + else + begin (* move over *) + cmd1byte (RIGHTLEFT + 2); (* assume distance is less than 3 bytes *) + cmdSigned (spaceover, 3); + end; + end; +IPOP; +end; + + +(* && start dvidvi section *) +{-----------------------------------------------------} +procedure initialize; + var + i: integer; + begin + for i := 0 to 31 do + xchr[i] := '?'; + xchr[32] := ' '; + xchr[33] := '!'; + xchr[34] := '"'; + xchr[35] := '#'; + xchr[36] := '$'; + xchr[37] := '%'; + xchr[38] := '&'; + xchr[39] := ''''; + xchr[40] := '('; + xchr[41] := ')'; + xchr[42] := '*'; + xchr[43] := '+'; + xchr[44] := ','; + xchr[45] := '-'; + xchr[46] := '.'; + xchr[47] := '/'; + xchr[48] := '0'; + xchr[49] := '1'; + xchr[50] := '2'; + xchr[51] := '3'; + xchr[52] := '4'; + xchr[53] := '5'; + xchr[54] := '6'; + xchr[55] := '7'; + xchr[56] := '8'; + xchr[57] := '9'; + xchr[58] := ':'; + xchr[59] := ';'; + xchr[60] := '<'; + xchr[61] := '='; + xchr[62] := '>'; + xchr[63] := '?'; + xchr[64] := '@'; + xchr[65] := 'A'; + xchr[66] := 'B'; + xchr[67] := 'C'; + xchr[68] := 'D'; + xchr[69] := 'E'; + xchr[70] := 'F'; + xchr[71] := 'G'; + xchr[72] := 'H'; + xchr[73] := 'I'; + xchr[74] := 'J'; + xchr[75] := 'K'; + xchr[76] := 'L'; + xchr[77] := 'M'; + xchr[78] := 'N'; + xchr[79] := 'O'; + xchr[80] := 'P'; + xchr[81] := 'Q'; + xchr[82] := 'R'; + xchr[83] := 'S'; + xchr[84] := 'T'; + xchr[85] := 'U'; + xchr[86] := 'V'; + xchr[87] := 'W'; + xchr[88] := 'X'; + xchr[89] := 'Y'; + xchr[90] := 'Z'; + xchr[91] := '['; + xchr[92] := '\'; + xchr[93] := ']'; + xchr[94] := '^'; + xchr[95] := '_'; + xchr[96] := '`'; + xchr[97] := 'a'; + xchr[98] := 'b'; + xchr[99] := 'c'; + xchr[100] := 'd'; + xchr[101] := 'e'; + xchr[102] := 'f'; + xchr[103] := 'g'; + xchr[104] := 'h'; + xchr[105] := 'i'; + xchr[106] := 'j'; + xchr[107] := 'k'; + xchr[108] := 'l'; + xchr[109] := 'm'; + xchr[110] := 'n'; + xchr[111] := 'o'; + xchr[112] := 'p'; + xchr[113] := 'q'; + xchr[114] := 'r'; + xchr[115] := 's'; + xchr[116] := 't'; + xchr[117] := 'u'; + xchr[118] := 'v'; + xchr[119] := 'w'; + xchr[120] := 'x'; + xchr[121] := 'y'; + xchr[122] := 'z'; + xchr[123] := '{'; + xchr[124] := '|'; + xchr[125] := '}'; + xchr[126] := '~'; + for i := 127 to 255 do + xchr[i] := '?'; + for i := 0 to 127 do + xord[chr(i)] := 32; + for i := 32 to 126 do + xord[xchr[i]] := i; + initallspline; + initVnMnLtables; + multifigure := 0; + pgfigurenum := 0; + TotBytesWritten := 0; + ourq := 0; + specstart := 0; + currpagenum := 0; + newbackptr := (-1); + oldbackptr := (-1); + ourfontnum := (-1); (* undefined *) + origTexfont := (-1); + ourpushdepth := 0; + FTBDs := 0; + InitDVIBuf; + nf := 0; + inpostamble := false; + didnewfonts := false; + maxpages := 10000; + sysdependent; + s := 0; + skiptsclamp := false; + ErrorOccurred := false; + end; + + + +procedure inputln (var buffer : strng); +var + k: 0..ARRLIMIT; +begin + + flush(output); + + if eoln(input) then + readln(input); + k := 1; + while (k < ARRLIMIT) and (not eoln(input)) do + begin + buffer.str[k] := input^; + k := k + 1; + get(input) + end; + buffer.str[k] := ' '; + buffer.len := k - 1; +end; + +function revindex (st : strng; let : char) : integer; +label 2; +var posit,i : integer; +begin + posit := 0; + for i := st.len downto 1 do + begin + if (st.str[i] = let) then + begin + posit := i; + goto 2; + end; + end; +2: + revindex := posit; +end; + + +procedure stripblanks (var st : strng); +var i,j,k: integer; + temp : charstring; + begin + j := 1; + i := 1; + while ((i <= st.len) and + ((st.str[i] = ' ') or (st.str[i] = xchr[HT]))) do + begin + j := j + 1; + i := i + 1; + end; + +(* j now points to the first non-blank character in st.str *) + i := 1; + for k := j to st.len do + begin + if ((st.str[k] <> ' ') and (st.str[k] <> xchr[HT])) then + begin + temp[i] := st.str[k]; + i := i + 1; + end; + end; + (* now copy it back *) + if (i <> 1) then + begin (* there was blankspace *) + for k := 1 to (i- 1) do + st.str[k] := temp[k]; + st.len := i - 1; + + st.str[i] := chr(32); (* end of string *) + + end; + end; + + +{-----------------------------------------------------} +procedure AskandOpenFiles; +var isok : boolean; + i : integer; + rp : integer; + tempname : strng; +begin + isok := false; + while (not isok) do + begin + write (' DVI-input File Name: '); + inputln (dvifname); + stripblanks (dvifname); + + rp := revindex (dvifname, '.'); + if (rp = 0) then + begin + (* add a ".dvi" extension *) + i := dvifname.len; + dvifname.str[i + 1] := '.'; + dvifname.str[i + 2] := 'd'; + dvifname.str[i + 3] := 'v'; + dvifname.str[i + 4] := 'i'; + dvifname.len := i + 4; + end; + if (not opendvifile) then + begin + isok := false; (* it is empty *) + writestrng(dvifname,false); + writeln(': Empty File?? Try another name.'); + end + else + isok := true; + end; (* while *) + + (* and ask for the name of the output file *) + (* default it to be the same prefix, but with a ".tyl" suffix *) + strcopy (dvifname.str, outname.str, dvifname.len); + outname.len := dvifname.len; + rp := revindex (outname, '.'); + i := rp - 1; + outname.str[i + 1] := '.'; + outname.str[i + 2] := 't'; + outname.str[i + 3] := 'y'; + outname.str[i + 4] := 'l'; + outname.len := i + 4; + + writeln (' DVI-output File Name :'); + write('(different than input name)[default of '); + writestrng (outname,false); + write(']'); + inputln (tempname); + if (tempname.len > 1) then + begin (* a filename was typed in *) + + strcopy (tempname.str, outname.str, tempname.len); + end; + + openoutputfile; diff --git a/macros/latex209/contrib/textyl/psrc/textyl.pas.ah b/macros/latex209/contrib/textyl/psrc/textyl.pas.ah new file mode 100644 index 0000000000..484c45dbb4 --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/textyl.pas.ah @@ -0,0 +1,873 @@ + + strcopy (dvifname.str, logfilnam.str, dvifname.len); + logfilnam.len := dvifname.len; + rp := revindex (logfilnam, '.'); + (* add a ".tlog" extension *) + i := rp - 1; + logfilnam.str[i + 1] := '.'; + logfilnam.str[i + 2] := 't'; + logfilnam.str[i + 3] := 'l'; + logfilnam.str[i + 4] := 'o'; + logfilnam.str[i + 5] := 'g'; + logfilnam.len := i + 5; + + openlogfile; +end; + + +{-----------------------------------------------------} + function inTFM (z: integer): boolean; + label + 9997, 9998, 9999; + var + k: integer; + lh: integer; + nw: integer; + alpha, beta: integer; + begin + readtfmword; + lh := b2 * 256 + b3; + readtfmword; + font[nf].bc := b0 * 256 + b1; + font[nf].ec := b2 * 256 + b3; + if (font[nf].ec < font[nf].bc) then + font[nf].bc := font[nf].ec + 1; + readtfmword; + nw := b0 * 256 + b1; + if ((nw = 0) or (nw > 256)) then + goto 9997; + for k := 1 to 3 + lh do + begin + if eof(tfmfile) then + goto 9997; + readtfmword; + if (k = 4) then + if (b0 < 128) then + tfmchecksum := ((b0 * 256 + b1) * 256 + b2) * 256 + b3 + else + tfmchecksum := (((b0 - 256) * 256 + b1) * 256 + b2) * 256 + b3 + end; + + for k := 0 to (font[nf].ec - font[nf].bc) do + begin + readtfmword; + if (b0 > nw) then + goto 9997; + font[nf].widths[k] := b0 + end; + alpha := 16 * z; + beta := 16; + while z >= TWO23 do + begin + z := z div 2; + beta := beta div 2 + end; + for k := 0 to nw - 1 do + begin + readtfmword; + inwidth[k] := (((b3 * z) div 256 + b2 * z) div 256 + b1 * z) div beta; + if b0 > 0 then + if b0 < 255 then + goto 9997 + else + inwidth[k] := inwidth[k] - alpha; + end; + if inwidth[0] <> 0 then + goto 9997; + with font[nf] do + begin + for k := 0 to (ec - bc) do + if widths[k] = 0 then + begin + widths[k + bc] := TWO31; +{ pixelwidths[k + bc] := 0;} + end + else + begin + widths[k + bc] := inwidth[widths[k]]; +{ pixelwidths[k + bc] := round(conv * widths[k]);} + end; + end; (* with *) + inTFM := true; + goto 9999; +9997: + complain (ERRREALBAD); + writestrng(tfmname,true); + writeln(logfile,'---not loaded, TFM file is bad'); + +9998: + inTFM := false; +9999: + + end; + + + +{-----------------------------------------------------} +procedure Fastdefinefont (fn: integer); +var p, k: integer; + n, waste: integer; + c, q, d: integer; + +begin { Fastdefinefont } + c := Dsign4byte; + q := Dsign4byte; + d := Dsign4byte; + p := Dget1byte; + n := Dget1byte; + for k := 1 to (p + n) do + waste := Dget1byte; +end; { Fastdefinefont } + + +{-----------------------------------------------------} + procedure definefont (e: integer); + var + f: 0..MAXFONTS; + p, k: integer; + n: integer; + c, q, d: integer; + r: integer; + begin + if (nf = MAXFONTS) then + begin + complain (ERRREALBAD); + writeln(logfile,'TeXtyl capacity exceeded (max fonts=', MAXFONTS: 1, ')!'); + writeln('TeXtyl capacity exceeded (max fonts=', MAXFONTS: 1, ')!'); + jumpout + end; + font[nf].num := e; + f := 0; + while font[f].num <> e do (* find first occurrence *) + f := f + 1; + c := Dsign4byte; + font[nf].checksum := c; + q := Dsign4byte; + font[nf].scaledsize := q; + d := Dsign4byte; + font[nf].designsize := d; + p := Dget1byte; + n := Dget1byte; + font[nf].name.len := p + n; + for k := 1 to (p + n) do + font[nf].name.str[k] := Dget1byte; + + if (f = nf) then + begin (* f = nf *) + for k := 1 to AREALENGTH do + tfmname.str[k] := ' '; + + r := 0; + + for k := 1 to font[nf].name.len do + begin + r := r + 1; + tfmname.str[r] := xchr[font[nf].name.str[k]] + end; + tfmname.str[r + 1] := '.'; + tfmname.str[r + 2] := 't'; + tfmname.str[r + 3] := 'f'; + tfmname.str[r + 4] := 'm'; + + tfmname.str[r + 5] := chr(32); + + tfmname.len := r + 4; + + if (not opentfmfile) then + begin + complain (ERRREALBAD); + writestrng(tfmname,true); + writeln(logfile,'---not loaded, TFM file can''t be opened!'); + writestrng(tfmname, false); + writeln(' cannot be opened. Aborting.'); + jumpout; + end + else + begin + if (q <= 0) or (q >= TWO27) then + begin + complain (ERRREALBAD); + writestrng(tfmname,true); + writeln(logfile,'---not loaded, bad scale (', q: 1, ')!'); + end + else if (d <= 0) or (d >= TWO27) then + begin + complain (ERRREALBAD); + writestrng(tfmname,true); + writeln(logfile,'---not loaded, bad design size (', d: 1, ')!'); + end + else + if inTFM(q) then + begin (* intfm *) + font[nf].space := q div 6; + if (c <> 0) and (tfmchecksum <> 0) and (c <> tfmchecksum) then + begin + writeln(logfile,'Problem in fig#',pgfigurenum:0,' on page ',currpagenum:0); + writestrng(tfmname,true); + writeln(logfile,'---beware: check sums do not agree!'); + writeln(logfile,' (', c: 1, ' vs. ', tfmchecksum: 1, ')'); + end; + d := round(100.0 * conv * q / (trueconv * d)); + nf := nf + 1; + font[nf].space := 0; + end (* intfm *) + end; + end; + end; + +{-----------------------------------------------------} + function firstpar (o: OctByt): integer; + var fpar : integer; + begin + case (o) of + 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, + 126, 127: + fpar := o - 0; + 128, 133, 235, 239, 243: + fpar := Dget1byte; + 129, 134, 236, 240, 244: + fpar := Dget2byte; + 130, 135, 237, 241, 245: + fpar := Dget3byte; + 143, 148, 153, 157, 162, 167: + fpar := Dsign1byte; + 144, 149, 154, 158, 163, 168: + fpar := Dsign2byte; + 145, 150, 155, 159, 164, 169: + fpar := Dsign3byte; + 131, 132, 136, 137, 146, 151, 156, + 160, 165, 170, 238, 242, 246: + fpar := Dsign4byte; + 138, 139, 140, 141, 142, 247, 248, + 249, 250, 251, 252, 253, 254, 255: + fpar := 0; + 147: + fpar := w; + 152: + fpar := x; + 161: + fpar := y; + 166: + fpar := z; + 171, 172, 173, 174, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, + 234: + fpar := o - 171 + end; + firstpar := fpar; + end; + +{-----------------------------------------------------} + function specialcases (o: OctByt; p: integer): boolean; + label + 46, 44, 30, 9998; + var + pure: boolean; + + begin + pure := true; + if ((o < 157) or (o > 249)) then + begin + complain (ERRREALBAD); + writeln(logfile, 'undefined command ', o: 1, '!'); + goto 30; + end; + case (o) of + 157, 158, 159, 160: + begin + goto 44; + end; + 161, 162, 163, 164, 165: + begin + y := p; + goto 44; + end; + 166, 167, 168, 169, 170: + begin + z := p; + goto 44; + end; + 171, 172, 173, 174, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, + 234: + begin + goto 46; + end; + 235, 236, 237, 238: + begin + goto 46; + end; + 243, 244, 245, 246: + begin + definefont(p); + goto 30; + end; + + 239, 240, 241, 242: + begin (* =========specials============= *) + mainhandlespecials (o, p); + goto 30; + end; + 247: + begin + complain (ERRREALBAD); + writeln(logfile,'preamble command within a page!'); + goto 9998; + end; + 248, 249: + begin + complain (ERRREALBAD); + writeln(logfile,'postamble command within a page!'); + goto 9998; + end; + (* others: + begin + write(' ', 'undefined command ', o: 1, '!'); + goto 30; + end + *) + end; +44: (* label *) + if (v > 0) and (p > 0) then + if (v > TWO31 - p) then + begin + p := TWO31 - v + end; + if (v < 0) and (p < 0) then + if ((-v) > (p + TWO31)) then + begin + p := -v - TWO31 + end; + + v := v + p; + + goto 30; +46: (* label *) + font[nf].num := p; + curfont := 0; + while font[curfont].num <> p do + curfont := curfont + 1; + goto 30 ; +9998: + pure := false; +30: + specialcases := pure; + end; + + +{-----------------------------------------------------} + function dopage : boolean; + label + 41, 42, 43, 30, 9998, 9999; + var + o: OctByt; + p, q: integer; + + begin + curfont := nf; + s := 0; + h := 0; + v := 0; + w := 0; + x := 0; + y := 0; + z := 0; + + ourxpos := 0; + ourypos := 0; + ourfontnum := (-1); + while true do + begin + o := Dget1byte; + p := firstpar(o); + if eof(dvifile) then begin + writeln(logfile, 'Bad DVI file: ', 'the file ended prematurely', '!'); + writeln('Bad DVI file: ', 'the file ended prematurely', '!'); + jumpout + end; + if o <= 131 then + begin + goto 41; + end + else + begin + if (o > 156) then + begin + if specialcases(o, p) then + goto 30 + else + goto 9998; + end; + + case (o) of + 133, 134, 135, 136: + begin + goto 41; + end; + 132, 137: + begin + goto 42 + end; + 138: + begin + goto 30; + end; + 139: + begin (* BOP *) + complain (ERRREALBAD); + writeln(logfile, 'bop occurred before eop'); + goto 9998; (* Fail *) + end; + 140: + begin (* EOP *) + if (s <> 0) then + begin + complain (ERRREALBAD); + writeln(logfile, 'stack not empty at end of page (level ', s: 1, ')!'); + end; + if (multifigure <> 0) then + begin + complain (ERRBAD); + writeln(logfile,'Some figure definition not closed at end of page ', currpagenum:0,'!'); + end; + + write (currpagenum:0,']'); + write (logfile,currpagenum:0,']'); + if ((currpagenum mod 10) = 0) then + writeln; + dopage := true; + goto 9999; + end; + 141: + begin (* PUSH *) + with stack[s] do + begin + sh := h; + sv := v; + sw := w; + sx := x; + sy := y; + sz := z; + end; (* with *) + s := s + 1; + goto 30; + end; + 142: + begin (* POP *) + if s = 0 then + begin + complain (ERRREALBAD); + writeln(logfile,'illegal pop at level zero!'); + end + else + begin + s := s - 1; + with stack[s] do + begin + h := sh; + v := sv; + w := sw; + x := sx; + y := sy; + z := sz; + end; + end; + goto 30; + end; + 143, 144, 145, 146: + begin + q := p; + goto 43 + end; + 147, 148, 149, 150, 151: + begin + w := p; + q := p; + goto 43 + end; + 152, 153, 154, 155, 156: + begin + x := p; + q := p; + goto 43 + end; + (* others: + if specialcases(o, p) then + goto 30 + else + goto 9998; + *) + end; (* case *) + end; (* else *) +41: (* finish cmd to set/put a char *) + if p < 0 then + p := 255 - (-1 - p) mod 256 + else if p >= 256 then + p := p mod 256; + if (p < font[curfont].bc) or (p > font[curfont].ec) then + q := TWO31 + else + q := font[curfont].widths[p]; + if (q = TWO31) then + begin + complain (ERRREALBAD); + writeln(logfile,'Character ', p:1,' invalid in font #',curfont:0); + end; + if o >= 133 then + goto 30; + if q = TWO31 then + q := 0; + goto 43; + +42: (* finish cmd to set/put rule *) + q := Dsign4byte; + if o = 137 then + goto 30; + goto 43 ; + +43: (*finish cmd that sets h += q *) + if (h > 0) and (q > 0) then + if (h > (TWO31 - q)) then + begin + q := TWO31 - h + end; + if (h < 0) and (q < 0) then + if ((-h) > (q + TWO31)) then + begin + q := (-h) - TWO31 + end; + + h := h + q; +30: + end; +9998: + dopage := false; +9999: + + end; + +{-----------------------------------------------------} + procedure skippages; + label + 9999; + var + p: integer; + k: 0..255; + downthedrain: integer; + begin + while true do + begin + if eof(dvifile) then + begin + writeln(logfile, 'Bad DVI file: ', 'the file ended prematurely', '!'); + write(' ', 'Bad DVI file: ', 'the file ended prematurely', '!'); + jumpout + end; + k := Dget1byte; + p := firstpar(k); + case (k) of + 139: + begin (* BOP *) + newbackptr := DVIMark + TotBytesWritten - 1; + currpagenum := Dsign4byte; (* count[0] *) + for k := 1 to 9 do + waste := Dsign4byte; (* WAS count[k] := *) + downthedrain := Dsign4byte; + BackupInBuf (4); + cmdSigned (oldbackptr, 4); + oldbackptr := newbackptr; + write(' ['); + write(logfile,' ['); + goto 9999; + end; + 132, 137: (* RULE *) + downthedrain := Dsign4byte; + 243, 244, 245, 246: + begin + definefont(p); + end; + 239, 240, 241, 242: (* specials *) + begin + mainhandlespecials (k, p); + end; + 248: + begin (* POST *) + ourq := DVIMark + TotBytesWritten - 1; + inpostamble := true; + goto 9999 + end; + (* others: + null + *) + end + end; + 9999: + + end; + +{-----------------------------------------------------} + procedure readpostamble; + var + k: integer; + p, q, m: integer; + indx : integer; + begin + if (Dsign4byte <> numerator) then + writeln(logfile,'Postamble',' numerator',' doesn''t match the preamble!'); + if (Dsign4byte <> denominator) then + writeln(logfile,'Postamble',' denominator',' doesn''t match the preamble!'); + if (Dsign4byte <> mag) then + begin + writeln(logfile,'Postamble',' magnification',' doesn''t match the preamble!'); + end; + maxv := Dsign4byte; + maxh := Dsign4byte; + maxs := Dget2byte; + BackupInBuf (2); + cmd2byte (maxs + 2); (* pretend the stack depth + * does not increase by + * more than two + *) + + totalpages := Dget2byte; + repeat + k := Dget1byte; + if (k >= 243) and (k < 247) then + begin + p := firstpar(k); + Fastdefinefont(p); + k := 138; + end + until k <> 138; (* NOP *) + + (* here, backup 1, enter all our fonts and + then output the 249 that we backed over *) + BackupInBuf (1); + for indx := 1 to MFontsDefd do + begin + with MFontTable[indx]^ do + enterfont (DVIFontNum, Cksum, DesSize, + DesSize, FontName ); + end; (* for *) + for indx := 1 to VFontsDefd do + begin + with VFontTable[indx]^ do + enterfont (DVIFontNum, Cksum, DesSize, + DesSize, FontName); + end; (* for *) + for indx := 1 to LFontsDefd do + begin + with LFontTable[indx]^ do + enterfont (DVIFontNum, Cksum, DesSize, + DesSize, FontName); + end; + cmd1byte(249); (* post post *) + + if (k <> 249) then + writeln(logfile,'byte ',k:0,' is not postpost!'); + q := Dsign4byte; + BackupInBuf (4); + cmd4byte (ourq); + m := Dget1byte; + if (m <> 2) then + writeln(logfile,'identification should be ', 2: 1, '!'); + m := 223; + while (m = 223) and not eof(dvifile) do + m := Dget1byte; + if not eof(dvifile) then + begin + writeln(' ', 'Bad DVI file: ', 'signature in should be 223', '!'); + writeln(logfile, 'Bad DVI file: ', 'signature in should be 223', '!'); + jumpout + end; + end; + + +(* MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN *) +begin (* main *) + initialize; + AskandOpenFiles; (* ask for filenames of inputdvi and outputfil *) + + writeln(logfile, TylVersion,' for Berkeley Unix'); + + write(logfile,'Reading File: '); + writestrng(dvifname,true); + writeln(logfile); + + + p := Dget1byte; + if (p <> 247) then + begin + write(' ', 'Bad DVI file: ', 'First byte isn''t start of preamble!', '!'); + writeln(logfile,'Bad DVI file: ', 'First byte isn''t start of preamble!', '!'); + jumpout + end; + p := Dget1byte; + if (p <> 2) then + writeln(logfile,'identification in byte 1 should be ', 2: 1, '!'); + numerator := Dsign4byte; + denominator := Dsign4byte; + if (numerator <= 0) then + begin + write(' ', 'Bad DVI file: ', 'numerator is ', numerator: 1, '!'); + writeln(logfile, 'Bad DVI file: ', 'numerator is ', numerator: 1, '!'); + jumpout + end; + if (denominator <= 0) then + begin + write(' ', 'Bad DVI file: ', 'denominator is ', denominator: 1, '!'); + writeln(logfile, 'Bad DVI file: ', 'denominator is ', denominator: 1, '!'); + jumpout + end; + conv := numerator / 254000.0 * (resolution / denominator); + mag := Dsign4byte; + if (mag <= 0) then + begin + write(' ', 'Bad DVI file: ', 'magnification is ', mag: 1, '!'); + writeln(logfile, 'Bad DVI file: ', 'magnification is ', mag: 1, '!'); + jumpout + end; + magfactor := mag / 1000.0; + trueconv := conv; + conv := trueconv * magfactor; + p := Dget1byte; (* the 'k' of the preamble *) + while p > 0 do + begin + p := p - 1; + waste := Dget1byte; + end; + + skippages; + if not inpostamble then + begin + while (maxpages > 0) do + begin (* while *) + maxpages := maxpages - 1; + if (not dopage) then + begin + write(' ', 'Bad DVI file: ', 'page ended unexpectedly', '!'); + writeln(logfile, 'Bad DVI file: ', 'page ended unexpectedly', '!'); + jumpout + end; + (* now we are at an EOP ---end of page *) + (* flushout GDVIbuffer, and reset counters *) +{ writeln('EOP: bytes used= ',GDVIBuf.TotByteLen:0); } + WriteDVIBuf; + ClearDVIBuf; + multifigure := 0; + pgfigurenum := 0; + FTBDs := 0; + didnewfonts := false; + repeat + k := Dget1byte; + if (k >= 243) and (k < 247) then + begin (* fontdefs *) + p := firstpar(k); + definefont(p); + k := 138 + end; + until (k <> 138); (* nop *) + + if (k = 248) then + begin + inpostamble := true; + ourq := DVIMark + TotBytesWritten - 1; + goto 30 + end; + + if (k = 139) then (* BOP *) + begin + newbackptr := DVIMark + TotBytesWritten - 1; + currpagenum := Dsign4byte; (* Count[0] *) + for k := 1 to 9 do + waste := Dsign4byte; (* WAS count[k] := *) + waste := Dsign4byte; (* backpointer *) + BackupInBuf (4); + cmdSigned (oldbackptr, 4); + oldbackptr := newbackptr; + write(' ['); + write(logfile,' ['); + end + else + begin (* NOT bop?? *) + writeln('We did not find BOP when expected'); + writeln(logfile,'We did not find BOP when expected'); + jumpout; + end; + + end; (* while *) +30: + end; (* if not inpostamble *) + if (not inpostamble) then + skippages; + waste := Dsign4byte; (* ptr to the last bop in file *) + BackupInBuf (4); + cmdSigned (oldbackptr, 4); + readpostamble; + WriteDVIBuf; + + while ((TotBytesWritten mod 4) <> 0) do + OutputByte(223); (* final signatures *) + + writeln; + writeln(logfile); + write ('Output written on '); + writestrng(outname, false); + write(' (',currpagenum:0,' page'); + if (currpagenum > 1) then + write('s'); + writeln(', ',TotBytesWritten:0,' bytes).'); + + write (logfile,'Output written on '); + writestrng(outname, true); + write(logfile,' (',currpagenum:0,' page'); + if (currpagenum > 1) then + write(logfile,'s'); + writeln(logfile,', ',TotBytesWritten:0,' bytes).'); + + write ('Log written on '); + writestrng(logfilnam, false); writeln; + write (logfile,'Log written on '); + writestrng(logfilnam, true); writeln (logfile); + writeln; + writeln(logfile); +666: + if (ErrorOccurred) then + begin + writeln; + writeln('Some error(s) occurred. Please check Logfile for details'); + writeln('Assume that the outputfile is incorrect'); + end; +end. + diff --git a/macros/latex209/contrib/textyl/psrc/tylext.c b/macros/latex209/contrib/textyl/psrc/tylext.c new file mode 100644 index 0000000000..9bbd057893 --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/tylext.c @@ -0,0 +1,138 @@ +/* External procedures for dvitype */ +/* Written by: H. Trickey, 2/19/83 (adapted from TeX's ext.c) */ + +#include "texpaths.h" /* defines default TEXFONTS path */ +#include "h00vars.h" /* defines Pascal I/O structure */ + +char *fontpath; + +char *getenv(); + +/* + * setpaths is called to set up the pointer fontpath + * as follows: if the user's environment has a value for TEXFONTS + * then use it; otherwise, use defaultfontpath. + */ +setpaths() +{ + register char *envpath; + + if ((envpath = getenv("TEXFONTS")) != NULL) + fontpath = envpath; + else + fontpath = defaultfontpath; +} + +#define namelength 100 /* should agree with defn in textyl program*/ +extern char thefilename[],realnameoffile[]; /* these have size namelength */ + +/* + * testaccess(amode,filepath) + * + * Test whether or not the file whose name is in the global thefilename + * can be opened for reading (if mode=READACCESS) + * or writing (if mode=WRITEACCESS). + * + * The filepath argument is one of the ...FILEPATH constants defined below. + * If the filename given in thefilename does not begin with '/', we try + * prepending all the ':'-separated areanames in the appropriate path to the + * filename until access can be made, if it ever can. + * + * The realnameoffile global array will contain the name that yielded an + * access success. + */ + +#define READACCESS 4 +#define WRITEACCESS 2 + +#define NOFILEPATH 0 +#define FONTFILEPATH 3 + +bool +testaccess(amode,filepath) + int amode,filepath; +{ + register bool ok; + register char *p; + char *curpathplace; + int f; + + switch (filepath) { + case NOFILEPATH: + curpathplace = NULL; + break; + case FONTFILEPATH: + curpathplace = fontpath; + break; + } + if (thefilename[0] == '/') /* file name has absolute path */ + curpathplace = NULL; + do { + packrealnameoffile (&curpathplace); + if (amode == READACCESS)/* use system call "access" to see if we + could read it */ + if (access (realnameoffile, READACCESS) == 0) + ok = TRUE; + else + ok = FALSE; + else { + /* WRITEACCESS: use creat to see if we could create it, but close + the file again if we''re OK, to let pc open it for real */ + f = creat (realnameoffile, 0666); + if (f >= 0) + ok = TRUE; + else + ok = FALSE; + if (ok) + close (f); + } + } while (!ok && curpathplace != NULL); + if (ok) { /* pad realnameoffile with blanks, as + Pascal wants */ + for (p = realnameoffile; *p != '\0'; p++) + /* nothing: find end of string */ + ; + while (p < &(realnameoffile[namelength])) + *p++ = ' '; + } + return (ok); +} + +/* + * packrealnameoffile(cpp) makes realnameoffile contain the directory at *cpp, + * followed by '/', followed by the characters in thefilename up until the + * first blank there, and finally a '\0'. The cpp pointer is left pointing + * at the next directory in the path. + * But: if *cpp == NULL, then we are supposed to use thefilename as is. + */ +packrealnameoffile(cpp) + char **cpp; +{ + register char *p, + *realname; + + realname = realnameoffile; + if ((p = *cpp) != NULL) { + while ((*p != ':') && (*p != '\0')) { + *realname++ = *p++; + if (realname == &(realnameoffile[namelength - 1])) + break; + } + if (*p == '\0') + *cpp = NULL; /* at end of path now */ + else + *cpp = p + 1; /* else get past ':' */ + *realname++ = '/'; /* separate the area from the name to + follow */ + } + /* now append thefilename to realname... */ + p = thefilename; + while (*p != ' ') { + if (realname >= &(realnameoffile[namelength - 1])) { + fprintf (stderr, "! Full file name is too long\n"); + break; + } + *realname++ = *p++; + } + *realname = '\0'; +} diff --git a/macros/latex209/contrib/textyl/psrc/tylext.h b/macros/latex209/contrib/textyl/psrc/tylext.h new file mode 100644 index 0000000000..6025e920cc --- /dev/null +++ b/macros/latex209/contrib/textyl/psrc/tylext.h @@ -0,0 +1,5 @@ +procedure setpaths; + external; + +function testaccess(accessmode:integer; filepath:integer): boolean; + external; diff --git a/macros/latex209/contrib/textyl/src/Makefile b/macros/latex209/contrib/textyl/src/Makefile new file mode 100644 index 0000000000..1ab9ce2598 --- /dev/null +++ b/macros/latex209/contrib/textyl/src/Makefile @@ -0,0 +1,23 @@ +textyl: textyl.o tyl.o spline.o io.o tables.o globals.o + $(CC) -g -o textyl textyl.o tyl.o spline.o io.o globals.o tables.o -lm + +textyl.o: defs.h globals.h tables.h textyl.c + $(CC) -g -c textyl.c + +tyl.o: defs.h globals.h tyl.c + $(CC) -g -c tyl.c + +spline.o: defs.h globals.h spline.c + $(CC) -g -c spline.c + +io.o: defs.h globals.h io.c + $(CC) -g -c io.c + +globals.o: defs.h globals.h globals.c + $(CC) -c globals.c + +tables.o: defs.h tables.h tables.c + $(CC) -c tables.c + +clean: + rm -f *.o textyl diff --git a/macros/latex209/contrib/textyl/src/defs.h b/macros/latex209/contrib/textyl/src/defs.h new file mode 100644 index 0000000000..6f8bec0fde --- /dev/null +++ b/macros/latex209/contrib/textyl/src/defs.h @@ -0,0 +1,208 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <math.h> +#include <setjmp.h> + +#ifdef __STDC__ +#define PP(x) x +#else +#define PP(x) () +#endif + +#define false 0 +#define true 1 + +#define TylVersion "This is TeXtyl, Version 1.30" +/* for dvi-commands */ + +#define DEFTEXFONTS "/n/l/u/kin/lib/tex/tfm" + +#define SET1 128 +#define PUT1 133 +#define PUTRULE 137 +#define NOP 138 +#define PUSH 141 +#define POP 142 +#define RIGHTLEFT 143 +#define DOWNUP 157 +#define FONTDEF 244 +#define USEFONT 236 + +#define USESTDAREA 0 + /* flag to use the 'standard' area to find .tfm files */ + +/* some conversions and numbers */ + +#define TWO16 65536 /* 2 ^ 16 */ +#define TWO20 1048576 /* 2 ^ 20 */ +#define TWO23 8388608 +#define TWO24 16777216 +#define TWO27 134217728 +#define TWO31 2147483647 /* 2^31 - 1 */ + +#define SPPERPT 65536 /* scaled points per printers point */ +#define SPPERMM 186468 /* scaled pts per millimetre */ + +#define RADTODEG 57.29577952 /* degrees per radian */ +#define DEGTORAD 0.0174532925 /* radians per degree */ +#define PI 3.141592654 + +#define BIGREAL 1.0e30 + +#define MAXCTLPTS 63 /* max number of control points */ +#define MAXCTLPTSp3 66 /* max control points + 3 */ +#define ARRLIMIT 100 /* limit for strings and other arrays */ +#define MAXSPLINESEGS 480 /* max number of spline segments */ +#define MAXTBDs 50 /* max number of Fonts-to-be-Defined */ +#define MAXVECLENsp 262144 +/* Normal maximum length of longest + * vector-font character in scaled points + */ + +#define OURFONTFLAG 256 /* our special 'byte' value flag */ +/* Music Font dependent constants */ + +#define DOTCHAR 127 /* ascii number of char that is a dot */ + +#define QNOTEGHUS 18.0 + /* MF: Global Horizontal Units for a Quarternote */ +#define QNOTEGVUS 16.0 + /* MF: Global Vertical units for a quarternote */ +#define GBMGHUS 12.0 /* MF: horizontal units for a grace beam */ +#define GBMGVUS 9.0 + +#define BMSTART 0 +#define BMEND 69 /* indices for start/end of the beam chars */ +#define LOBM1 0 /* indices for the regular beam chars that */ +#define HIBM1 34 /* are 1 quarternote long, and */ +#define LOBM1p5 35 /* for those that are 1.5 quarternotes long */ +#define HIBM1p5 69 + +#define GBMSTART 70 +#define GBMEND 105 /* indices for the grace beams */ +#define LOGBMp5 70 /* indices for grace beam chars that */ +#define HIGBMp5 87 /* are 0.5 grace quarternote long, and */ +#define LOGBMp66 88 /* 0.66 grace quarternotes long */ +#define HIGBMp66 105 + +#define LoVThick 1 /* Bounds for Vector char thicknesses */ +#define HiVThick 13 + +#define SizVFontTable 39 +/* size of the Vector Font Table */ +/* 3*HiVThick */ +#define SizMFontTable 18 /* size of the Music Font Table */ +#define MAXLABELFONTS 5 +#define SizLFontTable MAXLABELFONTS /* size of the Label Font Table */ + +#define TFMSIZE 8000 /* size of TFM array to hold .tfm file info */ + +/* Numeric names for the TeXtyl primitives */ +#define Aline 1 /* should be first */ +#define Aspline 2 +#define Attspline 3 +#define Abeam 4 +#define Atieslur 5 +#define Aarc 6 +#define Alabel 7 +#define Afigure 8 /* should be last one */ + +#define MAXFONTS 60 /* number of TeX fonts to keep track of */ +#define STACKSIZE 50 /* size of stack for pushes and pops */ +#define AREALENGTH 19 /* see also "sysdependent" proc for this value*/ + +#define ERRSIGNAL '?' +#define ERRNOTBAD 0 +#define ERRBAD 1 +#define ERRREALBAD 2 + +typedef int int32; +typedef int ScaledPts; +typedef int ControlPoints[MAXCTLPTSp3 + 1][2]; +typedef int VecIndex; +typedef char VThickness; +typedef VThickness ThickAryType[MAXSPLINESEGS + 1]; +typedef enum { + VKCirc, VKVert, VKHort +} VectKind; +typedef enum { + regular, grace +} BeamKind; +typedef enum { + BSPL, INTBSPL, CATROM, CARD +} SplineKind; +typedef enum { + solid, dotted, dashed, dotdash +} LineStyle; + +typedef char charstring[ARRLIMIT]; + +typedef struct Item { + struct Item *nextitem; + int32 BBlx, BBby, BBrx, BBty; /* Bounding box */ + int itemthick, itemvec; + int itempatt; + int kind; + union { + struct { + int32 lx1, ly1, lx2, ly2; + } U1; + struct { + int spltype; + int sclosed; + int32 dosmarks, nsplknots; + ControlPoints spts; + } U2; + struct { + int tspltype; + int tclosed; + int32 dottmarks, nttknots; + ControlPoints ttpts; + ThickAryType ttarry; + } U3; + struct { + int32 bx1, by1, bx2, by2, staf; + int bkind; + } U4; + struct { + int32 ntknots; + int minth, maxth; + ControlPoints tspts; + } U5; + struct { + int32 acentx, acenty, aradius, firstang, lastang, narcknots; + ControlPoints arcpts; + } U6; + struct { + int32 labx, laby, fontstyle; + charstring labeltext; + } U7; + struct { + double figtheta, fsx, fsy; + int32 fdx, fdy, preWid, preHt, postWid, postHt, depthnumber; + struct Figure *body; + } U8; + } UU; +} Item; + +typedef struct Figure { + Item *things; +} Figure; + +typedef struct { + int32 num; + char name[32]; + int32 checksum, scaledsize, designsize, space, bc, ec; + ScaledPts widths[128]; +} fontinfo; + +/* label fonts info */ + +typedef struct { + int32 DesSize; + charstring FontName; + int32 Cksum; + int Isdefined; + int32 DVIFontNum, internalnumber, spacewidth; +} LabFontInfRec; diff --git a/macros/latex209/contrib/textyl/src/globals.c b/macros/latex209/contrib/textyl/src/globals.c new file mode 100644 index 0000000000..2e0042368c --- /dev/null +++ b/macros/latex209/contrib/textyl/src/globals.c @@ -0,0 +1,22 @@ +#include "defs.h" +#include "globals.h" + +int32 intervals; /* count of spline interval we are on */ +int32 lastPoint; /* num of output points */ +int32 TotBytesWritten, ourq; /* the 'q' for the postpost */ +int didnewfonts; /* did we define the new fonts for this page? */ +char nf = 0; +fontinfo font[MAXFONTS + 1]; +int32 ourfontnum = -1;/* internal number of TeX font currently in use */ +int32 curfont; +LabFontInfRec *LFontTable[SizLFontTable]; +int32 pgfigurenum; /* figure number for this page */ +int32 currpagenum; /* number of page we are on */ + +FILE *dvifile, *tfmfile, *outputfil; +FILE *logfile; + +int32 h, v, w, x, y, z; + +double MINREAL = 1.0e-20; /* a system-dependent 'constant' */ +short b0, b1, b2, b3; diff --git a/macros/latex209/contrib/textyl/src/globals.h b/macros/latex209/contrib/textyl/src/globals.h new file mode 100644 index 0000000000..37b4e76a8a --- /dev/null +++ b/macros/latex209/contrib/textyl/src/globals.h @@ -0,0 +1,208 @@ +extern int32 h, v, w, x, y, z; +extern double MINREAL; /* a system-dependent 'constant' */ +extern FILE *dvifile, *outputfil, *tfmfile, *logfile; +extern int32 lastPoint; /* num of output points */ +extern int32 intervals; /* count of spline interval we are on */ +extern short b0, b1, b2, b3; +extern int didnewfonts; /* did we define the new fonts for this page? */ +extern char nf; +extern fontinfo font[MAXFONTS + 1]; +extern int32 ourfontnum; /* internal number of TeX font currently in use*/ +extern int32 curfont; +extern LabFontInfRec *LFontTable[SizLFontTable]; +extern int32 pgfigurenum; /* figure number for this page */ +extern int32 currpagenum; /* number of page we are on */ +extern int32 TotBytesWritten, ourq; + +extern void jumpout PP((void)); +extern void complain PP((int severity)); +extern double float_ PP((int32 i)); +extern int min PP((int a, int b)); +extern int max PP((int a, int b)); +extern double distance PP((double x0, double y0, double x1, double y1)); +extern void drawSpline PP((SplineKind splinetype, + int isclosed, + int isanArc, + LineStyle patt, + int32 numctls, + int32 (*arrayXY)[2], + int32 (*pointmatrix)[2], + int varythicks, + VThickness *thickmatrix, + VThickness *TTmatrix)); +extern int GetVectFont PP((int size, VectKind vk)); +extern int GetLabFont PP((int32 style)); +extern void defineNewfonts PP((void)); +extern void InitDVIBuf PP((void)); +extern void ClearDVIBuf PP((void)); +extern void BackupInBuf PP((int nbytes)); +extern void WriteDVIBuf PP((void)); +extern int32 DVIMark PP((void)); +extern int32 Dgetc PP((void)); +extern int32 Dget1byte PP((void)); +extern int32 Dget2byte PP((void)); +extern int32 Dget3byte PP((void)); +extern int32 Dsign1byte PP((void)); +extern int32 Dsign2byte PP((void)); +extern int32 Dsign3byte PP((void)); +extern int32 Dsign4byte PP((void)); +extern int Tgetc PP((void)); +extern void readtfmword PP((void)); +extern void cmd1byte PP((int32 cmd)); +extern void cmd2byte PP((int32 cmd)); +extern void cmd4byte PP((int32 cmd)); +extern void cmdSigned PP((int32 cmd, int32 numbytes)); +extern void OutputByte PP((int32 b)); +extern void Output2Byte PP((int32 i)); +extern void Output4Byte PP((int32 i)); +extern char *xmalloc PP((unsigned int size)); +extern Item *NewItem PP((int what)); +extern void pushItem PP((int depth, Item *newthing)); +extern void arccirclehandle PP((int32 figdepth, + double scalefact, + int32 cx, + int32 cy, + int32 radius, + int32 ang1, + int32 ang2, + int32 (*contpts)[2], + int32 nknots, + int32 dvih, + int32 dviv, + int thk, + VectKind vec, + LineStyle patt, + int32 minx, + int32 maxx, + int32 miny, + int32 maxy, + int32 tx, + int32 ty, + double sx, + double sy, + double r)); +extern void beamhandle PP((int32 depth, + int32 siz, + BeamKind bk, + int32 x1, + int32 y1, + int32 x2, + int32 y2)); +extern void figurehandle PP((Item *globalsymlist, Item *symbollist, int32 dopush)); +extern void labelhandle PP((int32 depth, + double scalefact, + int32 lax, + int32 lay, + int32 dvih, + int32 dviv, + int32 style, + char *phrase, + int32 tx, + int32 ty)); +extern void linehandle PP((int32 figdepth, + double scalefact, + int32 x1, + int32 y1, + int32 x2, + int32 y2, + int32 dvih, + int32 dviv, + int thk, + VectKind vk, + LineStyle patt, + int32 minx, + int32 maxx, + int32 miny, + int32 maxy, + int32 tx, + int32 ty, + double sx, + double sy, + double r)); +extern void splinehandle PP((int32 figdepth, + double scalefact, + SplineKind thetype, + int isclosed, + int32 markdiam, + int32 (*contpts)[2], + int32 nknots, + int32 dvih, + int32 dviv, + int thk, + VectKind vec, + LineStyle patt, + int32 minx, + int32 maxx, + int32 miny, + int32 maxy, + int32 tx, + int32 ty, + double sx, + double sy, + double r)); +extern void tieslurhandle PP((int32 depth, + int32 (*pts_)[2], + int32 numk, + int minthick, + int maxthick)); +extern void ttsplhandle PP((int32 figdepth, + double scalefact, + SplineKind thetype, + int isclosed, + int32 markdiam, + int32 (*contpts_)[2], + VThickness *ttks_, + int32 nknots, + int32 dvih, + int32 dviv, + VectKind vec, + LineStyle patt, + int32 minx, + int32 maxx, + int32 miny, + int32 maxy, + int32 tx, + int32 ty, + double sx, + double sy, + double r)); +extern void defineCircleCpts PP((int32 rad, + int32 centx, + int32 centy, + int32 (*CircleCpt)[2], + int32 *numpts)); +extern void definearcpts PP((int32 rad, + int32 centx, + int32 centy, + int32 startang, + int32 stopang, + int32 (*cpts)[2], + int32 *nknots)); +extern void layline PP((int32 xl, + int32 yb, + int32 xr, + int32 yt, + int32 fontindex, + LineStyle pattern, + int useVecfontOnly)); +extern void layAspline PP((SplineKind thetype, + int isclosed, + int isanArc, + int32 domarks, + int32 (*cpts)[2], + int32 numpts, + int thick_, + VectKind vkind, + LineStyle patt)); +extern void layNspline PP((SplineKind thetype, + int isclosed, + int isitaslur, + int32 domarks, + int32 (*cpts)[2], + int32 numpts, + VThickness *thickmatrix, + VectKind vkind, + LineStyle patt)); +extern void clampthickness PP((VThickness *thic)); +extern void isetpos PP((int posx, int posy)); +extern void isetfont PP((int DVINum)); diff --git a/macros/latex209/contrib/textyl/src/io.c b/macros/latex209/contrib/textyl/src/io.c new file mode 100644 index 0000000000..c2102bde17 --- /dev/null +++ b/macros/latex209/contrib/textyl/src/io.c @@ -0,0 +1,347 @@ +#include "defs.h" +#include "globals.h" + +static struct DVIBuftype +{ + int32 TotByteLen, curstrindex; + int32 maxlen; + short *Dstring; +} GDVIBuf; + +/* + * NOTATION:: All procedures that put a dvi-command into the temporary buffer are prefixed with "cmd"... Functions that deal + * with reading .tfm files are prefixed with "T" or have "tfm" in their names. Functions that deal with reading DVI files are + * prefixed with a "D". + */ + +/*--------------------------------------------*/ +void +cmd1byte(cmd) + int32 cmd; +{ + char *realloc PP((char *, unsigned)); + + if (GDVIBuf.curstrindex >= GDVIBuf.maxlen) + { /* buffer full */ + GDVIBuf.maxlen *= 2; + GDVIBuf.Dstring = (short *) realloc((char *)GDVIBuf.Dstring, (unsigned)sizeof(*GDVIBuf.Dstring) * GDVIBuf.maxlen); + } + GDVIBuf.Dstring[GDVIBuf.curstrindex] = cmd; + /* insert command byte */ + GDVIBuf.TotByteLen++; + GDVIBuf.curstrindex++; +} + + +/*---------------------------------------------------*/ +void +cmd2byte(cmd) + int32 cmd; +{ + cmd1byte((cmd >> 8) & 0xff); + cmd1byte(cmd & 0xff); +} + +/*---------------------------------------------------*/ +void +cmd4byte(cmd) + int32 cmd; +{ + cmd1byte((cmd >> 24) & 0xff); + cmd1byte((cmd >> 16) & 0xff); + cmd1byte((cmd >> 8) & 0xff); + cmd1byte(cmd & 0xff); +} + + +/*---------------------------------------------------*/ +/* + * ### may be system dependent as integers are assumed to be signed 32-bits + */ + +void +cmdSigned(i, numbytes) + int32 i, numbytes; +{ + int32 tmp; + + if (numbytes == 4) + { + cmd4byte(i); + return; + } + tmp = i; + if (numbytes == 3) + { + if (tmp < 0) + tmp += TWO24; + cmd1byte(tmp / TWO16); + tmp &= TWO16 - 1; + cmd1byte(tmp / 256); + } + if (numbytes == 2) + { + if (tmp < 0) + tmp += TWO16; + cmd1byte(tmp / 256); + } + if (numbytes == 1) + { + if (tmp < 0) + tmp += 256; + } + cmd1byte(tmp & 255); /* for all */ + + /* <= 3 bytes */ +} + +/*---------------------------------------------------*/ +int +Tgetc() +{ + int c; + + if ((c = getc(tfmfile)) == EOF) + { + complain(ERRREALBAD); + fprintf(logfile, " early EOF of tfm file! \n"); + return (0); + } + return (c & 0xff); +} + + +/*---------------------------------------------------*/ +void +readtfmword() +{ + b0 = Tgetc(); + b1 = Tgetc(); + b2 = Tgetc(); + b3 = Tgetc(); +} + + +/*---------------------------------------------------*/ +int32 +Dgetc() +{ + int c; + + if ((c = getc(dvifile)) == EOF) + return (0); + return (c & 0xff); +} + +/*---------------------------------------------------*/ +int32 +Dget1byte() +{ + int c; + + if ((c = getc(dvifile)) == EOF) + return (0); + else + { + cmd1byte(c); + return (c & 0xff);; + } +} + + +/*---------------------------------------------------*/ +int32 +Dsign1byte() +{ + int32 c; + + c = Dgetc(); + if (c >= 128) + c -= 256; + cmd1byte(c); + return (c); +} + + +/*---------------------------------------------------*/ +int32 +Dget2byte() +{ + int32 a, b; + + a = Dgetc(); + b = Dgetc(); + cmd1byte(a); + cmd1byte(b); + return ((a << 8) | b); +} + + +/*---------------------------------------------------*/ +int32 +Dsign2byte() +{ + int32 a, b; + + a = Dgetc(); + b = Dgetc(); + cmd1byte(a); + cmd1byte(b); + if (a < 128) + return ((a >> 8) | b); + else + return ((a - 256) * 256 + b); +} + + +/*---------------------------------------------------*/ +int32 +Dget3byte() +{ + int32 a, b, c; + + a = Dgetc(); + b = Dgetc(); + c = Dgetc(); + cmd1byte(a); + cmd1byte(b); + cmd1byte(c); + return ((a << 16) | (b << 8) | c); +} + + +/*---------------------------------------------------*/ +int32 +Dsign3byte() +{ + int32 a, b, c; + + a = Dgetc(); + b = Dgetc(); + c = Dgetc(); + cmd1byte(a); + cmd1byte(b); + cmd1byte(c); + if (a < 128) + return ((a << 16) | (b << 8) | c); + else + return ((a - 256) * 256 + b) * 256 + c; +} + + +/*---------------------------------------------------*/ +int32 +Dsign4byte() +{ + int32 a, b, c, d; + + a = Dgetc(); + b = Dgetc(); + c = Dgetc(); + d = Dgetc(); + cmd1byte(a); + cmd1byte(b); + cmd1byte(c); + cmd1byte(d); + if (a < 128) + return (((a * 256 + b) * 256 + c) * 256 + d); + else + return ((((a - 256) * 256 + b) * 256 + c) * 256 + d); +} + + +/*---------------------------------------------------*/ +/* + * write a byte out to the ouput file, but if we encounter the font flag, define the new fonts, and continue + */ +void +OutputByte(b) + int32 b; +{ + if (b == OURFONTFLAG) + { /* our special macro-flag */ + b = NOP; /* nullify it */ + if (!didnewfonts) + { + didnewfonts = true; + defineNewfonts(); /* expand the defns in the outfile itself */ + } + } /* if */ + putc(b, outputfil); + TotBytesWritten++; /* keep count of all bytes */ +} + + +/*---------------------------------------------------*/ +void +Output2Byte(i) + int32 i; +{ + OutputByte((i >> 8) & 0xff); + OutputByte(i & 0xff); +} + + +/*---------------------------------------------------*/ +void +Output4Byte(i) + int32 i; +{ + OutputByte((i >> 24) & 0xff); + OutputByte((i >> 16) & 0xff); + OutputByte((i >> 8) & 0xff); + OutputByte(i & 0xff); +} + +/*---------------------------------------------------*/ +void +InitDVIBuf() +{ + GDVIBuf.maxlen = 2048; + GDVIBuf.Dstring = (short *) xmalloc(sizeof(*GDVIBuf.Dstring) * 2048); + GDVIBuf.TotByteLen = 0; + GDVIBuf.curstrindex = 0; +} + + +/*---------------------------------------------------*/ +void +ClearDVIBuf() +{ + GDVIBuf.TotByteLen = 0; + GDVIBuf.curstrindex = 0; +} + + +/*---------------------------------------------------*/ +void +WriteDVIBuf() +{ + int32 i; + int32 b; + + for (i = 0; i < GDVIBuf.curstrindex; i++) + { + b = GDVIBuf.Dstring[i]; + OutputByte(b); + } + ClearDVIBuf(); +} + + +/*---------------------------------------------------*/ +void +BackupInBuf(nbytes) + int nbytes; +{ + GDVIBuf.curstrindex -= nbytes; /* points to position to-be-filled */ + GDVIBuf.TotByteLen -= nbytes; +} + + +/*-----------------------------------------------------*/ +int32 +DVIMark() +{ + return (GDVIBuf.TotByteLen); +} diff --git a/macros/latex209/contrib/textyl/src/spline.c b/macros/latex209/contrib/textyl/src/spline.c new file mode 100644 index 0000000000..6ac8c744e5 --- /dev/null +++ b/macros/latex209/contrib/textyl/src/spline.c @@ -0,0 +1,660 @@ +#include "defs.h" +#include "globals.h" +#include "tables.h" + +/* &&Module spline.p */ +/* + * Procedures below may make free use of the global variables arrayXY [list of control points] pointmatrix [list of spline + * segments] knot [list of spline knots] catrommtx [matrix for Catmull-Rom splines] bsplmtx [matrix for B-splines] + * lastPoint, intervals + */ + + +/*-----------------------------------------------------*/ +int +max(a, b) + int a, b; +{ + if (a > b) + return a; + else + return b; +} + + +/*-----------------------------------------------------*/ +int +min(a, b) + int a, b; +{ + if (a < b) + return a; + else + return b; +} + +/*-----------------------------------------------------*/ +static void +matXvector(m, v, result) + double (*m)[4]; + double *v, *result; +{ + /* IN */ + /* IN */ + /* OUT */ + double t[4]; + + t[0] = v[0] * m[0][0] + v[1] * m[0][1] + v[2] * m[0][2] + v[3] * m[0][3]; + t[1] = v[0] * m[1][0] + v[1] * m[1][1] + v[2] * m[1][2] + v[3] * m[1][3]; + t[2] = v[0] * m[2][0] + v[1] * m[2][1] + v[2] * m[2][2] + v[3] * m[2][3]; + t[3] = v[0] * m[3][0] + v[1] * m[3][1] + v[2] * m[3][2] + v[3] * m[3][3]; + result[0] = t[0]; + result[1] = t[1]; + result[2] = t[2]; + result[3] = t[3]; +} + + +/*-----------------------------------------------------*/ +/* actually the dot-product */ +static double +vecXvec(v1, v2) + double *v1, *v2; +{ + return (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2] + v1[3] * v2[3]); +} + + +/*------------------------------------------------------*/ +/* basXctl is the pre-computed BasisMatrix times the control-point vector */ + +static double +splinePosition(basXctl, t) + double *basXctl; + double t; +{ + /* IN */ + double tvect[4]; /* vector of t values for spline matrix */ + + tvect[3] = 1.0; + tvect[2] = t; + tvect[1] = t * t; + if (tvect[1] <= MINREAL)/* avoid underflow problems */ + tvect[1] = 0.0; + tvect[0] = t * tvect[1];/* t^3 */ + return (vecXvec(tvect, basXctl)); +} + + +/*-------------------------------------------------*/ +static int +TwoToThe(n) + int n; +{ + int i, tmp; + + for (i = 0, tmp = 1; i < n; i++) + tmp *= 2; + return (tmp); +} + +/*------------------------------------------------------*/ +double +distance(x0, y0, x1, y1) + double x0, y0, x1, y1; +{ + return (sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0))); +} + + +/*------------------------------------------------------*/ +/* + * compute the number of subdivisions for this span. We do this by a quadrature method and a simple linear-distance metric. + * This is not optimal in the number of subdivisions actually required, but is computationally efficient and accurate to the + * nearest power of 2 . + */ +static int32 +numsubdivisions(XtimesBas, YtimesBas, resolution) + double *XtimesBas, *YtimesBas; + int32 resolution; +{ + int32 n; + double t, x0, y0, xt, yt; + + x0 = splinePosition(XtimesBas, 0.0); + y0 = splinePosition(YtimesBas, 0.0); + + t = 1.0; + n = 0; + xt = splinePosition(XtimesBas, t); + yt = splinePosition(YtimesBas, t); + + while ((int32) floor(distance(x0, y0, xt, yt) + 0.5) > resolution || n < 1) + { + t /= 2.0; /* perform the quadrature */ + n++; + xt = splinePosition(XtimesBas, t); + yt = splinePosition(YtimesBas, t); + } /* while */ + return (TwoToThe(n)); +} + + +/*------------------------------------------------------------------------*/ +/* + * compute new control vertices such that the resulting spline will interpolate through the old control points. This will work + * as int32 as the actual arc length between consecutive nodes does not vary from span to span. The method is noted in Wu and + * Abel's CACM 20(10) Oct 77 paper but the actual working method is from Barsky and Greenberg's paper in CG&IP 14(3) Nov 1980 + * pp.203-226 + */ +static void +invertsplvertices(numpts, isclosed, xys) + int32 numpts; + int isclosed; +int32(*xys)[2]; +{ + /* INOUT */ + int32 i; + double beta[MAXCTLPTS + 1], Xrprime[MAXCTLPTS + 1], Yrprime[MAXCTLPTS + 1]; + ControlPoints tempxys; + + /* compute the values of beta */ + beta[1] = 0.25; + for (i = 2; i <= numpts + 1; i++) + beta[i] = 1.0 / (4.0 - beta[i - 1]); + + /* and the r primes from the original vertices */ + Xrprime[1] = beta[1] * xys[1][0] * 5.0; + Yrprime[1] = beta[1] * xys[1][1] * 5.0; + for (i = 2; i < numpts; i++) + { + Xrprime[i] = beta[i] * (6.0 * xys[i][0] - Xrprime[i - 1]); + Yrprime[i] = beta[i] * (6.0 * xys[i][1] - Yrprime[i - 1]); + } /* for */ + Xrprime[numpts] = beta[numpts] * (5.0 * xys[numpts][0] - Xrprime[numpts - 1]); + Yrprime[numpts] = beta[numpts] * (5.0 * xys[numpts][1] - Yrprime[numpts - 1]); + + /* Now perform the back-substitution from the bottom up */ + tempxys[numpts][0] = (int32) floor(Xrprime[numpts] + 0.5); + tempxys[numpts][1] = (int32) floor(Yrprime[numpts] + 0.5); + for (i = numpts - 1; i >= 1; i--) + { + tempxys[i] + [0] = (int32) floor(Xrprime[i] - beta[i] * tempxys[i + 1][0] + 0.5); + tempxys[i] + [1] = (int32) floor(Yrprime[i] - beta[i] * tempxys[i + 1][1] + 0.5); + } + + if (isclosed) + { + /* + * at this point, we've probably been through one control-point adjustment, so let's not muck it up + */ + tempxys[numpts + 1][0] = tempxys[1][0]; + tempxys[numpts + 1][1] = tempxys[1][1]; + tempxys[numpts + 2][0] = tempxys[2][0]; + tempxys[numpts + 2][1] = tempxys[2][1]; + tempxys[0][0] = tempxys[numpts][0]; + tempxys[0][1] = tempxys[numpts][1]; + /* copy them back */ + for (i = 0; i <= numpts + 2; i++) + { + xys[i][0] = tempxys[i][0]; + xys[i][1] = tempxys[i][1]; + } + return; + } /* closed */ + /* copy back */ + for (i = 2; i < numpts; i++) + { + xys[i][0] = tempxys[i][0]; + xys[i][1] = tempxys[i][1]; + } + + /* open */ +} + + +/*-----------------------------------------------------*/ +/* + * adjust the list of control points so that we can use it for B-spline interpolation. Add any "phantom" vertices necessary so + * that the end conditions will be correct for interpolation + */ +static void +Bctlptadjust(isclosed, isarc, n, xys, thx) + int isclosed, isarc; + int32 *n; +int32(*xys)[2]; + VThickness *thx; +{ /* ctlpt adjust */ + /* INOUT */ + /* INOUT */ + /* INOUT */ + int32 j; + ControlPoints tmp; + ThickAryType tmpthx; + int32 FORLIM; + + if (isclosed) + { + if (*n == 2) + { + complain(ERRBAD); + fprintf(logfile, + "A closed spline requires more than 2 control points \n"); + fprintf(logfile, "making a temporary fix in order to continue...\n"); + xys[3][0] = xys[1][0]; + xys[3][1] = xys[1][1]; + } + + FORLIM = *n; + for (j = 1; j <= FORLIM; j++) + { + tmp[j][0] = xys[j][0]; + tmp[j][1] = xys[j][1]; + tmpthx[j] = thx[j]; + } + /* Now take care of the 'phantom' vertices */ + tmp[*n + 1][0] = xys[1][0]; + tmp[*n + 1][1] = xys[1][1]; + tmpthx[*n + 1] = thx[1]; + tmp[*n + 2][0] = xys[2][0]; + tmp[*n + 2][1] = xys[2][1]; + tmpthx[*n + 2] = thx[2]; + tmp[*n + 3][0] = xys[3][0]; + tmp[*n + 3][1] = xys[3][1]; + tmpthx[*n + 3] = thx[3]; + + if (!isarc) + { + tmp[0][0] = xys[*n][0]; /* wrap around to the real last point */ + tmp[0][1] = xys[*n][1]; + tmpthx[0] = thx[*n]; + } + else + { + tmp[0][0] = xys[0][0]; + tmp[0][1] = xys[0][1]; + tmpthx[0] = thx[0]; + } + + (*n)++; /* we supplied the 'last' point for the user */ + + FORLIM = *n + 2; + for (j = 0; j <= FORLIM; j++) + { + xys[j][0] = tmp[j][0]; + xys[j][1] = tmp[j][1]; + thx[j] = tmpthx[j]; + } /* for */ + return; + } /* if closed */ + /* + * here, we have to supply the last 'real' point for the user, and add three phantoms-- one before, and two after + */ + + + if (!isarc) + { + tmp[0][0] = xys[1][0] * 2 - xys[2][0]; + tmp[0][1] = xys[1][1] * 2 - xys[2][1]; + } + else + { + tmp[0][0] = xys[0][0]; + tmp[0][1] = xys[0][1]; + } + tmpthx[0] = thx[1]; + + FORLIM = *n; + for (j = 1; j <= FORLIM; j++) + { + tmp[j][0] = xys[j][0]; + tmp[j][1] = xys[j][1]; + tmpthx[j] = thx[j]; + } + + tmp[*n + 1][0] = xys[*n][0] * 2 - xys[*n - 1][0]; + tmp[*n + 1][1] = xys[*n][1] * 2 - xys[*n - 1][1]; + tmpthx[*n + 1] = thx[*n]; + + tmp[*n + 2][0] = tmp[*n + 1][0]; + tmp[*n + 2][1] = tmp[*n + 1][1]; + tmpthx[*n + 2] = thx[*n]; + + FORLIM = *n + 2; + for (j = 0; j <= FORLIM; j++) + { + xys[j][0] = tmp[j][0]; + xys[j][1] = tmp[j][1]; + thx[j] = tmpthx[j]; + } /* for */ + + /* OPEN SPLINE */ + /* if open */ +} + + + +/*-----------------------------------------------------*/ +/* + * adjust the list of control points so that we can use it for simple Catmull-Rom spline interpolation. Add any "phantom" + * vertices necessary so that the end conditions will be correct for interpolation + */ +static void +CRctlptadjust(isclosed, isarc, n, xys, thx) + int isclosed, isarc; + int32 *n; +int32(*xys)[2]; + VThickness *thx; +{ /* ctlpt adjust */ + /* INOUT */ + /* INOUT */ + /* INOUT */ + int32 j; + ControlPoints tmp; + ThickAryType tmpthx; + int32 FORLIM; + + if (isclosed) + { + if (*n == 2) + { + complain(ERRBAD); + fprintf(logfile, + "A closed spline requires more than 2 control points \n"); + fprintf(logfile, "making a temporary fix in order to continue...\n"); + xys[3][0] = xys[1][0]; + xys[3][1] = xys[1][1]; + } + + + FORLIM = *n; + for (j = 1; j <= FORLIM; j++) + { + tmp[j][0] = xys[j][0]; + tmp[j][1] = xys[j][1]; + tmpthx[j] = thx[j]; + } + /* the phantom vertices */ + tmp[*n + 1][0] = xys[1][0]; + tmp[*n + 1][1] = xys[1][1]; + tmpthx[*n + 1] = thx[1]; + tmp[*n + 2][0] = xys[2][0]; + tmp[*n + 2][1] = xys[2][1]; + tmpthx[*n + 2] = thx[2]; + tmp[*n + 3][0] = xys[3][0]; + tmp[*n + 3][1] = xys[3][1]; + tmpthx[*n + 3] = thx[3]; + + if (!isarc) + { + tmp[0][0] = xys[*n][0]; /* wrap around to the real last point */ + tmp[0][1] = xys[*n][1]; + tmpthx[0] = thx[*n]; + } + else + { + tmp[0][0] = xys[0][0]; + tmp[0][1] = xys[0][1]; + tmpthx[0] = thx[0]; + } + (*n)++; /* we supplied the 'last' point for the user */ + + FORLIM = *n + 2; + for (j = 0; j <= FORLIM; j++) + { + xys[j][0] = tmp[j][0]; + xys[j][1] = tmp[j][1]; + thx[j] = tmpthx[j]; + } /* for */ + return; + } /* if closed */ + /* + * here, we have to supply the last 'real' point for the user, and add three phantoms-- one before, and two after + */ + + if (!isarc) + { + tmp[0][0] = xys[1][0]; /* double the first point */ + tmp[0][1] = xys[1][1]; + } + else + { + tmp[0][0] = xys[0][0]; + tmp[0][1] = xys[0][1]; + } + tmpthx[0] = thx[1]; + + FORLIM = *n; + for (j = 1; j <= FORLIM; j++) + { + tmp[j][0] = xys[j][0]; + tmp[j][1] = xys[j][1]; + tmpthx[j] = thx[j]; + } + + tmp[*n + 1][0] = xys[*n][0]; /* and triple the last */ + tmp[*n + 1][1] = xys[*n][1]; + tmpthx[*n + 1] = thx[*n]; + tmp[*n + 2][0] = xys[*n][0]; + tmp[*n + 2][1] = xys[*n][1]; + tmpthx[*n + 2] = thx[*n]; + + FORLIM = *n + 2; + for (j = 0; j <= FORLIM; j++) + { + xys[j][0] = tmp[j][0]; + xys[j][1] = tmp[j][1]; + thx[j] = tmpthx[j]; + } /* for */ + + /* OPEN SPLINE */ + /* if open */ +} /* ctlpt adjust */ + + + +/*----------------------------------------------------------*/ + +static void +interpsplines(splinetype, isclosed, isanArc, linepatt, + basismatrix, numctls, arrayXY, pointmatrix, + varythicks, thickmatrix, TTmatrix) + SplineKind splinetype; + int isclosed, isanArc; + LineStyle linepatt; + double (*basismatrix)[4]; + int32 numctls; +int32(*arrayXY)[2]; +int32(*pointmatrix)[2]; + int varythicks; + VThickness *thickmatrix, *TTmatrix; +{ /* interp splines */ + /* IN */ + /* IN */ + /* OUT */ + /* IN */ + /* OUT */ + double xctl[4], yctl[4]; /* vectors of x, y posits of control points */ + double wctl[4];/* vector of thicknesses at each ctl pt */ + double t, incr; + int32 Pi; /* P sub i */ + int32 currpt; + ScaledPts theresolution; + + if (!isclosed && isanArc) /* lie a little */ + numctls++; + + switch (splinetype) + { + + case BSPL: + Bctlptadjust(isclosed, isanArc, &numctls, arrayXY, thickmatrix); + break; + + case CARD: + case CATROM: + CRctlptadjust(isclosed, isanArc, &numctls, arrayXY, thickmatrix); + break; + + case INTBSPL: + if (isclosed) + { + Bctlptadjust(true, isanArc, &numctls, arrayXY, thickmatrix); + invertsplvertices(numctls, true, arrayXY); + } + else + { + invertsplvertices(numctls, false, arrayXY); + Bctlptadjust(false, isanArc, &numctls, arrayXY, thickmatrix); + } /* else */ + break; + /* Interpolating Bsplines */ + } + + if (!isclosed && isanArc) /* UN-lie a little */ + numctls--; + + + /* + * this is the scheme: val := t-vector * Basis matrix * point matrix [t^3 t^2 t 1] * [[Ms]] * [Pi-1 + * Pi Pi+1 Pi+2] where "Pi-1" is "P sub (i-1)", etc. + * + * But we do this in a round about way: Point matrix * basis then * t-vector will yield the single value + * + * there are certainly faster ways to do this, but this is the easiest to understand + */ + + currpt = 1; + switch (linepatt) + { + + case solid: + theresolution = MAXVECLENsp; + break; + + case dotted: + case dashed: + case dotdash: /* ### */ + theresolution = MAXVECLENsp * 3; + break; + } + + for (Pi = 1; Pi < numctls; Pi++) + { + xctl[0] = float_(arrayXY[Pi - 1][0]); + xctl[1] = float_(arrayXY[Pi][0]); + xctl[2] = float_(arrayXY[Pi + 1][0]); + xctl[3] = float_(arrayXY[Pi + 2][0]); + yctl[0] = float_(arrayXY[Pi - 1][1]); + yctl[1] = float_(arrayXY[Pi][1]); + yctl[2] = float_(arrayXY[Pi + 1][1]); + yctl[3] = float_(arrayXY[Pi + 2][1]); + matXvector(basismatrix, xctl, xctl); + matXvector(basismatrix, yctl, yctl); + + /* + * compute the delta-t increment for this segment based on a metric for subdivision + */ + intervals = numsubdivisions(xctl, yctl, theresolution); + if (linepatt == solid && intervals <= 2) + intervals *= 2; + incr = 1.0 / intervals; + + /* avoid over-flowing the "pointmatrix" */ + if (currpt + intervals - 1 >= MAXSPLINESEGS) + { + complain(ERRREALBAD); + fprintf(logfile, "error: Too many spline segments required.\n"); + fprintf(logfile, + " Reducing the number of control points to get output.\n"); + goto _L32; + } + + t = 0.0; + while (t < 0.999999999) + { + pointmatrix[currpt - 1][0] = (int32) floor(splinePosition(xctl, t) + 0.5); + pointmatrix[currpt - 1][1] = (int32) floor(splinePosition(yctl, t) + 0.5); + + if (varythicks) + { + wctl[0] = float_((int32) thickmatrix[Pi - 1]); + wctl[1] = float_((int32) thickmatrix[Pi]); + wctl[2] = float_((int32) thickmatrix[Pi + 1]); + wctl[3] = float_((int32) thickmatrix[Pi + 2]); + matXvector(catrommtx, wctl, wctl); /* requires using Catmull-Rom */ + TTmatrix[currpt] = (int32) floor(splinePosition(wctl, t) + 0.5); + } + + t += incr; + currpt++; + } /* while loop */ + + + } /* for loop */ + +_L32: + /* the END-condtion */ + pointmatrix[currpt - 1][0] = (int32) floor(splinePosition(xctl, 1.0) + 0.5); + pointmatrix[currpt - 1][1] = (int32) floor(splinePosition(yctl, 1.0) + 0.5); + if (varythicks) + { + wctl[0] = thickmatrix[numctls - 2]; + wctl[1] = thickmatrix[numctls - 1]; + wctl[2] = thickmatrix[numctls]; + wctl[3] = thickmatrix[numctls + 1]; + matXvector(catrommtx, wctl, wctl); /* requires using Catmull-Rom */ + TTmatrix[currpt] = (int32) floor(splinePosition(wctl, 1.0) + 0.5); + } + + lastPoint = currpt; + +} /* interpsplines */ + + +/*----------------------------------------------------------------*/ +void +drawSpline(splinetype, isclosed, isanArc, patt, numctls, arrayXY, + pointmatrix, varythicks, thickmatrix, TTmatrix) + SplineKind splinetype; + int isclosed, isanArc; + LineStyle patt; + int32 numctls; +int32(*arrayXY)[2]; +int32(*pointmatrix)[2]; + int varythicks; + VThickness *thickmatrix, *TTmatrix; +{ + /* IN */ + /* OUT */ + /* IN */ + /* OUT */ + lastPoint = 0; + + + switch (splinetype) + { + + case CATROM: + interpsplines(splinetype, isclosed, isanArc, patt, catrommtx, numctls, + arrayXY, pointmatrix, varythicks, thickmatrix, TTmatrix); + break; + + case CARD: + interpsplines(splinetype, isclosed, isanArc, patt, cardmtx, numctls, + arrayXY, pointmatrix, varythicks, thickmatrix, TTmatrix); + break; + + case BSPL: + interpsplines(splinetype, isclosed, isanArc, patt, bsplmtx, numctls, + arrayXY, pointmatrix, varythicks, thickmatrix, TTmatrix); + break; + + case INTBSPL: + interpsplines(splinetype, isclosed, isanArc, patt, bsplmtx, numctls, + arrayXY, pointmatrix, varythicks, thickmatrix, TTmatrix); + break; + } /* Case */ +} diff --git a/macros/latex209/contrib/textyl/src/tables.c b/macros/latex209/contrib/textyl/src/tables.c new file mode 100644 index 0000000000..382dd8ce17 --- /dev/null +++ b/macros/latex209/contrib/textyl/src/tables.c @@ -0,0 +1,157 @@ +#include "tables.h" + +struct vecinfo vectab[] = +{ + {15.9688, 0.0, 0.9981, 86.4237}, + {15.8764, 0.0, 1.9846, 82.8750}, + {15.7260, 0.0, 2.9486, 79.3803}, + {15.5223, 0.0, 3.8806, 75.9638}, + {15.2717, 0.0, 4.7724, 72.6460}, + {14.9813, 0.0, 5.6180, 69.4440}, + {14.6585, 0.0, 6.4131, 66.3706}, + {14.3108, 0.0, 7.1554, 63.4349}, + {13.9452, 0.0, 7.8442, 60.6422}, + {13.5680, 0.0, 8.4800, 57.9946}, + {13.1847, 0.0, 9.0645, 55.4915}, + {12.8000, 0.0, 9.6000, 53.1301}, + {12.4178, 0.0, 10.0895, 50.9061}, + {12.0412, 0.0, 10.5361, 48.8141}, + {11.6726, 0.0, 10.9431, 46.8476}, + {11.3137, 0.0, 11.3137, 45.0000}, + {10.9431, 0.0, 11.6726, 43.1524}, + {10.5361, 0.0, 12.0412, 41.1859}, + {10.0895, 0.0, 12.4178, 39.0939}, + {9.6000, 0.0, 12.8000, 36.8699}, + {9.0645, 0.0, 13.1847, 34.5085}, + {8.4800, 0.0, 13.5680, 32.0054}, + {7.8442, 0.0, 13.9452, 29.3578}, + {7.1554, 0.0, 14.3108, 26.5651}, + {6.4131, 0.0, 14.6585, 23.6294}, + {5.6180, 0.0, 14.9813, 20.5560}, + {4.7724, 0.0, 15.2717, 17.3540}, + {3.8806, 0.0, 15.5223, 14.0362}, + {2.9486, 0.0, 15.7260, 10.6197}, + {1.9846, 0.0, 15.8764, 7.1250}, + {0.9981, 0.0, 15.9688, 3.5763}, + {0.0, 0.0, 16.0000, 0.0000}, + {0.0, 0.9981, 15.9688, -3.5763}, + {0.0, 1.9846, 15.8764, -7.1250}, + {0.0, 2.9486, 15.7260, -10.6197}, + {0.0, 3.8806, 15.5223, -14.0362}, + {0.0, 4.7724, 15.2717, -17.3540}, + {0.0, 5.6180, 14.9813, -20.5560}, + {0.0, 6.4131, 14.6585, -23.6294}, + {0.0, 7.1554, 14.3108, -26.5651}, + {0.0, 7.8442, 13.9452, -29.3578}, + {0.0, 8.4800, 13.5680, -32.0054}, + {0.0, 9.0645, 13.1847, -34.5085}, + {0.0, 9.6000, 12.8000, -36.8699}, + {0.0, 10.0895, 12.4178, -39.0939}, + {0.0, 10.5361, 12.0412, -41.1859}, + {0.0, 10.9431, 11.6726, -43.1524}, + {0.0, 11.3137, 11.3137, -45.0000}, + {0.0, 11.6726, 10.9431, -46.8476}, + {0.0, 12.0412, 10.5361, -48.8141}, + {0.0, 12.4178, 10.0895, -50.9061}, + {0.0, 12.8000, 9.6000, -53.1301}, + {0.0, 13.1847, 9.0645, -55.4915}, + {0.0, 13.5680, 8.4800, -57.9946}, + {0.0, 13.9452, 7.8442, -60.6422}, + {0.0, 14.3108, 7.1554, -63.4349}, + {0.0, 14.6585, 6.4131, -66.3706}, + {0.0, 14.9813, 5.6180, -69.4440}, + {0.0, 15.2717, 4.7724, -72.6460}, + {0.0, 15.5223, 3.8806, -75.9638}, + {0.0, 15.7260, 2.9486, -79.3803}, + {0.0, 15.8764, 1.9846, -82.8750}, + {0.0, 15.9688, 0.9981, -86.4237}, + {8.0000, 0.0, 0.0, 90.0000}, + {7.9382, 0.0, 0.9923, 82.8750}, + {7.7611, 0.0, 1.9403, 75.9638}, + {7.4906, 0.0, 2.8090, 69.4440}, + {7.1554, 0.0, 3.5777, 63.4349}, + {6.7840, 0.0, 4.2400, 57.9946}, + {6.4000, 0.0, 4.8000, 53.1301}, + {6.0206, 0.0, 5.2680, 48.8141}, + {5.6569, 0.0, 5.6569, 45.0000}, + {5.2680, 0.0, 6.0206, 41.1859}, + {4.8000, 0.0, 6.4000, 36.8699}, + {4.2400, 0.0, 6.7840, 32.0054}, + {3.5777, 0.0, 7.1554, 26.5651}, + {2.8090, 0.0, 7.4906, 20.5560}, + {1.9403, 0.0, 7.7611, 14.0362}, + {0.9923, 0.0, 7.9382, 7.1250}, + {0.0, 0.0, 8.0000, 0.0000}, + {0.0, 0.9923, 7.9382, -7.1250}, + {0.0, 1.9403, 7.7611, -14.0362}, + {0.0, 2.8090, 7.4906, -20.5560}, + {0.0, 3.5777, 7.1554, -26.5651}, + {0.0, 4.2400, 6.7840, -32.0054}, + {0.0, 4.8000, 6.4000, -36.8699}, + {0.0, 5.2680, 6.0206, -41.1859}, + {0.0, 5.6569, 5.6569, -45.0000}, + {0.0, 6.0206, 5.2680, -48.8141}, + {0.0, 6.4000, 4.8000, -53.1301}, + {0.0, 6.7840, 4.2400, -57.9946}, + {0.0, 7.1554, 3.5777, -63.4349}, + {0.0, 7.4906, 2.8090, -69.4440}, + {0.0, 7.7611, 1.9403, -75.9638}, + {0.0, 7.9382, 0.9923, -82.8750}, + {0.0, 8.0000, 0.0, -90.0000}, + {4.0000, 0.0, 0.0, 90.0000}, + {3.8806, 0.0, 0.9701, 75.9638}, + {3.5777, 0.0, 1.7889, 63.4349}, + {3.2000, 0.0, 2.4000, 53.1301}, + {2.8284, 0.0, 2.8284, 45.0000}, + {2.4000, 0.0, 3.2000, 36.8699}, + {1.7889, 0.0, 3.5777, 26.5651}, + {0.9701, 0.0, 3.8806, 14.0362}, + {0.0, 0.0, 4.0000, 0.0000}, + {0.0, 0.9701, 3.8806, -14.0362}, + {0.0, 1.7889, 3.5777, -26.5651}, + {0.0, 2.4000, 3.2000, -36.8699}, + {0.0, 2.8284, 2.8284, -45.0000}, + {0.0, 3.2000, 2.4000, -53.1301}, + {0.0, 3.5777, 1.7889, -63.4349}, + {0.0, 3.8806, 0.9701, -75.9638}, + {0.0, 4.0000, 0.0, -90.0000}, + {2.0000, 0.0, 0.0, 90.0000}, + {1.7889, 0.0, 0.8944, 63.4349}, + {1.4142, 0.0, 1.4142, 45.0000}, + {0.8944, 0.0, 1.7889, 26.5651}, + {0.0, 0.0, 2.0000, 0.0000}, + {0.0, 0.8944, 1.7889, -26.5651}, + {0.0, 1.4142, 1.4142, -45.0000}, + {0.0, 1.7889, 0.8944, -63.4349}, + {0.0, 2.0000, 0.0, -90.0000}, + {1.0000, 0.0, 0.0, 90.0000}, + {0.7071, 0.0, 0.7071, 45.0000}, + {0.0, 0.0, 1.0000, 0.0000}, + {0.0, 0.7071, 0.7071, -45.0000}, + {0.0, 1.0000, 0.0, -90.0000}, + {0.0, 0.0, 0.0, -90.0000}, +}; + +double catrommtx[4][4] = +{ + -0.5, 1.5, -1.5, 0.5, + 1.0, -2.5, 2.0, -0.5, + -0.5, 0.0, 0.5, 0.0, + 0.0, 1.0, 0.0, 0.0, +}; + +double bsplmtx[4][4] = +{ + -1.0 / 6.0, 0.5, -0.5, 1.0 / 6.0, + 0.5, -1.0, 0.5, 0.0, + -0.5, 0.0, 0.5, 0.0, + 1.0 / 6.0, 2.0 / 3.0, 1.0 / 6.0, 0.0, +}; + +double cardmtx[4][4] = +{ + -1.0, 1.0, -1.0, 1.0, + 2.0, -2.0, 1.0, -1.0, + -1.0, 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, 0.0, +}; diff --git a/macros/latex209/contrib/textyl/src/tables.h b/macros/latex209/contrib/textyl/src/tables.h new file mode 100644 index 0000000000..ba62559e58 --- /dev/null +++ b/macros/latex209/contrib/textyl/src/tables.h @@ -0,0 +1,10 @@ +struct vecinfo +{ + double Cht, Cdp, Cwd, Angle; +}; + +extern struct vecinfo vectab[]; + +extern double catrommtx[4][4]; +extern double bsplmtx[4][4]; +extern double cardmtx[4][4]; diff --git a/macros/latex209/contrib/textyl/src/textyl.c b/macros/latex209/contrib/textyl/src/textyl.c new file mode 100644 index 0000000000..0f94cac1f7 --- /dev/null +++ b/macros/latex209/contrib/textyl/src/textyl.c @@ -0,0 +1,3422 @@ +/* Output from p2c, the Pascal-to-C translator */ +/* From input file "textyl.p" */ + +#include "defs.h" +#include "globals.h" +#include "tables.h" + +extern int abs PP((int)); + +/*---------------------------------------------------------- + TeXtyl line-drawing interface for TeX. + copyright (c) 1987 John S. Renner + All rights reserved. + +ABSTRACT: TeXtyl reads in a DVI file, and processes 'specials' + that refer to graphics capabilities that it knows about, + like line, spline, ThickThinSpline, and musical + beams and slurs. TeXtyl then outputs a new DVI file, + with the special-macros expanded and converted to + DVI-commands for character setting. + +DEPENDENCIES: Few assumptions about Pascal are assumed. All + identifiers are unique to eight characters. There are + notes to indicate system-dependencies. + I assume the standard definition of "READ(fil, x)" to be + equivalent to "x := fil^; GET(fil)" , and + "WRITE(fil, x)" == "fil^ := x; PUT(fil)" . + Arrays are passed by reference (VAR) for efficiency. + See also the "sysdependent" procedure; + Problem areas, or areas for expansion are marked with ### + +-------------------------------------------------------------*/ +/*-Revision History: + Jun. 1986 v1.0 Basic version of TeXtyl + Dec. 1986 v1.1 Added adaptive subdivision for spline + interpolation. Added Cardinal basis. + Mar. 1987 v1.2 Added F and W flags for beginfigure + to allow required and/or actual dimensions + to interface with files output by the + DP drawing program from Carnegie-Mellon + also various fixes + Apr. 1987 v1.3 Added linestyles (dotted, dashed, dotdashed) + Aug. 1991 Translated to C with p2c, then hacked a bit. (Ken Yap) +*/ + +/* ===========================TYPES============================= */ + +/* ---- PUBLIC types ---- */ + +typedef int MusIndex; +typedef int SplineSegments[MAXSPLINESEGS][2]; + +/* ----- Private Types ---- */ + +typedef struct FontInfRec +{ + int32 Cht, Cdp, Cwd; + double Angle; +} FontInfRec; + +/* vector font info */ + +typedef struct VectFontInfRec +{ + VectKind vkind; + int32 DesSize, PenSize; + VThickness psize; + int32 MaxVectLen; + charstring FontName; + int32 Cksum; + int Isdefined; + int32 DVIFontNum; + FontInfRec FontInfo[128]; +} VectFontInfRec; + +/* music font info */ + +typedef struct MusFontInfRec +{ + int32 DesSize, Family; + charstring FontName; + int32 Cksum; + int Isdefined; + int32 DVIFontNum, Staffsize, ghu, gvu; + FontInfRec FontInfo[128]; +} MusFontInfRec; + +/* + * representation of list of fonts that have to be defined + * before we output the BOP of the page we just scanned + */ + +typedef struct ToBeDefinedRec +{ + char which; + int32 indx; +} ToBeDefinedRec; + +/* ==============================VARS============================ */ + +/* ----- Private vars */ +static int32 ourxpos; /* internal x-position on page */ +static int32 ourypos; /* internal y-position on page */ + +static VectFontInfRec *VFontTable[SizVFontTable]; +static MusFontInfRec *MFontTable[SizMFontTable]; +/* the font tables, and the number of fonts defined in each */ +static int32 VFontsDefd, MFontsDefd, LFontsDefd; + +static int GDVIFN = 301; /* dvi font number currently in use */ + +/* table of fonts yet To-Be-Defined */ +static ToBeDefinedRec TBD[MAXTBDs]; +static int32 FTBDs; /* number of fonts to be defined for current page */ + +static Item *pageitems; +/* + * list of primitives in current use in the current figure on the current page + */ + +static int32 specstart = 0; +/* + * the place in the DVI buffer where the start of the special begins. + * this is so that we know how far to back up and over-write + * the old \special macro string with the cmds of our 'macro-expansion' + */ + +static int32 multifigure; /* depth of definition recursion of figures */ +static int skiptsclamp; /* DEBUG: should we skip post-clamping ties */ +static int ErrorOccurred; /* global flag in case some error happened */ + + +/* ----- End private vars */ + +static short tfm[TFMSIZE + 101]; + +static char s = 0; +struct stackrec +{ + int32 sh, sv, sw, sx, sy, sz; +} stack[STACKSIZE + 1]; + +static int32 inwidth[256]; +static int32 tfmchecksum; +static double conv, trueconv; +static int32 numerator, denominator; +static double mag, magfactor; +static int32 maxv, maxh, maxs, maxpages = 10000, totalpages; +static double resolution = 300.0; +static int inpostamble; +static int32 newbackptr = -1, oldbackptr = -1, p, k; + +/* forward declarations */ +static void definebeams PP((MusFontInfRec ** M)); +static void definevectors PP((VectFontInfRec ** Vec)); + +static jmp_buf _JL666; + +static int +opentfmfile(tfmname) + charstring tfmname; +{ + charstring thefilename; + char *path, *p, *q, *getenv PP((char *)); + + if ((path = getenv("TEXFONTS")) == 0) + path = DEFTEXFONTS; + if (tfmfile != NULL) + { + fclose(tfmfile); + tfmfile = NULL; + } + for (p = path; p != 0 && tfmfile == NULL; p = q ? q + 1 : 0) + { + if ((q = strchr(p, ':')) == 0) + strcpy(thefilename, p); + else + strncpy(thefilename, p, q - p); + strcat(thefilename, "/"); + if (strcmp(thefilename, "./") == 0) + thefilename[0] = '\0'; + strcat(thefilename, tfmname); + tfmfile = fopen(thefilename, "r"); + } + return (tfmfile != NULL); +} + +void +jumpout() +{ + longjmp(_JL666, 1); /* global label */ +} + +void +complain(severity) + int severity; +{ + fprintf(logfile, "Error in fig#%ld on page %ld\n", pgfigurenum, currpagenum); + switch (severity) + { + case ERRNOTBAD: + putc(ERRSIGNAL, logfile); + break; + case ERRBAD: + putc(ERRSIGNAL, logfile); + ErrorOccurred = true; + break; + case ERRREALBAD: + fprintf(logfile, "%c! ", ERRSIGNAL); + ErrorOccurred = true; + break; + } +} + +double +float_(i) + int32 i; +{ + return ((double) i); +} + +static int +tolowercase(let) + int let; +{ + return (isupper(let) ? tolower(let) : let); +} + +#define streq(a,b,n) (!strncmp((a),(b),(n))) + +/* + * Move the current DVI position to posx, posy by moving relatively from our current position and store the new position + */ +void +isetpos(posx, posy) + int posx, posy; +{ + ScaledPts dy, dx; + int32 numbytes; + + dx = posx - ourxpos; + dy = posy - ourypos; + numbytes = 1; + if (dx < 128 && dx >= -128) + numbytes = 1; + else if (dx < 32768 && dx >= -32768) + numbytes = 2; + else if (dx < TWO23 && dx >= -TWO23) + numbytes = 3; + else if (dx < TWO31 && dx >= -TWO31) + numbytes = 4; + else + { + complain(ERRREALBAD); + fprintf(logfile, "Panic: dx is too big/small in isetpos: %12ld\n", dx); + } + + cmd1byte(RIGHTLEFT + numbytes - 1); + /* number of bytes in its arg list */ + cmdSigned(dx, numbytes); + + numbytes = 1; + if (dy < 128 && dy >= -128) + numbytes = 1; + else if (dy < 32768 && dy >= -32768) + numbytes = 2; + else if (dy < TWO23 && dy >= -TWO23) + numbytes = 3; + else if (dy < TWO31 && dy >= -TWO31) + numbytes = 4; + else + { + complain(ERRREALBAD); + fprintf(logfile, "Panic: dy is too big/small in isetpos: %12ld\n", dy); + } + cmd1byte(DOWNUP + numbytes - 1); + cmdSigned(dy, numbytes); + ourxpos = posx; + ourypos = posy; +} + +/* put out a character */ +static void +iputchar(charno) + int charno; +{ + cmd1byte(PUT1); + cmd1byte(charno); +} + +/* + * set the font number, but only if it is different than the last one + * we accessed. + */ +void +isetfont(DVINum) + int DVINum; +{ + if (ourfontnum == DVINum) + return; + cmd1byte(USEFONT); + cmd2byte(DVINum); + ourfontnum = DVINum; +} + +/* Assumes that the correct font is currently set */ +static void +Tyldot(dotx, doty) + int32 dotx, doty; +{ + if (dotx != 0 && doty != 0) + isetpos(dotx, doty); + iputchar(DOTCHAR); +} + +/* + * ### Note: "pageitems" could be extended to be a list + * { of macrodefinitions which contain primitives , and { then could be + * instanced. E.g., a library of common { figures callable from \special level + */ + +void +pushItem(depth, newthing) + int depth; + Item *newthing; +{ + Item *i, *p; + + if (pageitems == NULL) + { + if (newthing->kind == Afigure) + { + pageitems = newthing; + return; + } + pageitems = NewItem(Afigure); + pageitems->UU.U8.depthnumber = depth; + } + + /* Assume that pageitems points to Afigure */ + /* traverse the list */ + i = pageitems; /* point to front of list for now */ + p = i->UU.U8.body->things; + while (p != NULL) + { + if (depth == i->UU.U8.depthnumber) + { /* simple push */ +/* + * Note: this is the case when pushing another figure item onto + * an already-existing list. We push the + * newfigure with a depth of (fig^.depthnumber - 1) because + * it really is part of the higer-level figure + */ + break; + } + if (depth <= i->UU.U8.depthnumber) + continue; + /* there MUST be a figure with a higher number deeper */ + while (p->kind != Afigure && p->nextitem != NULL) + p = p->nextitem; + + if (p->kind == Afigure) + { + i = p; + p = i->UU.U8.body->things; + } + else + { + complain(ERRREALBAD); + fprintf(logfile, + "OOPS p^.kind isnt a figure. It must be near endoflist\n"); + } + } + + /* + * we have the correct front of list-list, and i points to Afigure item + */ + newthing->nextitem = p; + i->UU.U8.body->things = newthing; +} + +static double +Tgetfixword(k) + int k; +{ + short a; + int32 f; + + a = tfm[k + 100] * 16 + tfm[k + 101] / 16; + f = ((tfm[k + 101] & 15) * 256 + tfm[k + 102]) * 256 + tfm[k + 103]; + if (a <= 2047) + return (a + (double) f / TWO20); + a = 4096 - a; + if (f > 0) + { + f = TWO20 - f; + a--; + } + return (a + (double) f / TWO20); +} + +static int32 +TgetSigned(k) + int k; +{ + int32 i; + + i = tfm[k + 100]; + if (i < 128) + i -= 256; + return (((i * 256 + tfm[k + 101]) * 256 + tfm[k + 102]) * 256 + tfm[k + 103]); +} + +/* + * open a .tfm file and return the parameters in it. + * Used only in conjuction with the vector and music fonts + */ +static void +gettfm(tfmfilnam, dessize, p1, p2, p3, p4, p5, p6, p7, cksum) + charstring tfmfilnam; + int32 *dessize, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *cksum; +{ + int32 tfmptr, lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np, charbase, widthbase, heightbase, depthbase, + italicbase, ligkernbase, kernbase, extenbase, parambase; + ScaledPts tempdesignsize; + + *p1 = 0; + *p2 = 0; + *p3 = 0; + *p4 = 0; + *p5 = 0; + *p6 = 0; + *p7 = 0; + *cksum = -1; + if (!opentfmfile(tfmfilnam)) + { + complain(ERRREALBAD); + fprintf(logfile, "%s---not loaded, TFM file can't be opened!\n", tfmfilnam); + jumpout(); + } + tfm[100] = Tgetc(); + tfm[101] = Tgetc(); + lf = tfm[100] * 256 + tfm[101]; + if (lf * 4 - 1 > TFMSIZE) + { + complain(ERRREALBAD); + fprintf(logfile, "The tfm file:%s is bigger than I can handle!\n", tfmfilnam); + return; + } + for (tfmptr = 102; tfmptr <= lf * 4 + 99; tfmptr++) + tfm[tfmptr] = Tgetc(); + tfmptr = 2; + lh = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + bc = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + ec = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + nw = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + nh = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + nd = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + ni = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + nl = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + nk = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + ne = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + np = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101]; + tfmptr += 2; + if (lf != lh + ec - bc + nw + nh + nd + ni + nl + nk + ne + np + 7) + { + complain(ERRREALBAD); + fprintf(logfile, "%s: subfile sizes don't add up to the stated total!\n", tfmfilnam); + fprintf(logfile, + "Sorry, but I can't go on; are you sure this is a TFM?\n"); + return; + } + if (bc > ec + 1 || ec > 255) + { + complain(ERRREALBAD); + fprintf(logfile, "The character code range %ld..%ld is illegal!\n", bc, ec); + fprintf(logfile, "Sorry, but I can't go on; are you sure this is a TFM?\n"); + return; + } + charbase = lh - bc + 6; + widthbase = charbase + ec + 1; + heightbase = widthbase + nw; + depthbase = heightbase + nh; + italicbase = depthbase + nd; + ligkernbase = italicbase + ni; + kernbase = ligkernbase + nl; + extenbase = kernbase + nk; + parambase = extenbase + ne - 1; + + *dessize = (int32) floor(Tgetfixword(28) * SPPERPT + 0.5); + /* now in ScaledPts */ + tempdesignsize = (int32) floor(*dessize * magfactor + 0.5); + *cksum = TgetSigned(24); + /* return the special 7 parameters for the font */ + *p1 = (int32) floor(Tgetfixword((parambase + 1) * 4) * tempdesignsize + 0.5); + *p2 = (int32) floor(Tgetfixword((parambase + 2) * 4) * tempdesignsize + 0.5); + *p3 = (int32) floor(Tgetfixword((parambase + 3) * 4) * tempdesignsize + 0.5); + *p4 = (int32) floor(Tgetfixword((parambase + 4) * 4) * tempdesignsize + 0.5); + *p5 = (int32) floor(Tgetfixword((parambase + 5) * 4) * tempdesignsize + 0.5); + *p6 = (int32) floor(Tgetfixword((parambase + 6) * 4) * tempdesignsize + 0.5); + *p7 = (int32) floor(Tgetfixword((parambase + 7) * 4) * tempdesignsize + 0.5); +} + +static void +initVnMnLtables() +{ + int32 i; + + for (i = 0; i < SizVFontTable; i++) + VFontTable[i] = NULL; + for (i = 0; i < SizMFontTable; i++) + MFontTable[i] = NULL; + for (i = 0; i < SizLFontTable; i++) + LFontTable[i] = NULL; + VFontsDefd = 0; + MFontsDefd = 0; + LFontsDefd = 0; +} + +static void +fonttobedefined(kind, findex) + char kind; + int findex; +{ + FTBDs++; + /* + * reset this to zero after outputting 1. fontdefs 2. bop + * 3. contents of dvi page 4. eop + */ + TBD[FTBDs - 1].which = kind; + TBD[FTBDs - 1].indx = findex; +} + +static void +enterfont(fontnum, ck, scalefact, dessiz, nam) + int32 fontnum, ck, scalefact, dessiz; + charstring nam; +{ + int32 n, len; + + cmd1byte(FONTDEF); + cmd2byte(fontnum); + cmd4byte(ck); + cmd4byte(scalefact); + cmd4byte(dessiz); + cmd1byte(USESTDAREA); + cmd1byte(len = strlen(nam) - 4);/* skip the length of the .tfm suffix */ + for (n = 0; n < len; n++) /* skip the .tfm suffix */ + cmd1byte(nam[n]); + +} + +static void +Outputfont(fontnum, ck, scalefact, dessiz, nam) + int32 fontnum, ck, scalefact, dessiz; + charstring nam; +{ + int32 n, len; + + OutputByte(FONTDEF); + Output2Byte(fontnum); + Output4Byte(ck); + Output4Byte(scalefact); + Output4Byte(dessiz); + OutputByte(USESTDAREA); + /* dont output the default dir prefix, nor the .tfm suffix */ + OutputByte(len = strlen(nam) - 4); + for (n = 0; n < len; n++) + OutputByte(nam[n]); + +} + +void +defineNewfonts() +{ + /* + * this needs to be done before first access to a font + * on a page later someone else will have to re-define all of them + * in the postamble + */ + int32 i, f, FORLIM; + VectFontInfRec *WITH; + MusFontInfRec *WITH1; + LabFontInfRec *WITH2; + + FORLIM = FTBDs; + for (i = 0; i < FORLIM; i++) + { + if (TBD[i].which == 'V') + { + f = TBD[i].indx; + WITH = VFontTable[f - 1]; /* with */ + if (WITH->Isdefined) + continue; + Outputfont(WITH->DVIFontNum, WITH->Cksum, WITH->DesSize, WITH->DesSize, + WITH->FontName); + WITH->Isdefined = true; + } /* if */ + else if (TBD[i].which == 'M') + { + f = TBD[i].indx; + WITH1 = MFontTable[f - 1]; /* with */ + if (WITH1->Isdefined) + continue; + Outputfont(WITH1->DVIFontNum, WITH1->Cksum, WITH1->DesSize, + WITH1->DesSize, WITH1->FontName); + WITH1->Isdefined = true; + } + else if (TBD[i].which == 'L') + { + f = TBD[i].indx; + WITH2 = LFontTable[f - 1]; /* with */ + if (WITH2->Isdefined) /* ### is this right? */ + continue; + Outputfont(WITH2->DVIFontNum, WITH2->Cksum, WITH2->DesSize, + WITH2->DesSize, WITH2->FontName); + WITH2->Isdefined = true; + } + else + { + complain(ERRREALBAD); + fprintf(logfile, "Unknown type of font to be defined:\"%c\"\n", + TBD[i].which); + } + } +} + +static int32 +GetMusFont(stfsiz, fam) + int32 stfsiz, fam; +{ + charstring mustfmnam; + MusIndex i; + ScaledPts design, p1, p2, p3, p4, linesp, gwidth, p7; + int32 cksm, FORLIM; + MusFontInfRec *WITH; + + /* see if it already exists */ + FORLIM = MFontsDefd; + for (i = 1; i <= FORLIM; i++) + { /* loop through since there are few */ + WITH = MFontTable[i - 1]; + if (WITH->Staffsize == stfsiz && WITH->Family == fam) + return (i); + } + + sprintf(mustfmnam, "mus%c%c.tfm", stfsiz + '0', fam + '0'); + gettfm(mustfmnam, &design, &p1, &p2, &p3, &p4, &linesp, &gwidth, &p7, &cksm); + + MFontsDefd++; + if (MFontsDefd > SizMFontTable) + { + complain(ERRREALBAD); + fprintf(logfile, "%s---not loadable. Size of Music Font table too small\n", mustfmnam); + jumpout(); + } + + i = MFontsDefd; + MFontTable[i - 1] = (MusFontInfRec *) xmalloc(sizeof(MusFontInfRec)); + WITH = MFontTable[i - 1]; + + WITH->Staffsize = stfsiz; + WITH->Family = fam; + WITH->DesSize = design; + strcpy(WITH->FontName, mustfmnam); + WITH->Cksum = cksm; + WITH->ghu = (int32) floor(gwidth / QNOTEGHUS + 0.5); + WITH->gvu = (int32) floor(linesp / QNOTEGVUS + 0.5); + WITH->DVIFontNum = GDVIFN++; + WITH->Isdefined = false; + /* call someone to do the defns of cdp, cht, cwd foreach beam */ + definebeams(&MFontTable[i - 1]); + fonttobedefined('M', i); + return (i); +} + +int32 +GetVectFont(size, vk) + VThickness size; + VectKind vk; +{ + charstring vectfmnam; + VecIndex i; + ScaledPts design, p1, p2, w0, w1, maxveclen, p6, p7; + int32 cksm, r, FORLIM; + VectFontInfRec *WITH; + + /* see if it already exists */ + FORLIM = VFontsDefd; + for (i = 1; i <= FORLIM; i++) + { /* with */ + WITH = VFontTable[i - 1]; + if (WITH->psize == size && WITH->vkind == vk) + return (i); + } + switch (vk) + { + case VKCirc: + r = 'c'; + break; + case VKVert: + r = 'v'; + break; + case VKHort: + r = 'h'; + break; + } + sprintf(vectfmnam, "%cvec%d.tfm", r, size); + gettfm(vectfmnam, &design, &p1, &p2, &w0, &w1, &maxveclen, &p6, &p7, &cksm); + VFontsDefd++; + if (VFontsDefd > SizVFontTable) + { + complain(ERRREALBAD); + fprintf(logfile, "%s---not loadable. Size of Vector Font table too small\n", vectfmnam); + jumpout(); + } + + i = VFontsDefd; + VFontTable[i - 1] = (VectFontInfRec *) xmalloc(sizeof(VectFontInfRec)); + WITH = VFontTable[i - 1]; + + WITH->vkind = vk; + WITH->psize = size; + WITH->DesSize = design; + if (vk == VKVert) + WITH->PenSize = w1; + else + WITH->PenSize = w0; + WITH->PenSize = (int32) floor(size * (MAXVECLENsp / 16.0) + 0.5); + WITH->MaxVectLen = maxveclen; + strcpy(WITH->FontName, vectfmnam); + WITH->Cksum = cksm; + WITH->Isdefined = false; + WITH->DVIFontNum = GDVIFN++; + + definevectors(&VFontTable[i - 1]); + /* someone asked for it, so they must want it, and we should fntdef it */ + fonttobedefined('V', i); + return (i); +} + + +/*----------------------------------------------------------*/ +int32 +GetLabFont(style) + int32 style; +{ + charstring labtfmnam; + int32 i, cksm, FORLIM; + ScaledPts design, p1, space, p3, p4, p5, p6, p7; + LabFontInfRec *WITH; + + if (style > MAXLABELFONTS) + style = 1; + FORLIM = LFontsDefd; + for (i = 1; i <= FORLIM; i++) + { + WITH = LFontTable[i - 1]; + if (WITH->internalnumber == style) + return (i); + } + + switch (style) + { + case 1: /* cmtt10 */ + strcpy(labtfmnam, "cmtt10"); + break; + case 2: /* cmb10 */ + strcpy(labtfmnam, "cmb10"); + break; + case 3: /* cmsl10 */ + strcpy(labtfmnam, "cmsl10"); + break; + case 4: /* cmtt8 */ + strcpy(labtfmnam, "cmtt8"); + break; + case 5: /* cmsl8 */ + strcpy(labtfmnam, "cmsl8"); + break; + } + strcat(labtfmnam, ".tfm"); + gettfm(labtfmnam, &design, &p1, &space, &p3, &p4, &p5, &p6, &p7, &cksm); + + LFontsDefd++; + + if (LFontsDefd > SizLFontTable) + { + complain(ERRREALBAD); + fprintf(logfile, "%s---not loadable. Size of Label Font table too small\n", labtfmnam); + jumpout(); + } + + i = LFontsDefd; + LFontTable[i - 1] = (LabFontInfRec *) xmalloc(sizeof(LabFontInfRec)); + WITH = LFontTable[i - 1]; /* with */ + + strcpy(WITH->FontName, labtfmnam); + WITH->Cksum = cksm; + WITH->DesSize = design; + WITH->internalnumber = style; + WITH->spacewidth = space; + WITH->DVIFontNum = GDVIFN++; + WITH->Isdefined = false; + fonttobedefined('L', i); + return (i); +} + +static double +vectangle(dx, dy) + int32 dx, dy; +{ + if (dx != 0) + return (atan(dy / (double) dx) * RADTODEG); + else + return (dy > 0 ? 90.0 : -90.0); +} + +static void +definevectors(Vec) + VectFontInfRec **Vec; +{ + /* var Vec: pVectFontInfRec */ + int i; + double units; + VectFontInfRec *V; + FontInfRec *F; + struct vecinfo *v; + + V = *Vec; + units = V->MaxVectLen / 16.0; + for (i = 0, F = V->FontInfo, v = vectab; i < 128; ++i, ++F, ++v) + { + F->Cht = floor(v->Cht * units + 0.5); + F->Cdp = floor(v->Cdp * units + 0.5); + F->Cwd = floor(v->Cwd * units + 0.5); + F->Angle = v->Angle; + } +} + +/* + * If, for some reason, you do not want to deal with music capabilities, + * replace the body of this procedure with just a begin + * end; pair and also the TylBeam proc. + */ +static void +definebeams(M) + MusFontInfRec **M; +{ + /* var M : pMusFontInfRec */ +} + +#define UnitRadius 16777216/* TWO24 scaledpts */ + +/* + * use pre-calculated coordinates of a circle that has a given unit-radius. + * Scale those points to fit the desired radius + */ +void +defineCircleCpts(rad, centx, centy, CircleCpt, numpts) + int32 rad, centx, centy; + int32 (*CircleCpt)[2]; + int32 *numpts; +{ + double ratio; + + if (rad == 0) + { + complain(ERRBAD); + fprintf(logfile, "Error in fig#%ld on page %ld\n", + pgfigurenum, currpagenum); + fprintf(logfile, "Zero length radius for circle! Setting to 1 sp\n"); + rad = 1; + } + ratio = float_(rad) / float_(UnitRadius); + *numpts = 16; + CircleCpt[1][0] = (int32) floor(ratio * 16777216.00000 + 0.5) + centx; + CircleCpt[1][1] = centy;/* round (ratio * 0.00000) */ + CircleCpt[2][0] = (int32) floor(ratio * 15500126.47492 + 0.5) + centx; + CircleCpt[2][1] = (int32) floor(ratio * 6420362.60441 + 0.5) + centy; + CircleCpt[3][0] = (int32) floor(ratio * 11863283.20303 + 0.5) + centx; + CircleCpt[3][1] = (int32) floor(ratio * 11863283.20303 + 0.5) + centy; + CircleCpt[4][0] = (int32) floor(ratio * 6420362.60441 + 0.5) + centx; + CircleCpt[4][1] = (int32) floor(ratio * 15500126.47492 + 0.5) + centy; + CircleCpt[5][0] = centx;/* round (ratio * -0.00000) */ + CircleCpt[5][1] = (int32) floor(ratio * 16777216.00000 + 0.5) + centy; + CircleCpt[6][0] = (int32) floor(0.5 - ratio * 6420362.60441) + centx; + CircleCpt[6][1] = (int32) floor(ratio * 15500126.47492 + 0.5) + centy; + CircleCpt[7][0] = (int32) floor(0.5 - ratio * 11863283.20303) + centx; + CircleCpt[7][1] = (int32) floor(ratio * 11863283.20303 + 0.5) + centy; + CircleCpt[8][0] = (int32) floor(0.5 - ratio * 15500126.47492) + centx; + CircleCpt[8][1] = (int32) floor(ratio * 6420362.60441 + 0.5) + centy; + CircleCpt[9][0] = (int32) floor(0.5 - ratio * 16777216.00000) + centx; + CircleCpt[9][1] = centy;/* round (ratio * -0.00000) */ + CircleCpt[10][0] = (int32) floor(0.5 - ratio * 15500126.47492) + centx; + CircleCpt[10][1] = (int32) floor(0.5 - ratio * 6420362.60441) + centy; + CircleCpt[11][0] = (int32) floor(0.5 - ratio * 11863283.20303) + centx; + CircleCpt[11][1] = (int32) floor(0.5 - ratio * 11863283.20303) + centy; + CircleCpt[12][0] = (int32) floor(0.5 - ratio * 6420362.60441) + centx; + CircleCpt[12][1] = (int32) floor(0.5 - ratio * 15500126.47492) + centy; + CircleCpt[13][0] = centx; /* round (ratio * 0.00000) */ + CircleCpt[13][1] = (int32) floor(0.5 - ratio * 16777216.00000) + centy; + CircleCpt[14][0] = (int32) floor(ratio * 6420362.60441 + 0.5) + centx; + CircleCpt[14][1] = (int32) floor(0.5 - ratio * 15500126.47492) + centy; + CircleCpt[15][0] = (int32) floor(ratio * 11863283.20303 + 0.5) + centx; + CircleCpt[15][1] = (int32) floor(0.5 - ratio * 11863283.20303) + centy; + CircleCpt[16][0] = (int32) floor(ratio * 15500126.47492 + 0.5) + centx; + CircleCpt[16][1] = (int32) floor(0.5 - ratio * 6420362.60441) + centy; + /* create the pre-list phantom */ + CircleCpt[0][0] = CircleCpt[16][0]; + CircleCpt[0][1] = CircleCpt[16][1]; +} + +#undef UnitRadius + +/* + * compute control points for an arc going from startangle to stopangle, centered at (centx, centy) + */ +void +definearcpts(rad, centx, centy, startang, stopang, cpts, nknots) + int32 rad, centx, centy, startang, stopang; + int32 (*cpts)[2]; + int32 *nknots; +{ + int32 n; + double a, b, curr, delta; + int32 i; + + a = startang * DEGTORAD; + b = stopang * DEGTORAD; + n = 16; + if (a > b) + a -= 2 * PI; + delta = fabs(b - a) / n; + if (a == b) + { + complain(ERRNOTBAD); + fprintf(logfile, "Error in compute arc points:: should be a circle\n"); + } + curr = a; + i = 1; + while (curr <= b) + { /* make arc about (centx,centy) */ + cpts[i][0] = (int32) floor(rad * cos(curr) + 0.5) + centx; + cpts[i][1] = (int32) floor(rad * sin(curr) + 0.5) + centy; + i++; + curr += delta; + } + + /* + * go one point beyond -- around the arc so that we can have + * good smoothness for this phantom point + */ + + cpts[i][0] = (int32) floor(rad * cos(b + delta) + 0.5) + centx; + cpts[i][1] = (int32) floor(rad * sin(b + delta) + 0.5) + centy; + + /* and one phantom point before the list */ + cpts[0][0] = (int32) floor(rad * cos(a - delta) + 0.5) + centx; + cpts[0][1] = (int32) floor(rad * sin(a - delta) + 0.5) + centy; + + *nknots = i - 1; +} + +static int +isaletter(b) + int b; +{ + return (isalpha(b) || b == '@' || b == '"'); +} + +static int +getnumber(cpp) + char **cpp; +{ + int n; + int isneg; + + n = 0; + isneg = false; + for ( ; **cpp != '\0' && (!isdigit(**cpp)); ++*cpp) + if (**cpp == '-') + isneg = true; + while (isspace(**cpp)) /* Skip spaces */ + ++*cpp; + for ( ; **cpp != '\0' && isdigit(**cpp); ++*cpp) + n = n * 10 + **cpp - '0'; + return (isneg ? -n : n); +} + +static int +getletter(cpp) + char **cpp; +{ + char *cp; + + cp = *cpp; + /* non letter */ + for (cp = *cpp; *cp != '\0' && !isaletter(*cp) && !isspace(*cp); ++cp) + ; + if (*cp != '\0' && (isaletter(*cp) || + (isspace(*cp) && !isdigit(*cp)))) + { + *cpp = cp + 1; + return (*cp); + } + return (' '); +} + +static int +getanything(cpp) + char **cpp; +{ + char c; + + if ((c = **cpp) != '\0') + { + ++*cpp; + return (c); + } + return (' '); +} + +/***************************************************** + The following routines look for key - letter tokens + that indicate certain attributes for a primitive. + +Currently, the letters used are: + Sfor scaled-points measurement + Pfor printers points + Mmillimeters measurement + Cuse a Circular vector for drawing + HHorizontal-pen vector + VVertical vector + BB-spline + IInterpolating B-spline + KCatmull-Rom spline + DCardinal spline + UOpen spline + Oclosed spline + Xput marks on spline control pts + TTransformation marker + RRegular beam characters + GGrace Beam characters + @Specify center-point for arc/circle + LLine-style + Ffor beginfigure: Fit figure to wid/ht + Wfor beginfigure: figure was created at this wid & ht +***************************************************/ + +static void +gettransforms(sc1, sc2, r, tr1, tr2, cpp) + double *sc1, *sc2, *r; + int32 *tr1, *tr2; + char **cpp; +{ + char *cp; + + *sc1 = 1.0; + *sc2 = 1.0; + *tr1 = 0; + *tr2 = 0; + *r = 0.0; + for (cp = *cpp; *cp != '\0'; ++cp) + { + if (*cp == 't' || *cp == 'T') + { + if (!isaletter(cp[-1]) && !isaletter(cp[1])) + { + /* get transform parameters and modify ptr */ + *cpp = cp; + *sc1 = getnumber(cpp) / 100.0; + *sc2 = getnumber(cpp) / 100.0; + *tr1 = getnumber(cpp); + *tr2 = getnumber(cpp); + *r = float_(getnumber(cpp)); + /* degrees about primitive center */ + if (*r < 0.0) + *r += 360.0; + break; + } + } + } +} + +static int +findmarker(set, cp) + char *set; + char *cp; +{ + for ( ; *cp != '\0'; ++cp) + { + if (strchr(set, *cp)) + if (!isaletter(cp[-1]) && !isaletter(cp[1])) + return (tolowercase(*cp)); + } + return (0); +} + +#define findscale(p) findmarker("sSpPmM", p) +#define findvectkind(p) findmarker("cChHvV", p) +#define findlinestyle(p) findmarker("lL", p) +#define findbeamkind(p) findmarker("rRgG", p) +#define findsplinekind(p) findmarker("bBiIkKdD", p) +#define findsplclosure(p) findmarker("oOuU", p) +#define findatsign(p) findmarker("@", p) +#define finddotmark(p) findmarker("xX", p) +#define findfigdimens(p) findmarker("wW", p) +#define findfitsizes(p) findmarker("fF", p) + +static double +thescaleof(scal) + int32 scal; +{ + if (scal == 's') + return (1 * magfactor); + if (scal == 'p') + return (SPPERPT * magfactor); + if (scal == 'm') + return (SPPERMM * magfactor); + if (scal == 0) + return (SPPERPT * magfactor); +} + + +static VectKind +thevectorof(vkin) + int32 vkin; +{ + if (vkin == 'c') + return VKCirc; + if (vkin == 'v') + return VKVert; + if (vkin == 'h') + return VKHort; + if (vkin == 0) + return VKCirc; +} + +static LineStyle +thestyleof(linest) + int32 linest; +{ + static LineStyle styletab[4] = {solid, dotted, dashed, dotdash}; + + if (linest > 3 || linest < 0) + linest = 0; + return (styletab[linest]); +} + +static void +tylspecials(cp) + char *cp; +{ + /* + * specnum is the DVI-number of the special + * nbytes is the number of parameter bytes + */ + int32 siz, numknots; /* Lots of temp vars that we use */ + int32 x1, y1, x2, y2; + double sx100, sy100, rot, SPscale; + ScaledPts transx, transy, minx, miny, maxx, maxy; + ControlPoints cpts; + VThickness thk; + LineStyle patt; + ThickAryType TTary; + VectKind vk; + BeamKind bk; + int32 markdiam, radius, ang1, ang2; + charstring phrase; + int32 style; + char nam[5]; /* the first parameter of the \special */ + char let; + int32 i; + Item *pi; + int32 maxthk, minthk; + SplineKind splinetype; + int isclosedspline; + int free PP((char *)); + + /* Lets look for a primitive to tyl */ + for ( ; !isaletter(*cp) && *cp != '\0'; ++cp) + ; + /* get the name of the primitive */ + for (i = 0; isaletter(*cp); ++cp) + if (i < 4) + nam[i++] = tolowercase(*cp); + nam[i] = '\0'; + + /* --- BEGINFIGURE ---- */ + if (streq(nam, "beginfigure", 3)) + { + multifigure++; + i = findscale(cp); + SPscale = thescaleof(i); + + gettransforms(&sx100, &sy100, &rot, &transx, &transy, &cp); + /* + * store all the primitives on pageitems, and dont output them + * until we get a endfigure. this way, we can take + * care of dealing with all the primitives according to some + * global tranformation for the whole figure + */ + pi = NewItem(Afigure); + pi->UU.U8.figtheta = rot; + pi->UU.U8.fsx = sx100; + pi->UU.U8.fsy = sy100; + pi->UU.U8.fdx = (int32) floor(transx * SPscale + 0.5); + pi->UU.U8.fdy = (int32) floor(transy * SPscale + 0.5); + pi->UU.U8.depthnumber = multifigure; /* we're at a new level */ + i = findfigdimens(cp); + if (i != 0) + { + pi->UU.U8.preWid = (int32) floor(getnumber(&cp) * SPscale + 0.5); + pi->UU.U8.preHt = (int32) floor(getnumber(&cp) * SPscale + 0.5); + } + i = findfitsizes(cp); + if (i != 0) + { /* with */ + pi->UU.U8.postWid = (int32) floor(getnumber(&cp) * SPscale + 0.5); + pi->UU.U8.postHt = (int32) floor(getnumber(&cp) * SPscale + 0.5); + } + BackupInBuf(DVIMark() - specstart); + pushItem(multifigure - 1, pi); + return; + } + /* ---- ENDFIGURE ---- */ + if (streq(nam, "endfigure", 3)) + { + multifigure--; + if (multifigure < 0) + { + complain(ERRBAD); + fprintf(logfile, "Warning: Too many \"endfigure\"s !"); + multifigure = 0; + } + BackupInBuf(DVIMark() - specstart); + if (multifigure == 0) + { + /* go do our set of figures (within figures...) */ + figurehandle(pageitems, pageitems, 1); + free((char *)pageitems);/* #### should maybe garbage collect here */ + pageitems = NULL; + } /* if */ + return; + } + + /* --- LINE --- */ + if (streq(nam, "line", 3)) + { + i = findscale(cp); + SPscale = thescaleof(i); + + gettransforms(&sx100, &sy100, &rot, &transx, &transy, &cp); + thk = getnumber(&cp); /* get the vector thickness */ + if (thk < 1) + { + complain(ERRBAD); + fprintf(logfile, "?? Thickness not found. Setting to 1\n"); + thk = 1; + } + i = findvectkind(cp); + vk = thevectorof(i); + + i = findlinestyle(cp); + if (i != 0) + patt = thestyleof(getnumber(&cp)); + else + patt = solid; + + x1 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + y1 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + x2 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + y2 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + + minx = min(x1, x2); + maxx = max(x1, x2); + miny = min(y1, y2); + maxy = max(y1, y2); + + BackupInBuf(DVIMark() - specstart); + cmd1byte(OURFONTFLAG); + linehandle(multifigure, SPscale, x1, y1, x2, y2, 0, 0, thk, vk, patt, + minx, maxx, miny, maxy, transx, transy, sx100, sy100, rot); + } /* line */ + else if (streq(nam, "spline", 3) || streq(nam, "ttspline", 3)) + { + i = findscale(cp); + SPscale = thescaleof(i); + + gettransforms(&sx100, &sy100, &rot, &transx, &transy, &cp); + + if (streq(nam, "spline", 3)) + { + thk = getnumber(&cp); + if (thk < 1) + { + complain(ERRBAD); + fprintf(logfile, "Spline Thickness not found. Setting to 1\n"); + thk = 1; + } + } + i = findvectkind(cp); + vk = thevectorof(i); + + i = findlinestyle(cp); + if (i != 0) + patt = thestyleof(getnumber(&cp)); + else + patt = solid; + + i = findsplinekind(cp); + if (i == 'b') + splinetype = BSPL; + else if (i == 'i') + splinetype = INTBSPL; + else if (i == 'k') + splinetype = CATROM; + else if (i == 'd') + splinetype = CARD; + else if (i == 0) + splinetype = CATROM; + + i = findsplclosure(cp); + if (i == 'o') + isclosedspline = true; + else if (i == 'u') + isclosedspline = false; + else if (i == 0) + isclosedspline = false; + + i = finddotmark(cp); + if (i == 'x') + markdiam = getnumber(&cp); + else if (i == 0) + markdiam = 0; + + numknots = min(getnumber(&cp), (int32) MAXCTLPTS); + if (numknots < 1) + { + complain(ERRBAD); + fprintf(logfile, + "Number of spline/ttspline knot points not found. Setting to 1\n"); + numknots = 1; + } + + minx = TWO24; + miny = TWO24; + maxx = -TWO24; + maxy = -TWO24; + + for (i = 0; i <= numknots + 3; i++) + { + cpts[i][0] = 0; + cpts[i][1] = 0; + } /* for */ + + for (i = 1; i <= numknots; i++) + { + x1 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + cpts[i][0] = x1; + if (x1 < minx) + minx = x1; + if (x1 > maxx) + maxx = x1; + y1 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + cpts[i][1] = y1; + if (y1 < miny) + miny = y1; + if (y1 > maxy) + maxy = y1; + } /* for */ + + if (streq(nam, "ttspline", 3)) + { + for (i = 1; i <= numknots; i++) + TTary[i] = getnumber(&cp); + } + + BackupInBuf(DVIMark() - specstart); + cmd1byte(OURFONTFLAG); + + if (streq(nam, "spline", 3)) + splinehandle(multifigure, SPscale, splinetype, isclosedspline, markdiam, + cpts, numknots, 0, 0, thk, vk, patt, minx, maxx, miny, + maxy, transx, transy, sx100, sy100, rot); + else + ttsplhandle(multifigure, SPscale, splinetype, isclosedspline, markdiam, + cpts, TTary, numknots, 0, 0, vk, patt, minx, maxx, miny, + maxy, transx, transy, sx100, sy100, rot); + } + else if (streq(nam, "beam", 4)) + { + i = findscale(cp); + SPscale = thescaleof(i); + + /* no transforms */ + + siz = getnumber(&cp); /* the staffsize */ + i = findbeamkind(cp); + if (i == 'g') + bk = grace; + else if (i == 'r') + bk = regular; + else if (i == 0) + bk = regular; + + x1 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + y1 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + x2 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + y2 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + + BackupInBuf(DVIMark() - specstart); + cmd1byte(OURFONTFLAG); + + beamhandle(multifigure, siz, bk, x1, y1, x2, y2); + } + else if (streq(nam, "tieslur", 3)) + { + i = findscale(cp); + SPscale = thescaleof(i); + + minthk = getnumber(&cp); + if (minthk < 1) + { + complain(ERRBAD); + fprintf(logfile, "Tie/Slur Min Thickness not found. Setting to 1\n"); + minthk = 1; + } + + maxthk = getnumber(&cp); + if (maxthk < 1) + { + complain(ERRBAD); + fprintf(logfile, "Tie/Slur MaxThickness not found. Setting to 1\n"); + maxthk = 1; + } + + numknots = min(getnumber(&cp), (int32) MAXCTLPTS); + if (numknots < 1) + { + complain(ERRBAD); + fprintf(logfile, + "Tie/Slur Number of knot points not found. Setting to 1. Should be 5\n"); + numknots = 1; + } + for (i = 1; i <= numknots; i++) + { + cpts[i][0] = (int32) floor(getnumber(&cp) * SPscale + 0.5); + cpts[i][1] = (int32) floor(getnumber(&cp) * SPscale + 0.5); + } /* for */ + BackupInBuf(DVIMark() - specstart); + cmd1byte(OURFONTFLAG); + + tieslurhandle(multifigure, cpts, numknots, (int) minthk, (int) maxthk); + } + else if (streq(nam, "arc", 3)) + { + i = findscale(cp); + SPscale = thescaleof(i); + + gettransforms(&sx100, &sy100, &rot, &transx, &transy, &cp); + + thk = getnumber(&cp); + if (thk < 1) + { + complain(ERRBAD); + fprintf(logfile, "Arc Thickness not found. Setting to 1\n"); + thk = 1; + } + i = findvectkind(cp); + vk = thevectorof(i); + + i = findlinestyle(cp); + if (i != 0) + patt = thestyleof(getnumber(&cp)); + else + patt = solid; + + radius = (int32) floor(getnumber(&cp) * SPscale + 0.5); + if (radius == 0) + radius = (int32) floor(1 * SPscale + 0.5); + i = findatsign(cp); + if (i != 0) + { + x2 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + y2 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + } + else + { + x2 = 0; + y2 = 0; /* assume center at origin */ + } + + ang1 = getnumber(&cp); + if (abs(ang1) > 360) + { + ang1 %= 360; + /* + * p2c: x.p, line 5570: Note: Using % for possibly-negative arguments [317] + */ + } + ang2 = getnumber(&cp); + if (abs(ang2) > 360) + { + ang2 %= 360; + /* + * p2c: x.p, line 5573: Note: Using % for possibly-negative arguments [317] + */ + } + + minx = TWO24; + miny = TWO24; + maxx = -TWO24; + maxy = -TWO24; + + if (ang1 == ang2) /* a circle */ + defineCircleCpts(radius, x2, y2, cpts, &numknots); + else /* a real arc */ + definearcpts(radius, x2, y2, ang1, ang2, cpts, &numknots); + + for (i = 1; i <= numknots; i++) + { + x1 = cpts[i][0]; + if (x1 < minx) + minx = x1; + if (x1 > maxx) + maxx = x1; + + y1 = cpts[i][1]; + if (y1 < miny) + miny = y1; + if (y1 > maxy) + maxy = y1; + } /* for */ + + BackupInBuf(DVIMark() - specstart); + cmd1byte(OURFONTFLAG); + + + arccirclehandle(multifigure, SPscale, x2, y2, radius, ang1, ang2, cpts, + numknots, 0, 0, thk, vk, patt, minx, maxx, miny, maxy, + transx, transy, sx100, sy100, rot); + } + else if (streq(nam, "label", 3)) + { + i = findscale(cp); + SPscale = thescaleof(i); + + style = getnumber(&cp); /* font style number */ + if (style < 1 || style > MAXLABELFONTS) + { + complain(ERRBAD); + fprintf(logfile, "Label style bad? Setting to Style 1\n"); + style = 1; + } + + x1 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + y1 = (int32) floor(getnumber(&cp) * SPscale + 0.5); + + let = getletter(&cp); + while (let != '"') + let = getletter(&cp); + let = getanything(&cp); /* get next letter or whatever */ + for (i = 0; let != '"'; ++i) + { /* get the label phrase */ + phrase[i] = let; + let = getanything(&cp); /* getletter; */ + } + phrase[i] = '\0'; + + BackupInBuf(DVIMark() - specstart); + cmd1byte(OURFONTFLAG); + labelhandle(multifigure, SPscale, x1, y1, 0, 0, style, phrase, 0, 0); + } + else if (streq(nam, "param", 3)) + { + i = getnumber(&cp); /* addressable param number */ + + fprintf(logfile, " I do not know what internal parameter #%ld is\n", i); + /* else */ + BackupInBuf(DVIMark() - specstart); + } + else + { + complain(ERRNOTBAD); + fprintf(logfile, "Sorry, I don't know how to tyl %s\n", nam); + } +} + +static int +otherspecials(cp) + char *cp; +{ + fprintf(logfile, "Special: %s\n", cp); + return (1); +} + +static void +mainhandlespecials(specnum, nbytes) + int32 specnum, nbytes; +{ + /* + * specnum is the DVI-number of the special + * nbytes is the number of parameter bytes + */ + char sysnam[4]; + char *cp, *buf; + int32 i; + char *malloc PP((unsigned)); + int free PP((char *)); + + specstart = DVIMark() - specnum + 237; + ourxpos = h; + ourypos = v; /* note the global DVI (h,v) coords */ + + cp = buf = malloc((unsigned)(nbytes + 1)); + for (i = 0; i < nbytes; ++i) + cp[i] = Dget1byte(); + cp[i] = '\0'; + + while (isspace(*cp)) + ++cp; + /* get the name of the system --- Hopefully 'tyl' */ + for (i = 0; *cp != '\0' && *cp != ' '; ++cp) + if (i < 3) + sysnam[i++] = tolowercase(*cp); + sysnam[i] = '\0'; /* end of string */ + if (streq(sysnam, "tyl", 3)) + tylspecials(cp); + else if (otherspecials(buf)) + ; + else + fprintf(logfile, "Unknown special ignored: %s\n", buf); + free((char *)buf); +} + +/* + * ================================================== + * + * The routines below assume coordinates are already in 4th Quadrant DVI-space + * + * ===================================================== + */ + +/* + * returns 0 if dy.dx not in font 1 if ok 2 if ok and caller should use two of the "code"s coding scheme requires 0<= [dx, dy] + * <= 16 AND that max(dx, abs(dy)) is in [0,1,2,4,8,16] + */ +static int32 +outvector(dx, dy, code) + int32 dx, dy, *code; +{ + int32 c, result; + + if (dx < 0) + return (0); + + result = 0; /* init for potential failure */ + *code = -1; + if (dy < 0) + c = dy + dx - max(dx, -dy) * 9 + 160; + else + c = dy - dx - max(dx, dy) * 7 + 160; + + /* + * here translate to OUR coding scheme and return the correct number + * this is needed because "c" thinks the char range + * is 0 to 160, while we have only 128 chars + */ + + if (c == 0) + { /* special cases */ + *code = 63; + result = 2; + } + else if (c == 64) + { + *code = 95; + result = 2; + } + else + { + result = 1; /* just one char is fine */ + if (c >= 1 && c <= 63) /* c - 33 */ + *code = c - 1; + else if (c >= 80 && c <= 112) + *code = c - 17; + else if (c >= 120 && c <= 136) + *code = c - 24; + else if (c >= 140 && c <= 148) + *code = c - 27; + else if (c >= 150 && c <= 154) + *code = c - 28; + else if (c == 160) + *code = 127; + } + return result; +} + +/* take care of a Manhattan (horizontal /vertical) line */ +static void +hvline(lx, by, rx, ty, fontindex) + int32 lx, by, rx, ty, fontindex; +{ + int32 t, rth, x, y, width, height; + + rth = VFontTable[fontindex - 1]->PenSize; /* thickness of vector in sp */ + if (lx == rx) + { /* Vertical line */ + if (ty > by) + { + t = by; + by = ty; + ty = t; /* swap */ + } + x = (int32) floor(lx - rth / 2.0 + 0.5); + y = by; + width = rth; + height = by - ty; + } + else + { /* Horizontal line */ + if (ty < by) + { + t = by; + by = ty; + ty = t; /* swap */ + } + if (lx > rx) + { + t = lx; + lx = rx; + rx = t; /* swap */ + } + x = lx; + + y = by + rth / 2; /* + rth for {h,v}-space */ + width = rx - lx; + height = rth; + } + + isetpos(x, y); + cmd1byte(PUTRULE); + cmd4byte(height); + cmd4byte(width); + + /* + * output two dots on ends of the rules at lx, by and rx, ty + */ + /* the font has already been set before these calls */ + Tyldot(lx, by); + Tyldot(rx, ty); + isetpos(rx, ty); +} + + +/* Local variables for diagonal: */ +struct LOC_diagonal +{ + int32 xl, yb, xr, yt, curx, cury; + double slope; + ScaledPts mxveclen; +}; + +/* compute maximum length vector character that we can use */ +static void +getincr(outdx, outdy, LINK) + int32 *outdx, *outdy; + struct LOC_diagonal *LINK; +{ + int32 radius, x, y, sign; + + radius = LINK->mxveclen;/* radius of semi-square */ + /* + * make sure the pt is outside of the semi-square, scaling down radius if necessary + */ + while (LINK->xr - LINK->curx < radius && + abs(LINK->yt - LINK->cury) < radius) + radius /= 2; + if (LINK->slope < 0.0) /* <0 since in 4th quad by now */ + sign = -1; + else + sign = 1; + if (LINK->xr == LINK->curx) + { + *outdx = 0; + *outdy = sign * radius; + return; + } + if (LINK->yt == LINK->cury) + { + *outdx = abs(radius); + *outdy = 0; + return; + } + + /* + * compute the intersection with the semi-square, choose whichever slope is best + */ + if (fabs(LINK->slope) < 1.0) + { /* mostly horizontal */ + *outdx = abs(radius); + y = LINK->yb + + (int32) floor((LINK->curx + abs(radius) - LINK->xl) * LINK->slope + 0.5); + *outdy = y - LINK->cury; + } + else + { /* mostly vertical */ + x = LINK->xl + + (int32) floor((LINK->cury + sign * radius - LINK->yb) / LINK->slope + 0.5); + *outdx = x - LINK->curx; + *outdy = sign * radius; + } + + if (abs(*outdy) > abs(LINK->yt - LINK->cury)) /* truncate */ + *outdy = LINK->yt - LINK->cury; + if (*outdx > LINK->xr - LINK->curx) /* truncate */ + *outdx = LINK->xr - LINK->curx; + if (*outdx < 0) + *outdx = 0; + + /* + * method to find the exact intersection of the line segment with the semi-circle, used to determine the x and y + * values:: we do this by using the arctangent of the slope as the angle 'a' from the x-axis. Then use the relation y = + * r cos a, and x = r sin a we can be smart about all this trig stuff by using the relation : sin (arctan a) = 1/sqrt(1 + * + a^2) cos (arctan a) = a/sqrt(1 + a^2) Thus: q := (1.0 / sqrt (slope * slope + 1.0)); outdx := round (q * radius); + * outdy := round (q * radius * slope); + * + * Unfortunately, we cannot access the Vector Font coding scheme because the outdx, outdy 's produced here do no conform + * to the condition max (dx, abs(dy)) in [0,1,2,4,8,16] when converted to vector-font sizes with sptovecs (see the + * 'diagonal' proc.). + */ +} + +static void +diagonal(xl_, yb_, xr_, yt_, fontindex) + int32 xl_, yb_, xr_, yt_, fontindex; +{ + struct LOC_diagonal V; + int32 t, dx, dy, code; + double sptovecs; + ScaledPts rho; + + V.xl = xl_; + V.yb = yb_; + V.xr = xr_; + V.yt = yt_; + if (V.xr != V.xl) /* some illegal value */ + V.slope = (double) (V.yt - V.yb) / (V.xr - V.xl); + else + V.slope = BIGREAL; + + if (V.xl > V.xr) + { + t = V.xl; + V.xl = V.xr; + V.xr = t; + t = V.yb; + V.yb = V.yt; + V.yt = t; + } /* swap */ + + V.curx = V.xl; + V.cury = V.yb; + V.mxveclen = VFontTable[fontindex - 1]->MaxVectLen; + rho = V.mxveclen / 16; /* minimum radius of vector fonts */ + if (rho == 0) + { + complain(ERRREALBAD); + fprintf(logfile, + "Diagonal: Min radius of vector font is zero. setting to 1\n"); + rho = 1; + } + + if (abs(V.xl - V.xr) <= rho && abs(V.yb - V.yt) <= rho) + { /* pretty much a null line */ + Tyldot(V.xl, V.yb); + return; + } + sptovecs = 1.0 / rho; /* conversion for scaled pts to vectorfont units */ + + code = -1; /* initialize to a bogus number */ + + /* + * this conditional really has to have "or" instead of "and", because of lines that are nearly* horizontal or vertical + */ + while (V.xr - V.curx >= rho || abs(V.yt - V.cury) >= rho) + { + getincr(&dx, &dy, &V); + + /* + * Get the vector character code corresponding to this approximate incremental amount + */ + t = outvector((int32) floor(dx * sptovecs + 0.5), + (int32) floor(dy * sptovecs + 0.5), &code); + /* + * Now that we have the character code, go find out its actual physical dimensions for the real dy/dx amounts + */ + if (dy > 0) + dy = VFontTable[fontindex - 1]->FontInfo[code].Cdp; + else + dy = -VFontTable[fontindex - 1]->FontInfo[code].Cht; + + dx = VFontTable[fontindex - 1]->FontInfo[code].Cwd; + + switch (t) + { + + case 0: + complain(ERRREALBAD); + fprintf(logfile, "Error in Diagonal:: bad dydx\n"); + break; + + case 1: + isetpos(V.curx, V.cury); + iputchar(code); + break; + + case 2: + isetpos(V.curx, V.cury); + iputchar(code); + isetpos(V.curx + dx / 2, V.cury + dy / 2); + iputchar(code); + break; + } /* case */ + + V.curx += dx; + V.cury += dy; + } /* while */ + /* + * Get the approximate incremental amount. We use this dy/dx pair in order to index into our vector font coding scheme + */ + + + if (code >= 0 && V.xr - V.curx >= rho && abs(V.yt - V.cury) >= rho) + iputchar(code); + + /* not null line */ +} + + +/* Local variables for tylBrokenLine: */ +struct LOC_tylBrokenLine +{ + int32 fontindex; + LineStyle line_type; + int useXaxis; + int32 a0, b0, a1, b1, a2, a3, b2, b3, gap, dot, dash; + double s, z; + int32 J, frame, Dotgap, Dotdot, Dashgap, Dashdash, DDotgap, DDotdot, DDotdash; +}; + +static void +spread(lt, extra, T, LINK) + LineStyle lt; + int32 extra, T; + struct LOC_tylBrokenLine *LINK; +{ + if (T == 0) + { /* only partial frame fits */ + if (LINK->useXaxis) + diagonal(LINK->a0, LINK->b0, LINK->a1, LINK->b1, LINK->fontindex); + else + diagonal(LINK->b0, LINK->a0, LINK->b1, LINK->a1, LINK->fontindex); + return; + } + LINK->J = 0; + LINK->s = float_(LINK->b1 - LINK->b0) / float_(LINK->a1 - LINK->a0); + LINK->z = float_(extra) / float_(T); + switch (lt) + { + + case dotted: + do + { + LINK->a2 = LINK->a0 + LINK->J * LINK->frame; + if (extra > 0) + LINK->a2 += (int32) floor(LINK->J * LINK->z + 0.5); + LINK->a3 = LINK->a2 + LINK->dot; + LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5); + LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5); + if (LINK->a3 <= LINK->a1) + { + if (LINK->useXaxis) + diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex); + else + diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex); + } + LINK->J++; + } while (LINK->a3 < LINK->a1); + break; + + case dashed: + do + { + LINK->a2 = LINK->a0 + LINK->J * LINK->frame; + if (extra > 0) + LINK->a2 += (int32) floor(LINK->J * LINK->z + 0.5); + LINK->a3 = LINK->a2 + LINK->dash; + LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5); + LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5); + if (LINK->a3 <= LINK->a1) + { + if (LINK->useXaxis) + diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex); + else + diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex); + } + LINK->J++; + } while (LINK->a3 < LINK->a1); + break; + + case dotdash: + do + { + LINK->a2 = LINK->a0 + LINK->J * LINK->frame; + if (extra > 0) + LINK->a2 += (int32) floor(LINK->J * LINK->z + 0.5); + LINK->a3 = LINK->a2 + LINK->dash; + LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5); + LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5); + if (LINK->a3 <= LINK->a1) + { + if (LINK->useXaxis) + diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex); + else + diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex); + LINK->a2 = LINK->a3 + LINK->gap; + if (extra > 0) + LINK->a2 += (int32) floor(LINK->z * 0.5 + 0.5); + LINK->a3 = LINK->a2 + LINK->dot; + LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5); + LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5); + if (LINK->a3 <= LINK->a1) + { + if (LINK->useXaxis) + diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex); + else + diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex); + } + } + LINK->J++; + } while (LINK->a3 < LINK->a1); + break; + } +} /* spread */ + +static void +balance(lt, extra, T, LINK) + LineStyle lt; + int32 extra, T; + struct LOC_tylBrokenLine *LINK; +{ + if (T == 0) + { /* only partial frame fits */ + if (LINK->useXaxis) + diagonal(LINK->a0, LINK->b0, LINK->a1, LINK->b1, LINK->fontindex); + else + diagonal(LINK->b0, LINK->a0, LINK->b1, LINK->a1, LINK->fontindex); + return; + } + LINK->J = 0; + LINK->s = float_(LINK->b1 - LINK->b0) / float_(LINK->a1 - LINK->a0); + switch (lt) + { + + case dashed: + do + { + LINK->a2 = LINK->a0 + LINK->J * LINK->frame - extra / 2; + LINK->a3 = LINK->a2 + LINK->dash; + if (LINK->J == 0) + LINK->a2 = LINK->a0; + if (LINK->a3 > LINK->a1) + LINK->a3 = LINK->a1; + LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5); + LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5); + if (LINK->a3 <= LINK->a1) + { + if (LINK->useXaxis) + diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex); + else + diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex); + } + LINK->J++; + } while (LINK->a3 < LINK->a1); + break; + + case dotdash: + do + { + LINK->a2 = LINK->a0 + LINK->J * LINK->frame - extra / 2; + LINK->a3 = LINK->a2 + LINK->dash; + if (LINK->J == 0) + LINK->a2 = LINK->a0; + if (LINK->a3 > LINK->a1) + LINK->a3 = LINK->a1; + LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5); + LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5); + if (LINK->a3 <= LINK->a1) + { + if (LINK->useXaxis) + diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex); + else + diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex); + LINK->a2 = LINK->a3 + LINK->gap; + LINK->a3 = LINK->a2 + LINK->dot; + LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5); + LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5); + if (LINK->a3 <= LINK->a1) + { + if (LINK->useXaxis) + diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex); + else + diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex); + } + } + LINK->J++; + } while (LINK->a3 < LINK->a1); + break; + } +} /* balance */ + +static int32 +project(I, LINK) + int32 I; + struct LOC_tylBrokenLine *LINK; +{ + int32 K; /* gives the projection of lengths onto axes */ + + K = (int32) floor(I * float_(abs(LINK->a1 - LINK->a0)) / LINK->s + 0.5); + if (K == 0) + K = 1; + return K; +} + +static void +setlengths(findex, LINK) + int32 findex; + struct LOC_tylBrokenLine *LINK; +{ + /* sets the "optimal" sizes for textured lines */ + int32 penrad; + VThickness siz; + + penrad = VFontTable[findex - 1]->PenSize; + siz = VFontTable[findex - 1]->psize; + + LINK->Dotdot = penrad / siz; + LINK->Dotgap = penrad * 6; + LINK->Dashdash = penrad * 6; + LINK->Dashgap = penrad * 6; + LINK->DDotdash = penrad * 6; + LINK->DDotgap = penrad * 4; + LINK->DDotdot = penrad / siz; +} + +static void +setframesize(LINK) + struct LOC_tylBrokenLine *LINK; +{ + switch (LINK->line_type) + { + /* length of frame depends on type of broken line */ + case solid: + LINK->frame = 0; + break; + case dotted: + LINK->frame = LINK->gap + LINK->dot; + break; + case dashed: + LINK->frame = LINK->gap + LINK->dash; + break; + case dotdash: + LINK->frame = LINK->gap * 2 + LINK->dot + LINK->dash; + break; + } +} + +static void +tylBrokenLine(x0, y0, x1, y1, fontindex_, line_type_) + int32 x0, y0, x1, y1, fontindex_; + LineStyle line_type_; +{ + struct LOC_tylBrokenLine V; + double fit; + int32 T, a1ma0; + + V.fontindex = fontindex_; + V.line_type = line_type_; + if (x0 == x1 && y0 == y1) + { + diagonal(x0, y0, x1, y1, V.fontindex); /* null line */ + return; + } + + setlengths(V.fontindex, &V); + + if (abs(y1 - y0) > abs(x1 - x0)) + { /* longer axis is used as base */ + V.useXaxis = false; + V.a0 = y0; + V.b0 = x0; + V.a1 = y1; + V.b1 = x1; + } + else + { + V.useXaxis = true; + V.a0 = x0; + V.b0 = y0; + V.a1 = x1; + V.b1 = y1; + } + /* the distance between a0 and a1 is now greater than that between b0 and b1. */ + + /* redefine distances as integral units along axes */ + V.s = distance(float_(V.a0), float_(V.b0), float_(V.a1), float_(V.b1)); + + switch (V.line_type) + { + + case solid: + /* blank case */ + break; + case dotted: + V.gap = project(V.Dotgap, &V); + V.dot = project(V.Dotdot, &V); + break; + case dashed: + V.gap = project(V.Dashgap, &V); + V.dash = project(V.Dashdash, &V); + break; + case dotdash: + V.gap = project(V.DDotgap, &V); + V.dot = project(V.DDotdot, &V); + V.dash = project(V.DDotdash, &V); + break; + } + + /* + * ensure direction of line is from smaller to larger along the longer axis + */ + if (V.a0 > V.a1) + { + V.J = V.a0; + V.a0 = V.a1; + V.a1 = V.J; + V.J = V.b0; + V.b0 = V.b1; + V.b1 = V.J; + } + + setframesize(&V); + + a1ma0 = V.a1 - V.a0; + + /* fit is the number of frames that fit in line */ + if (V.frame != 0) + fit = float_(a1ma0) / float_(V.frame); + else + fit = 1.0; + + if (fit >= 1.0) + T = (int32) floor(fit + 0.5); + else + { + /* change frame elements (dot, dash, gap) since frame is too large */ + switch (V.line_type) + { + + case dotted: + V.gap += a1ma0 - V.frame; + if (V.gap < V.dot) + return; /* exit */ + setframesize(&V); + break; + + case dashed: + case dotdash: + /* idea:decrease gap; if too small then shrink dash and refigure gap */ + if (V.frame - a1ma0 > V.gap / 2) + { + V.dash = (int32) floor(V.dash * fit * 0.80 + 0.5); + V.gap = (int32) floor(V.gap * fit + 0.5); + setframesize(&V); + } + V.gap += a1ma0 - V.frame; + if (V.line_type == dotdash) + V.gap /= 2; + if (V.gap < V.dot) + return; /* exit */ + setframesize(&V); + break; + } /* case */ + T = 1; /* NOW it will fit */ + } /* else */ + + + switch (V.line_type) + { + case solid: + if (V.useXaxis) + diagonal(V.a0, V.b0, V.a1, V.b1, V.fontindex); + else + diagonal(V.b0, V.a0, V.b1, V.a1, V.fontindex); + break; + case dotted: /* dotted lines begin and end on a dot */ + if (T * V.frame + V.dot == a1ma0) + spread(dotted, 0, T, &V); + else if (T * V.frame + V.dot > a1ma0) + { + /* + * gap := gap - ((T*frame+dot)-a1ma0); { + */ + spread(dotted, a1ma0 - T * V.frame - V.dot, T, &V); + + /* + * spread(dotted, a1ma0 - (T-1)*frame - dot, T-1); { + */ + } + else + spread(dotted, a1ma0 - T * V.frame - V.dot, T, &V); + break; + case dashed: + /* + * dashed lines begin and end on dash : the beginning and ending dashes are at least half the dash length + * int32. + */ + if (T * V.frame + V.dash == a1ma0) + spread(dashed, 0, T, &V); + else if (T * V.frame + V.dash > a1ma0) + balance(dashed, T * V.frame + V.dash - a1ma0, T, &V); + else + spread(dashed, a1ma0 - T * V.frame - V.dash, T, &V); + break; + case dotdash: + /* + * if ending on a dash then beginning and ending dashes are half the dash length long - final dots are full + * dot length + */ + if (T * V.frame + V.dash == a1ma0) + spread(dotdash, 0, T, &V); + else if (T * V.frame + V.dash + V.gap + V.dot == a1ma0) + spread(dotdash, 0, T, &V); + else if (T * V.frame + V.dash > a1ma0) + balance(dotdash, T * V.frame + V.dash - a1ma0, T, &V); + else if (T * V.frame + V.dash + V.gap + V.dot > a1ma0) + spread(dotdash, a1ma0 - T * V.frame - V.dash, T, &V); + else + spread(dotdash, a1ma0 - T * V.frame - V.dash - V.gap - V.dot, T, &V); + break; + } +} + +void +clampthickness(thic) + VThickness *thic; +{ + /* + * #### this is just a simple clamp really should be something like: while not (thic in set_of_appropriate_thicknesses) + * do modify thic and try again + */ + if (*thic <= LoVThick) + *thic = LoVThick + 1; + while (((1 << (*thic)) & 0x1ffe) == 0 && *thic <= HiVThick) + (*thic)++; + if (*thic > HiVThick) + *thic = HiVThick; +} + +static void +slurclamp(thic, totpts) + VThickness *thic; + int32 totpts; +{ + /* + * this post-clamps the sampled thicknesses calculated over the whole of the spline + */ + int32 i, oneseventh, middle, startval, endval; + double deltaval, val, incrval, alpha, alphaincr; + + /* + * $$ NOTE:: How does the ttspline interpolation of thicknesses compare to the below results?? Can we avoid having it + * done elsewhere and concentrate on it here?? + */ + + oneseventh = (int32) floor(totpts / 7.0 + 0.5); + for (i = 1; i <= oneseventh; i++) + thic[i] = thic[1]; + for (i = oneseventh * 6; i <= totpts; i++) + thic[i] = thic[totpts]; + + middle = (int32) floor(totpts / 2.0 + 0.5); + for (i = oneseventh * 3; i <= oneseventh * 4; i++) + thic[i] = thic[middle]; + + startval = thic[oneseventh - 1]; + endval = thic[oneseventh * 3 + 1]; + deltaval = (endval - startval) * 2.0 / (oneseventh * 2); + alphaincr = PI / (oneseventh * 2 + 1); + alpha = PI; + val = float_(startval); + for (i = oneseventh; i < oneseventh * 3; i++) + { /* interpolate: ease in from minthick to middlethickness */ + alpha += alphaincr; + incrval = (cos(alpha) + 1.0) / 2.0 * deltaval; + val += incrval; + thic[i] = (int32) floor(val + 0.5); + } + + startval = thic[oneseventh * 4 - 1]; + endval = thic[oneseventh * 6 + 1]; + deltaval = (endval - startval) * 2.0 / (oneseventh * 2); + alphaincr = PI / (oneseventh * 2 + 1); + alpha = 0.0; + val = float_(startval); + for (i = oneseventh * 4 + 1; i <= oneseventh * 6; i++) + { /* ease out from middle thickness to min thick at far end */ + alpha += alphaincr; + incrval = (cos(alpha) + 1.0) / 2.0 * deltaval; + val += incrval; + thic[i] = (int32) floor(val + 0.5); + } +} + +void +layline(xl, yb, xr, yt, fontindex, pattern, useVecfontOnly) + int32 xl, yb, xr, yt, fontindex; + LineStyle pattern; + int useVecfontOnly; +{ + int32 t; + + if (xr < xl) + { + t = xr; + xr = xl; + xl = t; + t = yb; + yb = yt; + yt = t; + } + + isetfont(VFontTable[fontindex - 1]->DVIFontNum); + + /* + * we may want to require using a vector font only, instead of a combination of vectors and TeX-rules. It may look + * better this way. + */ + if (useVecfontOnly) + { + tylBrokenLine(xl, yb, xr, yt, fontindex, pattern); + return; + } + + if ((xl != xr || yb != yt) && (xl == xr || yb == yt)) + { /* Null or diagonal lines */ + /* + * if (pattern = solid) then hvline (xl, yb, xr, yt, fontindex) (* make use of rules *) else USENORULES + */ + tylBrokenLine(xl, yb, xr, yt, fontindex, pattern); + return; + } + if (pattern == solid) + diagonal(xl, yb, xr, yt, fontindex); + else + tylBrokenLine(xl, yb, xr, yt, fontindex, pattern); + /* be smart about the lines */ +} + + +#define DontDoThicks false +#define VectorsOnly true + +/* Local variables for layAspline: */ +struct LOC_layAspline +{ + VThickness thick; +}; + +void +layAspline(thetype, isclosed, isanArc, domarks, cpts, numpts, + thick_, vkind, patt) + SplineKind thetype; + int isclosed, isanArc; + int32 domarks; +int32(*cpts)[2]; + int32 numpts; + VThickness thick_; + VectKind vkind; + LineStyle patt; +{ + struct LOC_layAspline V; + SplineSegments pointList; + int32 i, xs, ys; + ThickAryType tt1, tt2; + VecIndex F; + int32 FORLIM; + + V.thick = thick_; + clampthickness(&V.thick); + for (i = 0; i <= numpts + 3; i++) + tt1[i] = V.thick; + + /* do any marks if necessary to show the control points */ + if (domarks > 0) + { + F = GetVectFont((int) domarks, VKCirc); + isetfont(VFontTable[F - 1]->DVIFontNum); + for (i = 1; i <= numpts; i++) + Tyldot(cpts[i][0], cpts[i][1]); + } + + drawSpline(thetype, isclosed, isanArc, patt, numpts, cpts, pointList, + DontDoThicks, tt1, tt2); + + + F = GetVectFont(V.thick, vkind); + xs = pointList[0][0]; + ys = pointList[0][1]; + + FORLIM = lastPoint; + for (i = 1; i < FORLIM; i++) + { + layline(xs, ys, pointList[i][0], pointList[i][1], F, patt, VectorsOnly); + xs = pointList[i][0]; + ys = pointList[i][1]; + } + if (isclosed) /* complete the motion */ + layline(pointList[lastPoint - 1][0], pointList[lastPoint - 1] + [1], pointList[0][0], pointList[0][1], F, patt, VectorsOnly); +} + +#define NotAnArc false +#define DoThicksToo true +#define VectorsOnly true + +void +layNspline(thetype, isclosed, isitaslur, domarks, cpts, numpts, + thickmatrix, vkind, patt) + SplineKind thetype; + int isclosed, isitaslur; + int32 domarks; +int32(*cpts)[2]; + int32 numpts; + VThickness *thickmatrix; + VectKind vkind; + LineStyle patt; +{ + SplineSegments pointList; + int32 i, xs, ys; + VThickness ts; + ThickAryType tt; + VecIndex F; + int32 FORLIM; + + /* do any marks if necessary to show the control points */ + if (domarks > 0) + { + F = GetVectFont((int) domarks, VKCirc); + isetfont(VFontTable[F - 1]->DVIFontNum); + for (i = 1; i <= numpts; i++) + Tyldot(cpts[i][0], cpts[i][1]); + } + + drawSpline(thetype, isclosed, NotAnArc, patt, numpts, cpts, pointList, + DoThicksToo, thickmatrix, tt); + if (isitaslur && !skiptsclamp) + slurclamp(tt, lastPoint); /* which kind of clamping to use */ + + xs = pointList[0][0]; + ys = pointList[0][1]; + ts = tt[1]; + + FORLIM = lastPoint; + for (i = 1; i < FORLIM; i++) + { + clampthickness(&ts); + F = GetVectFont(ts, vkind); + layline(xs, ys, pointList[i][0], pointList[i][1], F, patt, VectorsOnly); + xs = pointList[i][0]; + ys = pointList[i][1]; + ts = tt[i + 1]; + } + if (!isclosed) + return; + ts = tt[lastPoint]; + clampthickness(&ts); + F = GetVectFont(ts, vkind); + layline(pointList[lastPoint - 1][0], pointList[lastPoint - 1] + [1], pointList[0][0], pointList[0][1], F, patt, VectorsOnly); +} + +/* && start dvidvi section */ +/*-----------------------------------------------------*/ +static void +initialize() +{ + initVnMnLtables(); + multifigure = 0; + pgfigurenum = 0; + TotBytesWritten = 0; + ourq = 0; + currpagenum = 0; + FTBDs = 0; + InitDVIBuf(); + inpostamble = false; + didnewfonts = false; + skiptsclamp = false; + ErrorOccurred = false; +} + +/*-----------------------------------------------------*/ +static int +inTFM(z) + int32 z; +{ + int32 k, lh, nw, alpha, beta, FORLIM; + fontinfo *WITH; + + readtfmword(); + lh = b2 * 256 + b3; + readtfmword(); + font[nf].bc = b0 * 256 + b1; + font[nf].ec = b2 * 256 + b3; + if (font[nf].ec < font[nf].bc) + font[nf].bc = font[nf].ec + 1; + readtfmword(); + nw = b0 * 256 + b1; + if (nw == 0 || nw > 256) + return (false); + for (k = 1; k <= lh + 3; k++) + { + if (feof(tfmfile)) + return (false); + readtfmword(); + if (k == 4) + { + if (b0 < 128) + tfmchecksum = ((b0 * 256 + b1) * 256 + b2) * 256 + b3; + else + tfmchecksum = (((b0 - 256) * 256 + b1) * 256 + b2) * 256 + b3; + } + } + + FORLIM = font[nf].ec - font[nf].bc; + for (k = 0; k <= FORLIM; k++) + { + readtfmword(); + if (b0 > nw) + return (false); + font[nf].widths[k] = b0; + } + alpha = z * 16; + beta = 16; + while (z >= TWO23) + { + z /= 2; + beta /= 2; + } + for (k = 0; k < nw; k++) + { + readtfmword(); + inwidth[k] = ((b3 * z / 256 + b2 * z) / 256 + b1 * z) / beta; + if (b0 > 0) + { + if (b0 < 255) + return (false); + inwidth[k] -= alpha; + } + } + if (inwidth[0] != 0) + return (false); + WITH = &font[nf]; /* with */ + FORLIM = WITH->ec - WITH->bc; + for (k = 0; k <= FORLIM; k++) + { + if (WITH->widths[k] == 0) + { + WITH->widths[k + WITH->bc] = TWO31; + /* pixelwidths[k + bc] := 0; */ + } + else + { + WITH->widths[k + WITH->bc] = inwidth[WITH->widths[k]]; + /* pixelwidths[k + bc] := round(conv * widths[k]); */ + } + } + return (true); +} + +static void +Fastdefinefont(fn) + int32 fn; +{ + int32 p, k, n; + + (void) Dsign4byte(); + (void) Dsign4byte(); + (void) Dsign4byte(); + p = Dget1byte(); + n = Dget1byte(); + for (k = 1; k <= p + n; k++) + (void) Dget1byte(); +} /* Fastdefinefont */ + +static void +definefont(e) + int32 e; +{ + char f; + int32 p, k, n, c, q, d; + charstring tfmname; + + if (nf == MAXFONTS) + { + complain(ERRREALBAD); + fprintf(logfile, "TeXtyl capacity exceeded (max fonts=%d)!\n", + MAXFONTS); + jumpout(); + } + font[nf].num = e; + f = 0; + while (font[f].num != e)/* find first occurrence */ + f++; + c = Dsign4byte(); + font[nf].checksum = c; + q = Dsign4byte(); + font[nf].scaledsize = q; + d = Dsign4byte(); + font[nf].designsize = d; + p = Dget1byte(); + n = Dget1byte(); + for (k = 0; k < p + n; k++) + font[nf].name[k] = Dget1byte(); + font[nf].name[k] = '\0'; + + if (f != nf) /* f = nf */ + return; + + strcpy(tfmname, font[nf].name); + strcat(tfmname, ".tfm"); + + if (!opentfmfile(tfmname)) + { + complain(ERRREALBAD); + fprintf(logfile, "%s---not loaded, TFM file can't be opened!\n", tfmname); + jumpout(); + return; + } + if (q <= 0 || q >= TWO27) + { + complain(ERRREALBAD); + fprintf(logfile, "%s---not loaded, bad scale (%d)!\n", tfmname, q); + return; + } + if (d <= 0 || d >= TWO27) + { + complain(ERRREALBAD); + fprintf(logfile, "%s---not loaded, bad design size (%d)!\n", tfmname, d); + return; + } + if (!inTFM(q)) + { /* intfm */ + complain(ERRREALBAD); + fprintf(logfile, "%s---not loaded, TFM file is bad\n", tfmname); + return; + } /* intfm */ + font[nf].space = q / 6; + if (c != 0 && tfmchecksum != 0 && c != tfmchecksum) + { + fprintf(logfile, "Problem in fig#%d on page %d\n", + pgfigurenum, currpagenum); + fprintf(logfile, "%s---beware: check sums do not agree!\n", tfmname); + fprintf(logfile, " (%d vs. %d)\n", c, tfmchecksum); + } + d = (int32) floor(100.0 * conv * q / (trueconv * d) + 0.5); + nf++; + font[nf].space = 0; +} + +static int32 +firstpar(o) + int o; +{ + int32 fpar; + + if (0 <= o && o <= 127) + fpar = o; + else if (171 <= o && o <= 234) + fpar = o - 171; + else + switch (o) + { + case 128: + case 133: + case 235: + case 239: + case 243: + fpar = Dget1byte(); + break; + case 129: + case 134: + case 236: + case 240: + case 244: + fpar = Dget2byte(); + break; + case 130: + case 135: + case 237: + case 241: + case 245: + fpar = Dget3byte(); + break; + case 143: + case 148: + case 153: + case 157: + case 162: + case 167: + fpar = Dsign1byte(); + break; + case 144: + case 149: + case 154: + case 158: + case 163: + case 168: + fpar = Dsign2byte(); + break; + case 145: + case 150: + case 155: + case 159: + case 164: + case 169: + fpar = Dsign3byte(); + break; + case 131: + case 132: + case 136: + case 137: + case 146: + case 151: + case 156: + case 160: + case 165: + case 170: + case 238: + case 242: + case 246: + fpar = Dsign4byte(); + break; + case 138: + case 139: + case 140: + case 141: + case 142: + case 247: + case 248: + case 249: + case 250: + case 251: + case 252: + case 253: + case 254: + case 255: + fpar = 0; + break; + case 147: + fpar = w; + break; + case 152: + fpar = x; + break; + case 161: + fpar = y; + break; + case 166: + fpar = z; + break; + } + return fpar; +} + +static int +specialcases(o, p) + int32 o, p; +{ + if (o < 157 || o > 249) + { + complain(ERRREALBAD); + fprintf(logfile, "undefined command %d!\n", o); + return (true); + } + else if (171 <= o && o <= 238) + { + font[nf].num = p; + curfont = 0; + while (font[curfont].num != p) + curfont++; + return (true); + } + switch (o) + { + case 157: + case 158: + case 159: + case 160: + break; + case 161: + case 162: + case 163: + case 164: + case 165: + y = p; + break; + case 166: + case 167: + case 168: + case 169: + case 170: + z = p; + break; + case 243: + case 244: + case 245: + case 246: + definefont(p); + return (true); + case 239: + case 240: + case 241: + case 242: /* =========specials============= */ + mainhandlespecials(o, p); + return (true); + case 247: + complain(ERRREALBAD); + fprintf(logfile, "preamble command within a page!\n"); + return (false); + case 248: + case 249: + complain(ERRREALBAD); + fprintf(logfile, "postamble command within a page!\n"); + return (false); + } + if (v > 0 && p > 0) + { + if (v > TWO31 - p) + p = TWO31 - v; + } + if (v < 0 && p < 0) + { + if (-v > p + TWO31) + p = -v - TWO31; + } + v += p; + return (true); +} + +static int +dopage() +{ + int32 o, p, q; + struct stackrec *WITH; + + curfont = nf; + s = 0; + h = 0; + v = 0; + w = 0; + x = 0; + y = 0; + z = 0; + + ourxpos = 0; + ourypos = 0; + ourfontnum = -1; + for (;;) + { + o = Dget1byte(); + p = firstpar(o); + if (feof(dvifile)) + { + fprintf(logfile, "Bad DVI file: the file ended prematurely!\n"); + jumpout(); + } + if (o <= 131) + goto _L41; + if (o > 156) + { + if (specialcases(o, p)) + continue; + else + return (false); + } + + switch (o) + { + case 133: + case 134: + case 135: + case 136: + goto _L41; + break; + case 132: + case 137: + goto _L42; + break; + case 138: + continue; + case 139: /* BOP */ + complain(ERRREALBAD); + fprintf(logfile, "bop occurred before eop\n"); + return (false); /* Fail */ + break; + case 140: /* EOP */ + if (s != 0) + { + complain(ERRREALBAD); + fprintf(logfile, "stack not empty at end of page (level %d)!\n", s); + } + if (multifigure != 0) + { + complain(ERRBAD); + fprintf(logfile, + "Some figure definition not closed at end of page %d!\n", + currpagenum); + } + fprintf(logfile, "%d]", currpagenum); + if (currpagenum % 10 == 0) + putc('\n', logfile); + return (true); + case 141: /* PUSH */ + WITH = &stack[s]; /* with */ + WITH->sh = h; + WITH->sv = v; + WITH->sw = w; + WITH->sx = x; + WITH->sy = y; + WITH->sz = z; + s++; + continue; + case 142: /* POP */ + if (s == 0) + { + complain(ERRREALBAD); + fprintf(logfile, "illegal pop at level zero!\n"); + } + else + { + s--; + WITH = &stack[s]; + h = WITH->sh; + v = WITH->sv; + w = WITH->sw; + x = WITH->sx; + y = WITH->sy; + z = WITH->sz; + } + continue; + case 143: + case 144: + case 145: + case 146: + q = p; + goto _L43; + break; + case 147: + case 148: + case 149: + case 150: + case 151: + w = p; + q = p; + goto _L43; + break; + case 152: + case 153: + case 154: + case 155: + case 156: + x = p; + q = p; + goto _L43; + break; + } /* case */ +_L41: /* finish cmd to set/put a char */ + if (p < 0) + p = 255 - ((-p - 1) & 255); + else if (p >= 256) + p &= 255; + if (p < font[curfont].bc || p > font[curfont].ec) + q = TWO31; + else + q = font[curfont].widths[p]; + if (q == TWO31) + { + complain(ERRREALBAD); + fprintf(logfile, "Character %d invalid in font #%d\n", p, curfont); + } + if (o >= 133) + continue; + if (q == TWO31) + q = 0; + goto _L43; +_L42: /* finish cmd to set/put rule */ + q = Dsign4byte(); + if (o == 137) + continue; + goto _L43; +_L43: /* finish cmd that sets h += q */ + if (h > 0 && q > 0) + { + if (h > TWO31 - q) + q = TWO31 - h; + } + if (h < 0 && q < 0) + { + if (-h > q + TWO31) + q = -h - TWO31; + } + h += q; + } +} + +static void +skippages() +{ + int32 p; + int32 k; + + for (;;) + { + if (feof(dvifile)) + { + fprintf(logfile, "Bad DVI file: the file ended prematurely!\n"); + jumpout(); + } + k = Dget1byte(); + p = firstpar(k); + switch (k) + { + case 139: /* BOP */ + newbackptr = DVIMark() + TotBytesWritten - 1; + currpagenum = Dsign4byte(); /* count[0] */ + for (k = 1; k <= 9; k++) /* WAS count[k] := */ + (void) Dsign4byte(); + (void) Dsign4byte(); + BackupInBuf(4); + cmdSigned(oldbackptr, 4); + oldbackptr = newbackptr; + fprintf(logfile, "["); + return; + case 132: + case 137: /* RULE */ + (void) Dsign4byte(); + break; + case 243: + case 244: + case 245: + case 246: + definefont(p); + break; + case 239: + case 240: + case 241: + case 242: /* specials */ + mainhandlespecials(k, p); + break; + case 248: /* POST */ + ourq = DVIMark() + TotBytesWritten - 1; + inpostamble = true; + return; + } + } +} + +static void +readpostamble() +{ + int32 k, p, m, indx, FORLIM; + MusFontInfRec *WITH; + VectFontInfRec *WITH1; + LabFontInfRec *WITH2; + + if (Dsign4byte() != numerator) + fprintf(logfile, "Postamble numerator doesn't match the preamble!\n"); + if (Dsign4byte() != denominator) + fprintf(logfile, "Postamble denominator doesn't match the preamble!\n"); + if (Dsign4byte() != mag) + fprintf(logfile, "Postamble magnification doesn't match the preamble!\n"); + maxv = Dsign4byte(); + maxh = Dsign4byte(); + maxs = Dget2byte(); + BackupInBuf(2); + cmd2byte(maxs + 2); + /* + * pretend the stack depth does not increase by more than two + */ + totalpages = Dget2byte(); + do + { + k = Dget1byte(); + if (k >= 243 && k < 247) + { + p = firstpar(k); + Fastdefinefont(p); + k = 138; + } + } while (k == 138); /* NOP */ + + /* + * here, backup 1, enter all our fonts and then output the 249 that we backed over + */ + BackupInBuf(1); + FORLIM = MFontsDefd; + for (indx = 0; indx < FORLIM; indx++) + { + WITH = MFontTable[indx]; + enterfont(WITH->DVIFontNum, WITH->Cksum, WITH->DesSize, WITH->DesSize, + WITH->FontName); + } /* for */ + FORLIM = VFontsDefd; + for (indx = 0; indx < FORLIM; indx++) + { + WITH1 = VFontTable[indx]; + enterfont(WITH1->DVIFontNum, WITH1->Cksum, WITH1->DesSize, WITH1->DesSize, + WITH1->FontName); + } /* for */ + FORLIM = LFontsDefd; + for (indx = 0; indx < FORLIM; indx++) + { + WITH2 = LFontTable[indx]; + enterfont(WITH2->DVIFontNum, WITH2->Cksum, WITH2->DesSize, WITH2->DesSize, + WITH2->FontName); + } + cmd1byte(249); /* post post */ + + if (k != 249) + fprintf(logfile, "byte %d is not postpost!\n", k); + (void) Dsign4byte(); + BackupInBuf(4); + cmd4byte(ourq); + m = Dget1byte(); + if (m != 2) + fprintf(logfile, "identification should be %d!\n", 2); + m = 223; + while ((m == 223) && (!feof(dvifile))) + m = Dget1byte(); + if (feof(dvifile)) + return; + fprintf(logfile, "Bad DVI file: signature in should be 223!\n"); + jumpout(); +} + + +/* MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN */ +int +main(argc, argv) + int argc; + char *argv[]; +{ + void exit PP((int)); + + if (setjmp(_JL666)) + goto _L666; + initialize(); + if (argc < 3) + { + fprintf(stderr, "Usage: textyl dvi-in dvi-out\n"); + exit(1); + } + if ((dvifile = fopen(argv[1], "r")) == NULL) + { + perror(argv[1]); + exit(1); + } + if ((outputfil = fopen(argv[2], "w")) == NULL) + { + perror(argv[2]); + exit(1); + } + logfile = stdout; + fprintf(logfile, "%s for Berkeley Unix\n", TylVersion); + + p = Dget1byte(); + if (p != 247) + { + fprintf(logfile, "Bad DVI file: First byte isn't start of preamble!!\n"); + jumpout(); + } + p = Dget1byte(); + if (p != 2) + fprintf(logfile, "identification in byte 1 should be %d!\n", 2); + numerator = Dsign4byte(); + denominator = Dsign4byte(); + if (numerator <= 0) + { + fprintf(logfile, "Bad DVI file: numerator is %d!\n", numerator); + jumpout(); + } + if (denominator <= 0) + { + fprintf(logfile, "Bad DVI file: denominator is %d!\n", denominator); + jumpout(); + } + conv = numerator / 254000.0 * (resolution / denominator); + mag = Dsign4byte(); + if (mag <= 0) + { + fprintf(logfile, "Bad DVI file: magnification is % .1E!\n", mag); + jumpout(); + } + magfactor = mag / 1000.0; + trueconv = conv; + conv = trueconv * magfactor; + p = Dget1byte(); /* the 'k' of the preamble */ + while (p > 0) + { + p--; + (void) Dget1byte(); + } + + skippages(); + if (!inpostamble) + { + while (maxpages-- > 0) + { /* while */ + if (!dopage()) + { + printf(" Bad DVI file: page ended unexpectedly!"); + fprintf(logfile, "Bad DVI file: page ended unexpectedly!\n"); + jumpout(); + } + WriteDVIBuf(); + ClearDVIBuf(); + multifigure = 0; + pgfigurenum = 0; + FTBDs = 0; + didnewfonts = false; + do + { + k = Dget1byte(); + if (k >= 243 && k < 247) + { /* fontdefs */ + p = firstpar(k); + definefont(p); + k = 138; + } + } while (k == 138); /* nop */ + + if (k == 248) + { + inpostamble = true; + ourq = DVIMark() + TotBytesWritten - 1; + break; + } + + if (k != 139) + { /* BOP */ + fprintf(logfile, "We did not find BOP when expected\n"); + jumpout(); + continue; + } + + newbackptr = DVIMark() + TotBytesWritten - 1; + currpagenum = Dsign4byte(); /* Count[0] */ + for (k = 1; k <= 9; k++) /* WAS count[k] := */ + (void) Dsign4byte(); + (void) Dsign4byte(); /* backpointer */ + BackupInBuf(4); + cmdSigned(oldbackptr, 4); + oldbackptr = newbackptr; + fprintf(logfile, "["); + } /* while */ + } /* if not inpostamble */ + if (!inpostamble) + skippages(); + (void) Dsign4byte(); /* ptr to the last bop in file */ + BackupInBuf(4); + cmdSigned(oldbackptr, 4); + readpostamble(); + WriteDVIBuf(); + + while ((TotBytesWritten & 3) != 0) /* final signatures */ + OutputByte(223); + + fprintf(logfile, "(%d page", currpagenum); + if (currpagenum > 1) + putc('s', logfile); + fprintf(logfile, ", %d bytes).\n", TotBytesWritten); + +_L666: + if (ErrorOccurred) + { + fprintf(logfile, "\nSome error(s) occurred.\n"); + fprintf(logfile, "Assume that the outputfile is incorrect\n"); + } + if (dvifile != NULL) + fclose(dvifile); + if (tfmfile != NULL) + fclose(tfmfile); + if (outputfil != NULL) + fclose(outputfil); + if (logfile != NULL) + fclose(logfile); + exit(0); + return (0); +} diff --git a/macros/latex209/contrib/textyl/src/tyl.c b/macros/latex209/contrib/textyl/src/tyl.c new file mode 100644 index 0000000000..e95445bf69 --- /dev/null +++ b/macros/latex209/contrib/textyl/src/tyl.c @@ -0,0 +1,1509 @@ +#include "defs.h" +#include "globals.h" + +static ScaledPts dviBBlx, dviBBrx; /* Bounding box of figure in DVI space */ +static ScaledPts dviBBby, dviBBty; +static int32 prevfont; +/* + * to keep track of prev font before the PUSH and expansion of the special + */ +static int32 ourpushdepth = 0; /* depth of internal pushes */ +static int32 origTexfont = -1; /* number of TeX font in use before tyling */ + +static void +IPUSH() +{ + if (ourpushdepth == 0) /* first push --> start tyling */ + origTexfont = font[curfont].num; + else + prevfont = ourfontnum; + /* store the internal font number in use at this time */ + cmd1byte(NOP); + cmd1byte(NOP); /* our greeting */ + cmd1byte(PUSH); + ourpushdepth++; +} + +static void +IPOP() +{ + cmd1byte(POP); + cmd1byte(NOP); + cmd1byte(NOP); /* our signature */ + ourpushdepth--; + if (ourpushdepth < 0) + { + complain(ERRREALBAD); + fprintf(logfile, "Error: too many internal pops\n"); + } + if (ourpushdepth == 0) + { /* we are totally done with tyling for now */ + if (nf > 0) /* only if it is valid */ + isetfont(origTexfont); + } + else + { + if (prevfont >= 0) /* restore that internal font previously in use */ + isetfont(prevfont); + } +} + +char * +xmalloc(size) + unsigned int size; +{ + char *p; + char *malloc PP((unsigned)); + void exit PP((int)); + + if ((p = malloc(size)) == 0) + { + fprintf(stderr, "Out of memory!\n"); + exit(1); + } + return (p); +} + +/*---------------------------------------------*/ +Item * +NewItem(what) + int what; +{ + Item *i; + Figure *f; + + if ((i = (Item *) xmalloc(sizeof(Item))) == 0) + i->nextitem = NULL; + i->BBlx = 0; + i->BBby = 0; + i->BBrx = 0; + i->BBty = 0; + i->itemthick = LoVThick; + i->itemvec = (unsigned) VKCirc; + i->itempatt = (unsigned) solid; + i->kind = what; + switch (what) + { /* give defaults */ + + case Aline: + /* blank case */ + break; + + case Aspline: + i->UU.U2.nsplknots = 0; + i->UU.U2.dosmarks = 0; + i->UU.U2.sclosed = false; + i->UU.U2.spltype = (unsigned) BSPL; + break; + + case Attspline: + i->UU.U3.nttknots = 0; + i->UU.U3.dottmarks = 0; + i->UU.U3.tspltype = (unsigned) BSPL; + i->UU.U3.tclosed = false; + break; + + case Abeam: + /* blank case */ + break; + + case Atieslur: + i->UU.U5.ntknots = 0; + break; + + case Aarc: + i->UU.U6.narcknots = 0; + break; + + case Alabel: + i->UU.U7.fontstyle = -1; /* undefined */ + i->UU.U7.labeltext[0] = '\0'; + break; + + case Afigure: + i->UU.U8.figtheta = 0.0; + i->UU.U8.fsx = 1.0; + i->UU.U8.fsy = 1.0; + i->UU.U8.fdx = 0; + i->UU.U8.fdy = 0; + i->UU.U8.preWid = 0; + i->UU.U8.preHt = 0; + i->UU.U8.postWid = 0; + i->UU.U8.postHt = 0; + i->UU.U8.depthnumber = 0; /* for now */ + f = (Figure *) xmalloc(sizeof(Figure)); /* a new figure */ + i->UU.U8.body = f; + i->UU.U8.body->things = NULL; + break; + } /* case */ + /* with */ + return i; +} /* NewItem */ + +/*-----------------------------------------------------*/ +static void +TylBeam(fromx, fromy, tox, toy, staffsize, kind) + int32 fromx, fromy, tox, toy, staffsize; + BeamKind kind; +{ + /* + * fromx, fromy, tox, toy: ScaledPts; staffsize : integer; kind : BeamKind + */ +} /* TylBeam */ + + +/* Local variables for TylLine: */ +struct LOC_TylLine +{ + VThickness thickness; +}; + + +/*-------------------------------------------------------*/ +static void +TylLine(xl, yb, xr, yt, thickness_, vec, patt) + int32 xl, yb, xr, yt; + VThickness thickness_; + VectKind vec; + LineStyle patt; +{ + /* + * xl, yb, xr, yt: ScaledPoints; thickness: VThickness; vec: VectKind; patt : LineStyle + */ + struct LOC_TylLine V; + VecIndex findex; + + V.thickness = thickness_; + /* + * p2c: x.p, line 6596: Note: Taking & of possibly promoted param thickness [324] + */ + clampthickness(&V.thickness); + findex = GetVectFont(V.thickness, vec); + layline(xl, yb, xr, yt, findex, patt, false); +} + +/*-----------------------------------------------------*/ +static void +TylThickThinSpline(thetype, isclosed, KnotArray, ThikThinAry, + numknots, vec, patt, domarks) + SplineKind thetype; + int isclosed; +int32(*KnotArray)[2]; + VThickness *ThikThinAry; + int32 numknots; + VectKind vec; + LineStyle patt; + int32 domarks; +{ + /* + * thetype : SplineKind; isclosed : boolean; var KnotArray: ControlPoints; var ThikThinAry: ThickAryType; numknots: + * integer; vec: VectKind; patt : LineStyle; domarks : integer + */ + layNspline(thetype, isclosed, false, domarks, KnotArray, numknots, + ThikThinAry, vec, patt); +} + +/*----------------------------------------------------*/ +static void +TylSpline(thetype, isclosed, KnotArray, numknots, thick, vec, + patt, domarks) + SplineKind thetype; + int isclosed; +int32(*KnotArray)[2]; + int32 numknots; + VThickness thick; + VectKind vec; + LineStyle patt; + int32 domarks; +{ + /* + * thetype : SplineKind; isclosed : boolean; var KnotArray: ControlPoints; numknots: integer; thick: VThickness; vec: + * VectKind; patt : LineStyle; domarks : integer + */ + layAspline(thetype, isclosed, false, domarks, KnotArray, numknots, thick, + vec, patt); +} + +#define ItsASlur true +#define NotClosed false + + +/* Local variables for TylTieSlur: */ +struct LOC_TylTieSlur +{ + VThickness minthick, maxthick; +}; + + +/*-----------------------------------------------------*/ +static void +TylTieSlur(KnotArray, numknots, minthick_, maxthick_) +int32(*KnotArray)[2]; + int32 numknots; + VThickness minthick_, maxthick_; +{ + /* + * KnotArray: ControlPoints; numknots: integer; minthick, maxthick: VThickness + */ + struct LOC_TylTieSlur V; + ThickAryType ourttarray; + double one7th; + VThickness val; + + V.minthick = minthick_; + V.maxthick = maxthick_; + /* + * p2c: x.p, line 6636: Note: Taking & of possibly promoted param minthick [324] + */ + clampthickness(&V.minthick); + /* + * p2c: x.p, line 6637: Note: Taking & of possibly promoted param maxthick [324] + */ + clampthickness(&V.maxthick); + if (numknots != 5) + fprintf(logfile, "TieSlur needs 5 control points\n"); + one7th = 1.0 / 7.0; + val = (int32) floor(one7th * (V.maxthick - V.minthick) + 0.5); + ourttarray[1] = V.minthick; + ourttarray[2] = V.minthick + val; + ourttarray[3] = V.maxthick; + ourttarray[4] = V.minthick + val; + ourttarray[5] = V.minthick; + + layNspline(CATROM, NotClosed, ItsASlur, 0, KnotArray, numknots, ourttarray, + VKCirc, solid); +} + +#undef ItsASlur +#undef NotClosed + + +#define ItsAnArc true + + +/*-------------------------------------------------------*/ +static void +doTylArc(iscircle, apts, numknots, thick, vec, patt) + int iscircle; +int32(*apts)[2]; + int32 numknots; + VThickness thick; + VectKind vec; + LineStyle patt; +{ + /* + * iscircle : boolean; var apts : ControlPoints; numknots : integer; thick : VThickness; vec : VectKind; patt : + * LineStyle + */ + layAspline(BSPL, iscircle, ItsAnArc, 0, apts, numknots, thick, vec, patt); +} + +#undef ItsAnArc + + +/*-----------------------------------------------------------*/ +static void +TylArc(radius, centx, centy, firstangle, secondangle, thick, vec, + patt) + int32 radius, centx, centy, firstangle, secondangle; + VThickness thick; + VectKind vec; + LineStyle patt; +{ + /* + * radius : ScaledPts; centx, centy : ScaledPts; firstangle, secondangle : integer; thick : VThickness; vec : VectKind; + * patt : LineStyle + */ + ControlPoints apts; + int32 numknots; + int iscircle; + + iscircle = (firstangle == secondangle); + if (iscircle) + { + /* + * maxspan := round ((360.0 / 16.0) * DEGTORAD * radius); { + */ + defineCircleCpts(radius, centx, centy, apts, &numknots); + } + else + { + /* + * maxspan := round ((abs (secondangle - firstangle) / 16.0) * DEGTORAD * radius); { + */ + definearcpts(radius, centx, centy, firstangle, secondangle, apts, + &numknots); + } + + doTylArc(iscircle, apts, numknots, thick, vec, patt); + +} + + +/*-----------------------------------------------------------*/ +static void +TylLabel(xpos, ypos, fontstyle, phrase, phraselen) + int32 xpos, ypos, fontstyle; + char *phrase; + int32 phraselen; +{ + /* + * xpos, ypos : ScaledPts; fontstyle : integer; phrase : charstring; phraselen : integer + */ + int32 findex, c, spaceover; + + if (fontstyle < 1 || fontstyle > MAXLABELFONTS) + { + complain(ERRREALBAD); + fprintf(logfile, "Unexpected bad fontstyle in TylLabel: %d?\n", + fontstyle); + jumpout(); + } + findex = GetLabFont(fontstyle); + isetpos(xpos, ypos); + IPUSH(); + isetfont(LFontTable[findex - 1]->DVIFontNum); + spaceover = LFontTable[findex - 1]->spacewidth; + for (c = 0; c < phraselen; c++) + { + if (phrase[c] != ' ') + { + cmd1byte(SET1); + cmd1byte(phrase[c]); + } + else + { /* move over */ + cmd1byte(RIGHTLEFT + 2); + /* assume distance is less than 3 bytes */ + cmdSigned(spaceover, 3); + } + } + IPOP(); +} + +/* &&module TeXtyl */ +/*----------------------------------------------------------------*/ +/* rotate a (x,y) point about mx, my */ +static void +ptrotate(x, y, mx, my, angle) + int32 *x, *y, mx, my; + double angle; +{ + int32 tmpx, tmpy; + double cosa, sina; + + tmpx = *x - mx; + tmpy = *y - my; + cosa = cos(angle * DEGTORAD); + sina = sin(angle * DEGTORAD); + *x = (int32) floor(tmpx * cosa - tmpy * sina + 0.5) + mx; + *y = (int32) floor(tmpx * sina + tmpy * cosa + 0.5) + my; +} + + +/*----------------------------------------------------------------*/ +/* + * transform two line points: scale, rotate and translate + */ +static void +xfmlinepts(x1, y1, x2, y2, offh, offv, midx, midy, scalefact, + theta, dx, dy, sx, sy) + int32 *x1, *y1, *x2, *y2, offh, offv, midx, midy; + double scalefact, theta; + int32 dx, dy; + double sx, sy; +{ + if (sx == 0.0 || sy == 0.0) + { + complain(ERRBAD); + fprintf(logfile, "?? Some scale factor is Zero... continuing anyway\n"); + } + /* scale about center of item */ + if (sx != 1.0 || sy != 1.0) + { + *x1 = (int32) floor((*x1 - midx) * sx + 0.5) + midx; + *x2 = (int32) floor((*x2 - midx) * sx + 0.5) + midx; + *y1 = (int32) floor((*y1 - midy) * sy + 0.5) + midy; + *y2 = (int32) floor((*y2 - midy) * sy + 0.5) + midy; + } + /* rotate if necessary */ + if (theta != 0.0) + { /* rotate about the midpoint */ + ptrotate(x1, y1, midx, midy, theta); + ptrotate(x2, y2, midx, midy, theta); + } + /* translate */ + *x1 += (int32) floor(dx * scalefact + 0.5) + offh; + *x2 += (int32) floor(dx * scalefact + 0.5) + offh; + *y1 += (int32) floor(dy * scalefact + 0.5) + offv; + *y2 += (int32) floor(dy * scalefact + 0.5) + offv; +} /* xfmlinepts */ + + +/*----------------------------------------------------------------*/ +static void +xfmcontpts(xpts, xknots, offh, offv, midx, midy, scalefact, theta, + dx, dy, sx, sy) +int32(*xpts)[2]; + int32 xknots, offh, offv, midx, midy; + double scalefact, theta; + int32 dx, dy; + double sx, sy; +{ + int32 i; + + /* scale about center of item */ + if (sx != 1.0 || sy != 1.0) + { + for (i = 0; i <= xknots; i++) + { + xpts[i][0] = (int32) floor((xpts[i][0] - midx) * sx + 0.5) + midx; + xpts[i][1] = (int32) floor((xpts[i][1] - midy) * sy + 0.5) + midy; + } + } + + if (theta != 0.0) + { /* rotate about center */ + for (i = 0; i <= xknots; i++) + ptrotate(xpts[i], &xpts[i][1], midx, midy, theta); + } + /* translate */ + for (i = 0; i <= xknots; i++) + { + xpts[i][0] += (int32) floor(dx * scalefact + 0.5) + offh; + xpts[i][1] += (int32) floor(dy * scalefact + 0.5) + offv; + } +} /* xfmcontpts */ + + +/*----------------------------------------------------------------*/ +/* convert into DVI space and offset by H & V */ +static void +dvilinepts(x1, y1, x2, y2, offh, offv) + int32 *x1, *y1, *x2, *y2, offh, offv; +{ + *x1 += offh; + *x2 += offh; + *y1 = offv - *y1; + *y2 = offv - *y2; +} + + +/*----------------------------------------------------------------*/ +/* convert into DVI space and offset by H & V */ +static void +dvicontpts(xpts, xknots, offh, offv) +int32(*xpts)[2]; + int32 xknots, offh, offv; +{ + int32 i; + + for (i = 0; i <= xknots; i++) + { + xpts[i][0] += offh; + xpts[i][1] = offv - xpts[i][1]; + } +} + + +/*----------------------------------------------------------------*/ +/* + * transform all the figure's elements according to the top-level tranformation requirements in 1st Quadrant space. then reset + * the toplevel's xfms. + */ +static void +toplevelxfm(toplev, curfig, recurlevel) + Item *toplev, *curfig; + int32 recurlevel; +{ + Item *pi; + ScaledPts null1, null2, old1, old2, midx, midy; + + midy = (toplev->BBty - toplev->BBby) / 2; + midx = (toplev->BBrx - toplev->BBlx) / 2; + pi = curfig->UU.U8.body->things; /* if recur==0, this is same as toplev */ + while (pi != NULL) + { + switch (pi->kind) + { /* with */ + + case Aline: + xfmlinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2, + &pi->UU.U1.ly2, 0, 0, midx, midy, 1.0, + toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy, + toplev->UU.U8.fsx, toplev->UU.U8.fsy); + break; + + case Aspline: + xfmcontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, 0, 0, midx, midy, 1.0, + toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy, + toplev->UU.U8.fsx, toplev->UU.U8.fsy); + break; + + case Attspline: + xfmcontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, 0, 0, midx, midy, 1.0, + toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy, + toplev->UU.U8.fsx, toplev->UU.U8.fsy); + break; + + case Aarc: + null1 = 0; + null2 = 0; + old1 = pi->UU.U6.acentx; + old2 = pi->UU.U6.acenty; + xfmlinepts(&pi->UU.U6.acentx, &pi->UU.U6.acenty, &null1, &null2, 0, 0, + midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx, + toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy); + + xfmcontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, 0, 0, old1, + old2, 1.0, toplev->UU.U8.figtheta, + toplev->UU.U8.fdx + pi->UU.U6.acentx - old1, + toplev->UU.U8.fdy + pi->UU.U6.acenty - old2, + toplev->UU.U8.fsx, toplev->UU.U8.fsy); + break; + + case Alabel: + null1 = 0; + null2 = 0; + xfmlinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, 0, 0, + midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx, + toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy); + break; + + case Abeam: /* not transformable */ + break; + + case Atieslur: /* not transformable */ + break; + + case Afigure: + toplevelxfm(toplev, pi, recurlevel + 1); + break; + } /* case */ + pi = pi->nextitem; + } /* while */ + if (recurlevel != 0) /* reset the toplevel's xfms */ + return; + toplev->UU.U8.figtheta = 0.0; + toplev->UU.U8.fsx = 1.0; + toplev->UU.U8.fsy = 1.0; + toplev->UU.U8.fdx = 0; + toplev->UU.U8.fdy = 0; +} + + +/*----------------------------------------------------------------*/ +static double +scalefitfactor(actualwid, actualht, goalwid, goalht) + int32 actualwid, actualht, goalwid, goalht; +{ + double sx, sy; + + sx = (double) goalwid / actualwid; + sy = (double) goalht / actualht; + if (sx < sy) + return sx; + else + return sy; +} + + + +/* + * ---- The handlers for each primitive ---- The result of calling each handler is either immediate output to the buffer of the + * commands to produce the primitive, OR the primitive gets pushed onto a stack/list that defines a current 'figure' (set of + * prims) for output at a later time + * + * Look at linehandle for a basic idea of how the handlers work. the others follow pretty closely. + */ + + +/*------------------------------------------------------------*/ +void +linehandle(figdepth, scalefact, x1, y1, x2, y2, dvih, dviv, thk, + vk, patt, minx, maxx, miny, maxy, tx, ty, sx, sy, r) + int32 figdepth; + double scalefact; + int32 x1, y1, x2, y2, dvih, dviv; + VThickness thk; + VectKind vk; + LineStyle patt; + int32 minx, maxx, miny, maxy, tx, ty; + double sx, sy, r; +{ + /* possible dvi-offsets */ + ScaledPts midx, midy; + Item *lineitem; + + midx = (minx + maxx) / 2; + midy = (miny + maxy) / 2; + + /* do local primitive -level transformations */ + xfmlinepts(&x1, &y1, &x2, &y2, dvih, dviv, midx, midy, scalefact, r, tx, ty, + sx, sy); + + if (figdepth == 0) + { /* ---- do the primitive by itself */ + /* re-transform it to the 4th Quadrant */ + dvilinepts(&x1, &y1, &x2, &y2, h, v); /* global h and v posit */ + IPUSH(); + TylLine(x1, y1, x2, y2, thk, vk, patt); + IPOP(); + return; + } + if (figdepth <= 0) + { /* ---- Pack it and stack it */ + if (figdepth < 0) + { /* ---- just do it right away without any PUSH/POP pair */ + /* + * this is the case when we are unpacking a figure for immediate output + */ + TylLine(x1, y1, x2, y2, thk, vk, patt); + } + return; + } + lineitem = NewItem(Aline); + lineitem->BBlx = minx; + lineitem->BBby = miny; + lineitem->BBrx = maxx; + lineitem->BBty = maxy; + lineitem->UU.U1.lx1 = x1; + lineitem->UU.U1.ly1 = y1; + lineitem->UU.U1.lx2 = x2; + lineitem->UU.U1.ly2 = y2; + lineitem->itemthick = thk; + lineitem->itemvec = (unsigned) vk; + lineitem->itempatt = (unsigned) patt; + pushItem(figdepth, lineitem); +} /* linehandle */ + + +/* --- Simple Splines ----- */ +/*-----------------------------------------------------*/ +void +splinehandle(figdepth, scalefact, thetype, isclosed, markdiam, + contpts, nknots, dvih, dviv, thk, vec, patt, minx, + maxx, miny, maxy, tx, ty, sx, sy, r) + int32 figdepth; + double scalefact; + SplineKind thetype; + int isclosed; + int32 markdiam; +int32(*contpts)[2]; + int32 nknots, dvih, dviv; + VThickness thk; + VectKind vec; + LineStyle patt; + int32 minx, maxx, miny, maxy, tx, ty; + double sx, sy, r; +{ + /* possible dvi-offsets */ + ScaledPts midx, midy; + Item *splineitem; + int32 i; + + midx = (minx + maxx) / 2; + midy = (miny + maxy) / 2; + + xfmcontpts(contpts, nknots, dvih, dviv, midx, midy, scalefact, r, tx, ty, + sx, sy); + + if (figdepth == 0) + { /* ---- do the primitive */ + /* transform to 4th quad */ + dvicontpts(contpts, nknots, h, v); + IPUSH(); + TylSpline(thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam); + IPOP(); + return; + } + if (figdepth <= 0) + { + if (figdepth < 0) + TylSpline(thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam); + return; + } + splineitem = NewItem(Aspline); + splineitem->BBlx = minx; + splineitem->BBby = miny; + splineitem->BBrx = maxx; + splineitem->BBty = maxy; + splineitem->itemthick = thk; + splineitem->itemvec = (unsigned) vec; + splineitem->itempatt = (unsigned) patt; + splineitem->UU.U2.nsplknots = nknots; + splineitem->UU.U2.spltype = (unsigned) thetype; + splineitem->UU.U2.sclosed = isclosed; + splineitem->UU.U2.dosmarks = markdiam; + for (i = 1; i <= nknots; i++) + { + splineitem->UU.U2.spts[i][0] = contpts[i][0]; + splineitem->UU.U2.spts[i][1] = contpts[i][1]; + } + pushItem(figdepth, splineitem); +} /* splinehandle */ + + +/* --- Variable thickness splines ----- */ +/*-----------------------------------------------------*/ +void +ttsplhandle(figdepth, scalefact, thetype, isclosed, markdiam, + contpts_, ttks_, nknots, dvih, dviv, vec, patt, minx, + maxx, miny, maxy, tx, ty, sx, sy, r) + int32 figdepth; + double scalefact; + SplineKind thetype; + int isclosed; + int32 markdiam; +int32(*contpts_)[2]; + VThickness *ttks_; + int32 nknots, dvih, dviv; + VectKind vec; + LineStyle patt; + int32 minx, maxx, miny, maxy, tx, ty; + double sx, sy, r; +{ + /* possible dvi-offsets */ + ControlPoints contpts; + ThickAryType ttks; + ScaledPts midx, midy; + Item *ttsplitem; + int32 i; + char *memcpy PP((char *, char *, int)); + + (void) memcpy((char *)contpts, (char *)contpts_, sizeof(ControlPoints)); + (void) memcpy((char *)ttks, (char *)ttks_, sizeof(ThickAryType)); + midx = (minx + maxx) / 2; + midy = (miny + maxy) / 2; + + xfmcontpts(contpts, nknots, dvih, dviv, midx, midy, scalefact, r, tx, ty, + sx, sy); + + if (figdepth == 0) + { + /* transform to 4th quad */ + dvicontpts(contpts, nknots, h, v); + IPUSH(); + TylThickThinSpline(thetype, isclosed, contpts, ttks, nknots, vec, patt, + markdiam); + IPOP(); + return; + } + + if (figdepth <= 0) + { + if (figdepth < 0) + TylThickThinSpline(thetype, isclosed, contpts, ttks, nknots, vec, patt, + markdiam); + return; + } + ttsplitem = NewItem(Attspline); + ttsplitem->BBlx = minx; + ttsplitem->BBby = miny; + ttsplitem->BBrx = maxx; + ttsplitem->BBty = maxy; + ttsplitem->itemvec = (unsigned) vec; + ttsplitem->itempatt = (unsigned) patt; + ttsplitem->UU.U3.nttknots = nknots; + ttsplitem->UU.U3.tspltype = (unsigned) thetype; + ttsplitem->UU.U3.dottmarks = markdiam; + ttsplitem->UU.U3.tclosed = isclosed; + for (i = 1; i <= nknots; i++) + { /* ttsplitem */ + ttsplitem->UU.U3.ttpts[i][0] = contpts[i][0]; + ttsplitem->UU.U3.ttpts[i][1] = contpts[i][1]; + ttsplitem->UU.U3.ttarry[i] = ttks[i]; + } + pushItem(figdepth, ttsplitem); +} /* ttsplhandle */ + + +/* ---- Musical Beams ---- */ +/*-----------------------------------------------------*/ +void +beamhandle(depth, siz, bk, x1, y1, x2, y2) + int32 depth, siz; + BeamKind bk; + int32 x1, y1, x2, y2; +{ + Item *bmitem; + + if (depth == 0) + { + dvilinepts(&x1, &y1, &x2, &y2, h, v); + IPUSH(); + TylBeam(x1, y1, x2, y2, siz, bk); + IPOP(); + return; + } + if (depth <= 0) + { + if (depth < 0) + { + TylBeam(x1, y1, x2, y2, siz, bk); + } /* else */ + return; + } + bmitem = NewItem(Abeam); + bmitem->BBlx = min(x1, x2); + bmitem->BBby = min(y1, y2); + bmitem->BBrx = max(x1, x2); + bmitem->BBty = max(y1, y2); + bmitem->UU.U4.bx1 = x1; + bmitem->UU.U4.by1 = y1; + bmitem->UU.U4.bx2 = x2; + bmitem->UU.U4.by2 = y2; + bmitem->UU.U4.staf = siz; + bmitem->UU.U4.bkind = (unsigned) bk; /* with */ + pushItem(depth, bmitem); +} /* beamhandle */ + + +/* ---- Musical Ties and Slurs ----- */ +/*-----------------------------------------------------*/ +void +tieslurhandle(depth, pts_, numk, minthick, maxthick) + int32 depth; +int32(*pts_)[2]; + int32 numk; + VThickness minthick, maxthick; +{ + ControlPoints pts; + Item *tsitem; + int32 i; + char *memcpy PP((char *, char *, int)); + + (void) memcpy((char *)pts, (char *)pts_, sizeof(ControlPoints)); + if (depth == 0) + { + dvicontpts(pts, numk, h, v); + IPUSH(); + TylTieSlur(pts, numk, minthick, maxthick); + IPOP(); + return; + } + if (depth <= 0) + { + if (depth < 0) + { + TylTieSlur(pts, numk, minthick, maxthick); + } /* else */ + return; + } + tsitem = NewItem(Atieslur); + tsitem->UU.U5.ntknots = numk; + for (i = 1; i <= numk; i++) + { + tsitem->UU.U5.tspts[i][0] = pts[i][0]; + tsitem->UU.U5.tspts[i][1] = pts[i][1]; + } + tsitem->UU.U5.minth = minthick; + tsitem->UU.U5.maxth = maxthick; /* with */ + pushItem(depth, tsitem); +} /* tieslurhandle */ + + +/*---------------------------------------------------------*/ +void +arccirclehandle(figdepth, scalefact, cx, cy, radius, ang1, ang2, + contpts, nknots, dvih, dviv, thk, vec, patt, minx, + maxx, miny, maxy, tx, ty, sx, sy, r) + int32 figdepth; + double scalefact; + int32 cx, cy, radius, ang1, ang2; +int32(*contpts)[2]; + int32 nknots, dvih, dviv; + VThickness thk; + VectKind vec; + LineStyle patt; + int32 minx, maxx, miny, maxy, tx, ty; + double sx, sy, r; +{ + /* IN */ + /* possible dvi-offsets */ + ScaledPts midx, midy; + Item *arcitem; + int32 i; + int isclosedarc; + + midx = cx; + midy = cy; + isclosedarc = (ang1 == ang2); + /* + * if (isclosedarc) then maxspanlen := round ((360.0 / 16.0) * DEGTORAD * radius) else maxspanlen := round ((abs(ang2 - + * ang1) / 16.0) * DEGTORAD * radius); { + */ + + + xfmcontpts(contpts, nknots + 1, dvih, dviv, midx, midy, scalefact, r, tx, + ty, sx, sy); + + if (figdepth == 0) + { /* ---- just do the primitive */ + /* transform to 4th quad */ + dvicontpts(contpts, nknots + 1, h, v); + IPUSH(); + doTylArc(isclosedarc, contpts, nknots, thk, vec, patt); + IPOP(); + return; + } + if (figdepth <= 0) + { + if (figdepth < 0) + doTylArc(isclosedarc, contpts, nknots, thk, vec, patt); + return; + } + arcitem = NewItem(Aarc); + arcitem->BBlx = minx; + arcitem->BBby = miny; + arcitem->BBrx = maxx; + arcitem->BBty = maxy; + arcitem->itemthick = thk; + arcitem->itemvec = (unsigned) vec; + arcitem->itempatt = (unsigned) patt; + arcitem->UU.U6.narcknots = nknots; + arcitem->UU.U6.acentx = cx; + arcitem->UU.U6.acenty = cy; + arcitem->UU.U6.aradius = radius; + arcitem->UU.U6.firstang = ang1; + arcitem->UU.U6.lastang = ang2; + for (i = 0; i <= nknots + 1; i++) + { + arcitem->UU.U6.arcpts[i][0] = contpts[i][0]; + arcitem->UU.U6.arcpts[i][1] = contpts[i][1]; + } + pushItem(figdepth, arcitem); +} /* arccirclehandle */ + + + +/*---------------------------------------------------------*/ +void +labelhandle(depth, scalefact, lax, lay, dvih, dviv, style, phrase, + tx, ty) + int32 depth; + double scalefact; + int32 lax, lay, dvih, dviv, style; + charstring phrase; + int32 tx, ty; +{ + /* possible dvi-offsets */ + Item *labitem; + ScaledPts null1, null2; + + /* xfm the label point if necessary */ + lax += (int32) floor(tx * scalefact + 0.5); + lay += (int32) floor(ty * scalefact + 0.5); + + if (depth == 0) + { + null1 = 0; + null2 = 0; + dvilinepts(&lax, &lay, &null1, &null2, h, v); + IPUSH(); + TylLabel(lax, lay, style, phrase, strlen(phrase)); + IPOP(); + return; + } + if (depth <= 0) + { + if (depth < 0) + TylLabel(lax, lay, style, phrase, strlen(phrase)); + return; + } + labitem = NewItem(Alabel); + labitem->UU.U7.labx = lax; + labitem->UU.U7.laby = lay; + labitem->UU.U7.fontstyle = style; + strcpy(labitem->UU.U7.labeltext, phrase); + pushItem(depth, labitem); +} + +/* + * #### Insert new handlers here for new "primitives" i.e., names callable from the \special[tyl ...] level + */ + +/*----------------------------------------------------------------*/ +/* transform the current bbox coordinates, and output the new one */ +static void +newbbox(minx, maxx, miny, maxy, midx, midy, sx, sy, rot, tx, ty) + int32 *minx, *maxx, *miny, *maxy, midx, midy; + double sx, sy, rot; + int32 tx, ty; +{ + /* coords of full bbox for transformation [n/s][e/w][x/y] */ + ScaledPts nex, ney, sex, sey, swx, swy, nwx, nwy; + int32 temp1, temp2; + + /* describe and transform the bbox */ + nwx = (int32) floor(*minx * sx + 0.5); + nex = (int32) floor(*maxx * sx + 0.5); + sex = (int32) floor(*maxx * sx + 0.5); + swx = (int32) floor(*minx * sx + 0.5); + ney = (int32) floor(*maxy * sy + 0.5); + nwy = (int32) floor(*maxy * sy + 0.5); + swy = (int32) floor(*miny * sy + 0.5); + sey = (int32) floor(*miny * sy + 0.5); + + ptrotate(&nex, &ney, midx, midy, rot); + ptrotate(&sex, &sey, midx, midy, rot); + ptrotate(&swx, &swy, midx, midy, rot); + ptrotate(&nwx, &nwy, midx, midy, rot); + + nex += tx; + sex += tx; + swx += tx; + nwx += tx; + ney += ty; + sey += ty; + swy += ty; + nwy += ty; + /* now find the actual extents of the bbox */ + temp1 = min(nex, nwx); + temp2 = min(swx, sex); + *minx = min(temp1, temp2); + + temp1 = min(ney, nwy); + temp2 = min(swy, sey); + *miny = min(temp1, temp2); + + temp1 = max(nex, nwx); + temp2 = max(swx, sex); + *maxx = max(temp1, temp2); + + temp1 = max(ney, nwy); + temp2 = max(swy, sey); + *maxy = max(temp1, temp2); +} + + +/*-----------------------------------------------*/ +/* + * find the bounding box of the list of primitives and/or sub-figures in this Item + */ + +static void +findBBox(blot, mnx, mxx, mny, mxy) + Item *blot; + int32 *mnx, *mxx, *mny, *mxy; +{ + Item *pi; + ScaledPts bmnx, bmxx, bmny, bmxy, midx, midy; /* bbox [min/max][x/y] */ + ScaledPts tmnx, tmxx, tmny, tmxy; /* temporary, in case of recursion */ + ScaledPts null1, null2, old1, old2; + double prescale, postscale; + + bmnx = TWO24; + bmny = TWO24; + bmxx = -TWO24; + bmxy = -TWO24; + if (blot->kind == Afigure) + { /* afigure */ + pi = blot->UU.U8.body->things; + while (pi != NULL) + { + /* find the current bbox of the list of items here */ + if (pi->kind == Afigure) + { /* recur */ + findBBox(pi, &tmnx, &tmxx, &tmny, &tmxy); + bmnx = min(bmnx, tmnx); + bmny = min(bmny, tmny); + bmxx = max(bmxx, tmxx); + bmxy = max(bmxy, tmxy); + } + else + { + bmnx = min(bmnx, pi->BBlx); + bmny = min(bmny, pi->BBby); + bmxx = max(bmxx, pi->BBrx); + bmxy = max(bmxy, pi->BBty); + } + pi = pi->nextitem; + } /* while */ + /* now transform the items inside, AND the bbox */ + pi = blot->UU.U8.body->things; + midx = (bmnx + bmxx) / 2; + midy = (bmny + bmxy) / 2; + /* now take care of any pre and post size requirements */ + /* see also the "figurehandle" proc. */ + /* #### Keep this scaling biz here, too, for now. May blast it later */ + if (blot->UU.U8.preWid != 0 && blot->UU.U8.preHt != 0) + { + prescale = scalefitfactor(bmxx - bmnx, bmxy - bmny, blot->UU.U8.preWid, + blot->UU.U8.preHt); + blot->UU.U8.fsx *= prescale; + blot->UU.U8.fsy *= prescale; + } + if (blot->UU.U8.postWid != 0 && blot->UU.U8.postHt != 0) + { /* with */ + postscale = scalefitfactor(bmxx - bmnx, bmxy - bmny, + blot->UU.U8.postWid, blot->UU.U8.postHt); + blot->UU.U8.fsx *= postscale; + blot->UU.U8.fsy *= postscale; + } + + /* the actual scale-up is taken care of later in this proc. */ + while (pi != NULL) + { + switch (pi->kind) + { /* with */ + + case Aline: + xfmlinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2, + &pi->UU.U1.ly2, 0, 0, midx, midy, 1.0, + blot->UU.U8.figtheta, blot->UU.U8.fdx, blot->UU.U8.fdy, + blot->UU.U8.fsx, blot->UU.U8.fsy); + break; + + case Aspline: + xfmcontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, 0, 0, midx, midy, + 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx, + blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy); + break; + + case Attspline: + xfmcontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, 0, 0, midx, midy, + 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx, + blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy); + break; + + case Aarc: + null1 = 0; + null2 = 0; + old1 = pi->UU.U6.acentx; + old2 = pi->UU.U6.acenty; + xfmlinepts(&pi->UU.U6.acentx, &pi->UU.U6.acenty, &null1, &null2, 0, + 0, midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx, + blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy); + xfmcontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, 0, 0, old1, + old2, 1.0, blot->UU.U8.figtheta, + blot->UU.U8.fdx + pi->UU.U6.acentx - old1, + blot->UU.U8.fdy + pi->UU.U6.acenty - old2, blot->UU.U8.fsx, + blot->UU.U8.fsy); + break; + + case Alabel: + null1 = 0; + null2 = 0; + xfmlinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, 0, 0, + midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx, + blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy); + break; + + case Abeam: /* not transformable */ + break; + + case Atieslur: /* not transformable */ + break; + + case Afigure: /* do not need to re-transform */ + break; + } /* case */ + pi = pi->nextitem; + } /* while */ + /* transform the bbox, and re-find the new bbox */ + newbbox(&bmnx, &bmxx, &bmny, &bmxy, midx, midy, blot->UU.U8.fsx, + blot->UU.U8.fsy, blot->UU.U8.figtheta, blot->UU.U8.fdx, + blot->UU.U8.fdy); + *mnx = bmnx; + *mny = bmny; + *mxx = bmxx; + *mxy = bmxy; + return; + } /* if */ + *mnx = blot->BBlx; + *mny = blot->BBby; + *mxx = blot->BBrx; + *mxy = blot->BBty; + + /* some other primitive */ + /* else */ +} /* findBBox */ + + +/*---------------------------------------------------------*/ +/* + * traverse the list, determining the current bounding box for the items. We need this to find the mid-point for doing any + * remaining rotations + */ +static void +traverse(thefig, theitem) + Item *thefig, *theitem; +{ + ScaledPts minx, maxx, miny, maxy, curminx, curmaxx, curminy, curmaxy; + + minx = TWO24; + maxx = -TWO24; + miny = TWO24; + maxy = -TWO24; + + while (theitem != NULL) + { /* set the bounding box for this upper-level symbol defn */ + if (theitem->kind == Afigure) + { /* recur */ + findBBox(theitem, &curminx, &curmaxx, &curminy, &curmaxy); + theitem->BBlx = curminx; + theitem->BBby = curminy; + theitem->BBrx = curmaxx; + theitem->BBty = curmaxy; + /* + * reset the symbol's parameters since all the primitives in it have now been transformed according to + * the previous specifications + */ + theitem->UU.U8.figtheta = 0.0; + theitem->UU.U8.fsx = 1.0; + theitem->UU.U8.fsy = 1.0; + theitem->UU.U8.fdx = 0; + theitem->UU.U8.fdy = 0; + theitem->UU.U8.preWid = 0; + theitem->UU.U8.preHt = 0; + theitem->UU.U8.postWid = 0; + theitem->UU.U8.postHt = 0; /* with */ + minx = min(minx, curminx); + miny = min(miny, curminy); + maxx = max(maxx, curmaxx); + maxy = max(maxy, curmaxy); + } /* if a figure/symbol */ + else + { /* a primitive */ + minx = min(minx, theitem->BBlx); + miny = min(miny, theitem->BBby); + maxx = max(maxx, theitem->BBrx); + maxy = max(maxy, theitem->BBty); /* with */ + } /* else */ + theitem = theitem->nextitem; + } /* while */ + + thefig->BBlx = minx; + thefig->BBby = miny; + thefig->BBrx = maxx; + thefig->BBty = maxy; /* with */ +} /* traverse */ + + +#define DoItNow (-1) +#define NoScale 1 + + +/* ----- Figure symbols ----- */ +/*---------------------------------------------------*/ +void +figurehandle(globalsymlist, symbollist, dopush) + Item *globalsymlist, *symbollist; + int32 dopush; +{ + Item *pi, *curfig; + ScaledPts midx, midy, null1, null2, tmnx, tmny, tmxx, tmxy; + double prescale, postscale; + + /* + * PUSH. traverse the lists (recursively if necessary) and compute the transformed points. Convert to 4th quadrant and + * offset by H & V. We can do this destructively here since we're going to output them right away anyhow. Then call + * each respective primitive handler with a level of -1 to indicate to do its job immediately. POP. + */ + curfig = symbollist; + pi = curfig->UU.U8.body->things; + /* + * find and set the bounding box for the figure's sub-symbols and primitives + */ + if (dopush > 0) + traverse(curfig, pi); + + /* + * We eventually transform the items to 4th Quadrant DVI space and output them! + */ + + pi = curfig->UU.U8.body->things; + + midy = (globalsymlist->BBby + globalsymlist->BBty) / 2; + midx = (globalsymlist->BBlx + globalsymlist->BBrx) / 2; + + if (dopush > 0) + { /* the top-level figure for outputting */ + /* + * convert the bounding box because we are about to enter into DVI space, and all calls to handlers hereafter + * are in terms of DVI coordinates + */ + + + /* + * Since there were external specifications about this figure, fit the current figure's actual size to the + * "pre" size (specified by W marker) and/or to the "post" size (specified by the F marker). We do this by + * simple scaling, *without* changing the midpoint of the bounding box, just its extents + */ + if (globalsymlist->UU.U8.preWid != 0 && globalsymlist->UU.U8.preHt != 0) + { + prescale = scalefitfactor(globalsymlist->BBrx - globalsymlist->BBlx, + globalsymlist->BBty - globalsymlist->BBby, + globalsymlist->UU.U8.preWid, globalsymlist->UU.U8.preHt); + globalsymlist->UU.U8.fsx *= prescale; + globalsymlist->UU.U8.fsy *= prescale; + } + if (globalsymlist->UU.U8.postWid != 0 && globalsymlist->UU.U8.postHt != 0) + { + postscale = scalefitfactor(globalsymlist->BBrx - globalsymlist->BBlx, + globalsymlist->BBty - globalsymlist->BBby, + globalsymlist->UU.U8.postWid, globalsymlist->UU.U8.postHt); + globalsymlist->UU.U8.fsx *= postscale; + globalsymlist->UU.U8.fsy *= postscale; + } + tmnx = globalsymlist->BBlx; + tmny = globalsymlist->BBby; + tmxx = globalsymlist->BBrx; + tmxy = globalsymlist->BBty; + xfmlinepts(&tmnx, &tmny, &tmxx, &tmxy, 0, 0, midx, midy, 1.0, 0.0, 0, + 0, globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy); + + toplevelxfm(globalsymlist, globalsymlist, 0); + + dviBBlx = tmnx; + dviBBrx = tmxx; + dviBBby = tmny; + dviBBty = tmxy; + + xfmlinepts(&dviBBlx, &dviBBby, &dviBBrx, &dviBBty, 0, 0, midx, midy, + 1.0, 0.0, globalsymlist->BBlx - tmnx, + globalsymlist->BBby - tmny, 1.0, 1.0); + + globalsymlist->UU.U8.fdx += globalsymlist->BBlx - tmnx; + globalsymlist->UU.U8.fdy += globalsymlist->BBby - tmny; + + dvilinepts(&dviBBlx, &dviBBby, &dviBBrx, &dviBBty, h, v); + pgfigurenum++; + + /* We are ready to output the figure to the page */ + fprintf(logfile, "\nFigure #%ld on page %ld is approx. ", + pgfigurenum, currpagenum); + /* + * write(logfile,((globalsymlist^.BBty - globalsymlist^.BBby) div SPPERPT):0,' pts high and '); + * writeln(logfile,((globalsymlist^.BBrx - globalsymlist^.BBlx) div SPPERPT):0,' pts wide (actual size)'); + */ + fprintf(logfile, "%ld pts high and ", (tmxy - tmny) / SPPERPT); + fprintf(logfile, "%ld pts wide (actual size)\n", (tmxx - tmnx) / SPPERPT); + IPUSH(); + + } + + + while (pi != NULL) + { + switch (pi->kind) + { /* with */ + + case Aline: + dvilinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2, + &pi->UU.U1.ly2, h, v); + /* DVI h and v posit */ + linehandle((int32) DoItNow, (double) NoScale, pi->UU.U1.lx1, pi->UU.U1.ly1, + pi->UU.U1.lx2, pi->UU.U1.ly2, 0, 0, pi->itemthick, + (VectKind) pi->itemvec, (LineStyle) pi->itempatt, dviBBlx, + dviBBrx, dviBBby, dviBBty, globalsymlist->UU.U8.fdx, + -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx, + globalsymlist->UU.U8.fsy, -globalsymlist->UU.U8.figtheta); + /* + * p2c: x.p, line 4681: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] + */ + break; + /* Aline */ + + case Aspline: + dvicontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, h, v); + splinehandle((int32) DoItNow, (double) NoScale, + (SplineKind) pi->UU.U2.spltype, pi->UU.U2.sclosed, + pi->UU.U2.dosmarks, pi->UU.U2.spts, pi->UU.U2.nsplknots, + 0, 0, pi->itemthick, (VectKind) pi->itemvec, + (LineStyle) pi->itempatt, dviBBlx, dviBBrx, dviBBby, + dviBBty, globalsymlist->UU.U8.fdx, + -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx, + globalsymlist->UU.U8.fsy, -globalsymlist->UU.U8.figtheta); + /* + * p2c: x.p, line 4693: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] + */ + break; + /* Aspline */ + + case Attspline: + dvicontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, h, v); + ttsplhandle((int32) DoItNow, (double) NoScale, + (SplineKind) pi->UU.U3.tspltype, pi->UU.U3.tclosed, + pi->UU.U3.dottmarks, pi->UU.U3.ttpts, pi->UU.U3.ttarry, + pi->UU.U3.nttknots, 0, 0, (VectKind) pi->itemvec, + (LineStyle) pi->itempatt, dviBBlx, dviBBrx, dviBBby, dviBBty, + globalsymlist->UU.U8.fdx, -globalsymlist->UU.U8.fdy, + globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy, + -globalsymlist->UU.U8.figtheta); + /* + * p2c: x.p, line 4705: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] + */ + break; + /* Attspline */ + + case Abeam: + dvilinepts(&pi->UU.U4.bx1, &pi->UU.U4.by1, &pi->UU.U4.bx2, + &pi->UU.U4.by2, h, v); + beamhandle((int32) DoItNow, pi->UU.U4.staf, (BeamKind) pi->UU.U4.bkind, + pi->UU.U4.bx1, pi->UU.U4.by1, pi->UU.U4.bx2, pi->UU.U4.by2); + break; + /* Abeam */ + + case Atieslur: + dvicontpts(pi->UU.U5.tspts, pi->UU.U5.ntknots, h, v); + tieslurhandle((int32) DoItNow, pi->UU.U5.tspts, pi->UU.U5.ntknots, + pi->UU.U5.minth, pi->UU.U5.maxth); + break; + /* a tie or slur */ + + case Aarc: + dvicontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, h, v); + arccirclehandle((int32) DoItNow, (double) NoScale, pi->UU.U6.acentx, + pi->UU.U6.acenty, pi->UU.U6.aradius, pi->UU.U6.firstang, + pi->UU.U6.lastang, pi->UU.U6.arcpts, + pi->UU.U6.narcknots, 0, 0, pi->itemthick, + (VectKind) pi->itemvec, (LineStyle) pi->itempatt, dviBBlx, + dviBBrx, dviBBby, dviBBty, globalsymlist->UU.U8.fdx, + -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx, + globalsymlist->UU.U8.fsy, + -globalsymlist->UU.U8.figtheta); + /* + * p2c: x.p, line 4729: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] + */ + break; + /* arc */ + + case Alabel: + null1 = 0; + null2 = 0; + dvilinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, h, v); + labelhandle((int32) DoItNow, (double) NoScale, pi->UU.U7.labx, + pi->UU.U7.laby, 0, 0, pi->UU.U7.fontstyle, + pi->UU.U7.labeltext, globalsymlist->UU.U8.fdx, + -globalsymlist->UU.U8.fdy); + break; + /* label */ + + case Afigure: /* recur */ + figurehandle(globalsymlist, pi, 0); + break; + /* another symbol */ + + } /* case */ + /* + * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] + */ + /* + * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] + */ + /* + * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] + */ + /* + * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267] + */ + pi = pi->nextitem; + } /* while */ + if (dopush > 0) + IPOP(); +} /* figurehandle */ + +#undef DoItNow +#undef NoScale diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec1.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec1.300pk Binary files differnew file mode 100644 index 0000000000..3c39da6f29 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec1.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec1.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec1.tfm Binary files differnew file mode 100644 index 0000000000..f15f24f7cd --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec1.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec10.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec10.300pk Binary files differnew file mode 100644 index 0000000000..9a1090b1bf --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec10.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec10.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec10.tfm Binary files differnew file mode 100644 index 0000000000..bc11ebb747 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec10.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec11.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec11.300pk Binary files differnew file mode 100644 index 0000000000..9a1090b1bf --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec11.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec11.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec11.tfm Binary files differnew file mode 100644 index 0000000000..7424d046f7 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec11.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec12.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec12.300pk Binary files differnew file mode 100644 index 0000000000..23bf540c9a --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec12.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec12.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec12.tfm Binary files differnew file mode 100644 index 0000000000..3572250795 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec12.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec2.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec2.300pk Binary files differnew file mode 100644 index 0000000000..8f7709b577 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec2.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec2.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec2.tfm Binary files differnew file mode 100644 index 0000000000..481df4a70c --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec2.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec3.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec3.300pk Binary files differnew file mode 100644 index 0000000000..8f7709b577 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec3.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec3.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec3.tfm Binary files differnew file mode 100644 index 0000000000..da3837af01 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec3.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec4.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec4.300pk Binary files differnew file mode 100644 index 0000000000..e03445d945 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec4.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec4.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec4.tfm Binary files differnew file mode 100644 index 0000000000..2605898dab --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec4.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec5.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec5.300pk Binary files differnew file mode 100644 index 0000000000..e03445d945 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec5.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec5.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec5.tfm Binary files differnew file mode 100644 index 0000000000..4b28abc081 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec5.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec6.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec6.300pk Binary files differnew file mode 100644 index 0000000000..d42181435b --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec6.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec6.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec6.tfm Binary files differnew file mode 100644 index 0000000000..b6075890fe --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec6.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec7.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec7.300pk Binary files differnew file mode 100644 index 0000000000..d42181435b --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec7.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec7.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec7.tfm Binary files differnew file mode 100644 index 0000000000..66ac443f72 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec7.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec8.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec8.300pk Binary files differnew file mode 100644 index 0000000000..a8447035b4 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec8.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec8.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec8.tfm Binary files differnew file mode 100644 index 0000000000..499ec767a7 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec8.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec9.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec9.300pk Binary files differnew file mode 100644 index 0000000000..a8447035b4 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec9.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec9.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec9.tfm Binary files differnew file mode 100644 index 0000000000..1bc6bd0a52 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/cvec9.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec1.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec1.300pk Binary files differnew file mode 100644 index 0000000000..3c39da6f29 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec1.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec1.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec1.tfm Binary files differnew file mode 100644 index 0000000000..f15f24f7cd --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec1.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec10.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec10.300pk Binary files differnew file mode 100644 index 0000000000..45674bbc05 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec10.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec10.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec10.tfm Binary files differnew file mode 100644 index 0000000000..7d795db2fe --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec10.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec11.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec11.300pk Binary files differnew file mode 100644 index 0000000000..45674bbc05 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec11.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec11.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec11.tfm Binary files differnew file mode 100644 index 0000000000..21dacc2855 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec11.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec12.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec12.300pk Binary files differnew file mode 100644 index 0000000000..e15485356e --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec12.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec12.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec12.tfm Binary files differnew file mode 100644 index 0000000000..ef0926a826 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec12.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec2.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec2.300pk Binary files differnew file mode 100644 index 0000000000..994a8e36aa --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec2.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec2.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec2.tfm Binary files differnew file mode 100644 index 0000000000..377b92782b --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec2.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec3.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec3.300pk Binary files differnew file mode 100644 index 0000000000..994a8e36aa --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec3.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec3.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec3.tfm Binary files differnew file mode 100644 index 0000000000..0a482b0d51 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec3.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec4.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec4.300pk Binary files differnew file mode 100644 index 0000000000..8dad1e314a --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec4.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec4.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec4.tfm Binary files differnew file mode 100644 index 0000000000..8d0dddacd3 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec4.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec5.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec5.300pk Binary files differnew file mode 100644 index 0000000000..8dad1e314a --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec5.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec5.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec5.tfm Binary files differnew file mode 100644 index 0000000000..08164eb704 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec5.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec6.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec6.300pk Binary files differnew file mode 100644 index 0000000000..4fc472f53c --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec6.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec6.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec6.tfm Binary files differnew file mode 100644 index 0000000000..bbcde71122 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec6.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec7.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec7.300pk Binary files differnew file mode 100644 index 0000000000..4fc472f53c --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec7.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec7.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec7.tfm Binary files differnew file mode 100644 index 0000000000..22ed363a84 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec7.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec8.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec8.300pk Binary files differnew file mode 100644 index 0000000000..e23662dd66 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec8.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec8.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec8.tfm Binary files differnew file mode 100644 index 0000000000..080ebcd67b --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec8.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec9.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec9.300pk Binary files differnew file mode 100644 index 0000000000..e23662dd66 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec9.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec9.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec9.tfm Binary files differnew file mode 100644 index 0000000000..d1b7993f3d --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/hvec9.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/mf/README b/macros/latex209/contrib/textyl/vecfonts/mf/README new file mode 100644 index 0000000000..7ee6c2e5da --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/mf/README @@ -0,0 +1,9 @@ +vecbase.mf is the original MF79 source. + +vecbase2.mf is the MF84 source provided by a kind reader of the TeX +newsgroup. The .bat files are for an Amiga ST. I have written a simple +Unix sh script that creates wrapper jobs for all 36 vector fonts. If +you are using a backend like dvips, all you have to do is put these MF +wrappers and vecbase2.mf where MF can find them and the backend will +fire up MF to create the fonts as needed. Of course you also need to +install the tfm files in ../ where TeX can find them. diff --git a/macros/latex209/contrib/textyl/vecfonts/mf/makevec.bat b/macros/latex209/contrib/textyl/vecfonts/mf/makevec.bat new file mode 100644 index 0000000000..d0b771305e --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/mf/makevec.bat @@ -0,0 +1,5 @@ +#------- File "makevec.bat" -------------------------------------------- +#------- The 36 TeXtyl fonts are created by the command 'makevec'. ---- +echo on +for %%w in ( 1 2 3 4 5 6 7 8 9 10 11 12 ) do c:\bat\makevec2.bat %%w +#------- End of "makevec.bat" ------------------------------------------ diff --git a/macros/latex209/contrib/textyl/vecfonts/mf/makevec2.bat b/macros/latex209/contrib/textyl/vecfonts/mf/makevec2.bat new file mode 100644 index 0000000000..deb5a7aca7 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/mf/makevec2.bat @@ -0,0 +1,13 @@ +#------- File "makevec2.bat", used in the above, ----------------------- +#------- (for lack of decent loops only). ------------------------------ +c: +cd c:\vec\pxl1200 +e: +cd e:\mf +mmf \relax;input modes;mode := epson;w0 := %1; w1 := %1;input vecbase2;end +gftopk e:modes.240 c:cvec%1 +mmf \relax;input modes;mode := epson;w0 := 1; w1 := %1;input vecbase2;end +gftopk e:modes.240 c:vvec%1 +mmf \relax;input modes;mode := epson;w0 := %1; w1 := 1;input vecbase2;end +gftopk e:modes.240 c:hvec%1 +#------- End of "makevec2.bat" ------------------------------------------ diff --git a/macros/latex209/contrib/textyl/vecfonts/mf/makewrappers.sh b/macros/latex209/contrib/textyl/vecfonts/mf/makewrappers.sh new file mode 100644 index 0000000000..58bd8dad84 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/mf/makewrappers.sh @@ -0,0 +1,7 @@ +#!/bin/sh +for i in 1 2 3 4 5 6 7 8 9 10 11 12 +do + echo "w0=$i; w1=$i; input vecbase2; end" > cvec$i.mf + echo "w0=1; w1=$i; input vecbase2; end" > vvec$i.mf + echo "w0=$i; w1=1; input vecbase2; end" > hvec$i.mf +done diff --git a/macros/latex209/contrib/textyl/vecfonts/mf/vecbase.mf b/macros/latex209/contrib/textyl/vecfonts/mf/vecbase.mf new file mode 100644 index 0000000000..7d8fffc353 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/mf/vecbase.mf @@ -0,0 +1,1151 @@ +% Vector font base +% Copyright (c) 1984,1985,1986, 1987 John S. Renner +% All rights reserved. +% +% +% +% the following variables must be defined +% before inputting this file +% mode (the resolution:: e.g., islaprinter or isxerox, etc.) +% w0 (the width of the pen in "vec units") +% w1 (the height of the pen in "vec units") +% (note that w0 == w1 for a circular pen) +% the type of pen to use (cpen, vpen, hpen) +% +pxlmode; tfmmode; fntmode; +islaprinter = 100; % just names +isxerox = 2700; +issun = 500; + +if mode = islaprinter: + mag = 0.66; %for DEC LA100 printer +else: if mode = isxerox: + mag = 1.5; %for Xerox X2700 +else: if mode = issun: + mag = .59; +fi; fi; fi; + + +ptsperinch=72.27; +spperinch=(65536.ptsperinch); +pixperinch=(200.mag); +pixpersp = (pixperinch / spperinch); +vecunit = 1; % just a name +vecmeasure = 16384; % in scaled points 2^14 sp +ptsperpixel = (ptsperinch / pixperinch); +pixpervecunit = pixpersp.vecmeasure; +ptspervecunit = ptsperpixel.pixpervecunit; + +hresolution pixperinch; +vresolution pixperinch; + +% +% we allow only Odd sized diameters for vector pens +% to avoid the off-by-one-half-pixel errors +% + +tempa = w1.pixpervecunit; % go from the user-specification +if tempa < 1 : % of pen size, to pixels + new w1; w1 = 1; % taking care of underflow +else: + new w1; w1 = 2*(round ((tempa - 1)/2)) + 1; +fi; + +tempb = w0.pixpervecunit; +if tempb < 1 : + new w0; w0 = 1; +else: + new w0; w0 = 2*(round ((tempb - 1)/2)) + 1; +fi; + +% pre-calculate some TeX information so that we can +% adjust it if necessary + +ds = ((16 vecunit).ptspervecunit); %the design size in points +if ds < 1.0 : + new ds; ds = 1.0; +fi; + +%-----------------Tex information--------------------- +% w0 is horizontal width +% w1 is vertical height + +magnification mag; +designsize ds; +fontidentifier "GRAPHIC-VECTORS"; +codingscheme "ASCII"; +maxht ((w1/2) + 16.vecunit.pixpervecunit); %in pixels I think + +texinfo 0, % -- but we'll use it for our own use + 0, % --and interpret them in our own way +(w0.ptsperpixel), % W0 the horizontal width +(w1.ptsperpixel), % W1 the vertical width +(16.vecunit.ptspervecunit), % Maxvectorlength +(16.vecunit.ptspervecunit), % " + 0; % empty + + +% +% set the pen dimensions +% +eqtrace; +vpenht = round (w1); +hpenwd = round (w0); +if w1 > w0 : % probably a vpen + w8 = w1; +else: %probably a hpen + w8 = w0; +fi; +no eqtrace; + + +no penreset; % VERY IMPORTANT +no pagewarning; + + + +subroutine vect (var dx) + (var dy): +x0 = 0; +y0 = 0; +if dx > 0 : + x1 = (dx.pixpervecunit) + 1; % what's an extra pixel among friends? +else: + x1 = (dx.pixpervecunit); +fi; + +if dy > 0 : + y1 = (dy.pixpervecunit) + 1; +else: if dy = 0 : + y1 = (dy.pixpervecunit) + 0; +else : if dy < 0 : + y1 = (dy.pixpervecunit) - 1; +fi; fi; fi; + +w8 draw 0..1. + + + +charcode 0; +charht (( 15.9688.vecunit).ptspervecunit); +chardp 0; +charwd (( 0.9981.vecunit).ptspervecunit); +call vect ( 0.9981, 15.9688). + + + +charcode 1; +charht (( 15.8764.vecunit).ptspervecunit); +chardp 0; +charwd (( 1.9846.vecunit).ptspervecunit); +call vect ( 1.9846, 15.8764). + + + +charcode 2; +charht (( 15.7260.vecunit).ptspervecunit); +chardp 0; +charwd (( 2.9486.vecunit).ptspervecunit); +call vect ( 2.9486, 15.7260). + + + +charcode 3; +charht (( 15.5223.vecunit).ptspervecunit); +chardp 0; +charwd (( 3.8806.vecunit).ptspervecunit); +call vect ( 3.8806, 15.5223). + + + +charcode 4; +charht (( 15.2717.vecunit).ptspervecunit); +chardp 0; +charwd (( 4.7724.vecunit).ptspervecunit); +call vect ( 4.7724, 15.2717). + + + +charcode 5; +charht (( 14.9813.vecunit).ptspervecunit); +chardp 0; +charwd (( 5.6180.vecunit).ptspervecunit); +call vect ( 5.6180, 14.9813). + + + +charcode 6; +charht (( 14.6585.vecunit).ptspervecunit); +chardp 0; +charwd (( 6.4131.vecunit).ptspervecunit); +call vect ( 6.4131, 14.6585). + + + +charcode 7; +charht (( 14.3108.vecunit).ptspervecunit); +chardp 0; +charwd (( 7.1554.vecunit).ptspervecunit); +call vect ( 7.1554, 14.3108). + + + +charcode 8; +charht (( 13.9452.vecunit).ptspervecunit); +chardp 0; +charwd (( 7.8442.vecunit).ptspervecunit); +call vect ( 7.8442, 13.9452). + + + +charcode 9; +charht (( 13.5680.vecunit).ptspervecunit); +chardp 0; +charwd (( 8.4800.vecunit).ptspervecunit); +call vect ( 8.4800, 13.5680). + + + +charcode 10; +charht (( 13.1847.vecunit).ptspervecunit); +chardp 0; +charwd (( 9.0645.vecunit).ptspervecunit); +call vect ( 9.0645, 13.1847). + + + +charcode 11; +charht (( 12.8000.vecunit).ptspervecunit); +chardp 0; +charwd (( 9.6000.vecunit).ptspervecunit); +call vect ( 9.6000, 12.8000). + + + +charcode 12; +charht (( 12.4178.vecunit).ptspervecunit); +chardp 0; +charwd (( 10.0895.vecunit).ptspervecunit); +call vect ( 10.0895, 12.4178). + + + +charcode 13; +charht (( 12.0412.vecunit).ptspervecunit); +chardp 0; +charwd (( 10.5361.vecunit).ptspervecunit); +call vect ( 10.5361, 12.0412). + + + +charcode 14; +charht (( 11.6726.vecunit).ptspervecunit); +chardp 0; +charwd (( 10.9431.vecunit).ptspervecunit); +call vect ( 10.9431, 11.6726). + + + +charcode 15; +charht (( 11.3137.vecunit).ptspervecunit); +chardp 0; +charwd (( 11.3137.vecunit).ptspervecunit); +call vect ( 11.3137, 11.3137). + + + +charcode 16; +charht (( 10.9431.vecunit).ptspervecunit); +chardp 0; +charwd (( 11.6726.vecunit).ptspervecunit); +call vect ( 11.6726, 10.9431). + + + +charcode 17; +charht (( 10.5361.vecunit).ptspervecunit); +chardp 0; +charwd (( 12.0412.vecunit).ptspervecunit); +call vect ( 12.0412, 10.5361). + + + +charcode 18; +charht (( 10.0895.vecunit).ptspervecunit); +chardp 0; +charwd (( 12.4178.vecunit).ptspervecunit); +call vect ( 12.4178, 10.0895). + + + +charcode 19; +charht (( 9.6000.vecunit).ptspervecunit); +chardp 0; +charwd (( 12.8000.vecunit).ptspervecunit); +call vect ( 12.8000, 9.6000). + + + +charcode 20; +charht (( 9.0645.vecunit).ptspervecunit); +chardp 0; +charwd (( 13.1847.vecunit).ptspervecunit); +call vect ( 13.1847, 9.0645). + + + +charcode 21; +charht (( 8.4800.vecunit).ptspervecunit); +chardp 0; +charwd (( 13.5680.vecunit).ptspervecunit); +call vect ( 13.5680, 8.4800). + + + +charcode 22; +charht (( 7.8442.vecunit).ptspervecunit); +chardp 0; +charwd (( 13.9452.vecunit).ptspervecunit); +call vect ( 13.9452, 7.8442). + + + +charcode 23; +charht (( 7.1554.vecunit).ptspervecunit); +chardp 0; +charwd (( 14.3108.vecunit).ptspervecunit); +call vect ( 14.3108, 7.1554). + + + +charcode 24; +charht (( 6.4131.vecunit).ptspervecunit); +chardp 0; +charwd (( 14.6585.vecunit).ptspervecunit); +call vect ( 14.6585, 6.4131). + + + +charcode 25; +charht (( 5.6180.vecunit).ptspervecunit); +chardp 0; +charwd (( 14.9813.vecunit).ptspervecunit); +call vect ( 14.9813, 5.6180). + + + +charcode 26; +charht (( 4.7724.vecunit).ptspervecunit); +chardp 0; +charwd (( 15.2717.vecunit).ptspervecunit); +call vect ( 15.2717, 4.7724). + + + +charcode 27; +charht (( 3.8806.vecunit).ptspervecunit); +chardp 0; +charwd (( 15.5223.vecunit).ptspervecunit); +call vect ( 15.5223, 3.8806). + + + +charcode 28; +charht (( 2.9486.vecunit).ptspervecunit); +chardp 0; +charwd (( 15.7260.vecunit).ptspervecunit); +call vect ( 15.7260, 2.9486). + + + +charcode 29; +charht (( 1.9846.vecunit).ptspervecunit); +chardp 0; +charwd (( 15.8764.vecunit).ptspervecunit); +call vect ( 15.8764, 1.9846). + + + +charcode 30; +charht (( 0.9981.vecunit).ptspervecunit); +chardp 0; +charwd (( 15.9688.vecunit).ptspervecunit); +call vect ( 15.9688, 0.9981). + + + +charcode 31; +charht (( 0.0000.vecunit).ptspervecunit); +chardp 0; +charwd (( 16.0000.vecunit).ptspervecunit); +call vect ( 16.0000, 0.0000). + + + +charcode 32; +charht 0; +chardp (( 0.9981.vecunit).ptspervecunit); +charwd (( 15.9688.vecunit).ptspervecunit); +call vect ( 15.9688, -0.9981). + + + +charcode 33; +charht 0; +chardp (( 1.9846.vecunit).ptspervecunit); +charwd (( 15.8764.vecunit).ptspervecunit); +call vect ( 15.8764, -1.9846). + + + +charcode 34; +charht 0; +chardp (( 2.9486.vecunit).ptspervecunit); +charwd (( 15.7260.vecunit).ptspervecunit); +call vect ( 15.7260, -2.9486). + + + +charcode 35; +charht 0; +chardp (( 3.8806.vecunit).ptspervecunit); +charwd (( 15.5223.vecunit).ptspervecunit); +call vect ( 15.5223, -3.8806). + + + +charcode 36; +charht 0; +chardp (( 4.7724.vecunit).ptspervecunit); +charwd (( 15.2717.vecunit).ptspervecunit); +call vect ( 15.2717, -4.7724). + + + +charcode 37; +charht 0; +chardp (( 5.6180.vecunit).ptspervecunit); +charwd (( 14.9813.vecunit).ptspervecunit); +call vect ( 14.9813, -5.6180). + + + +charcode 38; +charht 0; +chardp (( 6.4131.vecunit).ptspervecunit); +charwd (( 14.6585.vecunit).ptspervecunit); +call vect ( 14.6585, -6.4131). + + + +charcode 39; +charht 0; +chardp (( 7.1554.vecunit).ptspervecunit); +charwd (( 14.3108.vecunit).ptspervecunit); +call vect ( 14.3108, -7.1554). + + + +charcode 40; +charht 0; +chardp (( 7.8442.vecunit).ptspervecunit); +charwd (( 13.9452.vecunit).ptspervecunit); +call vect ( 13.9452, -7.8442). + + + +charcode 41; +charht 0; +chardp (( 8.4800.vecunit).ptspervecunit); +charwd (( 13.5680.vecunit).ptspervecunit); +call vect ( 13.5680, -8.4800). + + + +charcode 42; +charht 0; +chardp (( 9.0645.vecunit).ptspervecunit); +charwd (( 13.1847.vecunit).ptspervecunit); +call vect ( 13.1847, -9.0645). + + + +charcode 43; +charht 0; +chardp (( 9.6000.vecunit).ptspervecunit); +charwd (( 12.8000.vecunit).ptspervecunit); +call vect ( 12.8000, -9.6000). + + + +charcode 44; +charht 0; +chardp (( 10.0895.vecunit).ptspervecunit); +charwd (( 12.4178.vecunit).ptspervecunit); +call vect ( 12.4178, -10.0895). + + + +charcode 45; +charht 0; +chardp (( 10.5361.vecunit).ptspervecunit); +charwd (( 12.0412.vecunit).ptspervecunit); +call vect ( 12.0412, -10.5361). + + + +charcode 46; +charht 0; +chardp (( 10.9431.vecunit).ptspervecunit); +charwd (( 11.6726.vecunit).ptspervecunit); +call vect ( 11.6726, -10.9431). + + + +charcode 47; +charht 0; +chardp (( 11.3137.vecunit).ptspervecunit); +charwd (( 11.3137.vecunit).ptspervecunit); +call vect ( 11.3137, -11.3137). + + + +charcode 48; +charht 0; +chardp (( 11.6726.vecunit).ptspervecunit); +charwd (( 10.9431.vecunit).ptspervecunit); +call vect ( 10.9431, -11.6726). + + + +charcode 49; +charht 0; +chardp (( 12.0412.vecunit).ptspervecunit); +charwd (( 10.5361.vecunit).ptspervecunit); +call vect ( 10.5361, -12.0412). + + + +charcode 50; +charht 0; +chardp (( 12.4178.vecunit).ptspervecunit); +charwd (( 10.0895.vecunit).ptspervecunit); +call vect ( 10.0895, -12.4178). + + + +charcode 51; +charht 0; +chardp (( 12.8000.vecunit).ptspervecunit); +charwd (( 9.6000.vecunit).ptspervecunit); +call vect ( 9.6000, -12.8000). + + + +charcode 52; +charht 0; +chardp (( 13.1847.vecunit).ptspervecunit); +charwd (( 9.0645.vecunit).ptspervecunit); +call vect ( 9.0645, -13.1847). + + + +charcode 53; +charht 0; +chardp (( 13.5680.vecunit).ptspervecunit); +charwd (( 8.4800.vecunit).ptspervecunit); +call vect ( 8.4800, -13.5680). + + + +charcode 54; +charht 0; +chardp (( 13.9452.vecunit).ptspervecunit); +charwd (( 7.8442.vecunit).ptspervecunit); +call vect ( 7.8442, -13.9452). + + + +charcode 55; +charht 0; +chardp (( 14.3108.vecunit).ptspervecunit); +charwd (( 7.1554.vecunit).ptspervecunit); +call vect ( 7.1554, -14.3108). + + + +charcode 56; +charht 0; +chardp (( 14.6585.vecunit).ptspervecunit); +charwd (( 6.4131.vecunit).ptspervecunit); +call vect ( 6.4131, -14.6585). + + + +charcode 57; +charht 0; +chardp (( 14.9813.vecunit).ptspervecunit); +charwd (( 5.6180.vecunit).ptspervecunit); +call vect ( 5.6180, -14.9813). + + + +charcode 58; +charht 0; +chardp (( 15.2717.vecunit).ptspervecunit); +charwd (( 4.7724.vecunit).ptspervecunit); +call vect ( 4.7724, -15.2717). + + + +charcode 59; +charht 0; +chardp (( 15.5223.vecunit).ptspervecunit); +charwd (( 3.8806.vecunit).ptspervecunit); +call vect ( 3.8806, -15.5223). + + + +charcode 60; +charht 0; +chardp (( 15.7260.vecunit).ptspervecunit); +charwd (( 2.9486.vecunit).ptspervecunit); +call vect ( 2.9486, -15.7260). + + + +charcode 61; +charht 0; +chardp (( 15.8764.vecunit).ptspervecunit); +charwd (( 1.9846.vecunit).ptspervecunit); +call vect ( 1.9846, -15.8764). + + + +charcode 62; +charht 0; +chardp (( 15.9688.vecunit).ptspervecunit); +charwd (( 0.9981.vecunit).ptspervecunit); +call vect ( 0.9981, -15.9688). + + + +charcode 63; +charht (( 8.0000.vecunit).ptspervecunit); +chardp 0; +charwd (( -0.0000.vecunit).ptspervecunit); +call vect ( -0.0000, 8.0000). + + + +charcode 64; +charht (( 7.9382.vecunit).ptspervecunit); +chardp 0; +charwd (( 0.9923.vecunit).ptspervecunit); +call vect ( 0.9923, 7.9382). + + + +charcode 65; +charht (( 7.7611.vecunit).ptspervecunit); +chardp 0; +charwd (( 1.9403.vecunit).ptspervecunit); +call vect ( 1.9403, 7.7611). + + + +charcode 66; +charht (( 7.4906.vecunit).ptspervecunit); +chardp 0; +charwd (( 2.8090.vecunit).ptspervecunit); +call vect ( 2.8090, 7.4906). + + + +charcode 67; +charht (( 7.1554.vecunit).ptspervecunit); +chardp 0; +charwd (( 3.5777.vecunit).ptspervecunit); +call vect ( 3.5777, 7.1554). + + + +charcode 68; +charht (( 6.7840.vecunit).ptspervecunit); +chardp 0; +charwd (( 4.2400.vecunit).ptspervecunit); +call vect ( 4.2400, 6.7840). + + + +charcode 69; +charht (( 6.4000.vecunit).ptspervecunit); +chardp 0; +charwd (( 4.8000.vecunit).ptspervecunit); +call vect ( 4.8000, 6.4000). + + + +charcode 70; +charht (( 6.0206.vecunit).ptspervecunit); +chardp 0; +charwd (( 5.2680.vecunit).ptspervecunit); +call vect ( 5.2680, 6.0206). + + + +charcode 71; +charht (( 5.6569.vecunit).ptspervecunit); +chardp 0; +charwd (( 5.6569.vecunit).ptspervecunit); +call vect ( 5.6569, 5.6569). + + + +charcode 72; +charht (( 5.2680.vecunit).ptspervecunit); +chardp 0; +charwd (( 6.0206.vecunit).ptspervecunit); +call vect ( 6.0206, 5.2680). + + + +charcode 73; +charht (( 4.8000.vecunit).ptspervecunit); +chardp 0; +charwd (( 6.4000.vecunit).ptspervecunit); +call vect ( 6.4000, 4.8000). + + + +charcode 74; +charht (( 4.2400.vecunit).ptspervecunit); +chardp 0; +charwd (( 6.7840.vecunit).ptspervecunit); +call vect ( 6.7840, 4.2400). + + + +charcode 75; +charht (( 3.5777.vecunit).ptspervecunit); +chardp 0; +charwd (( 7.1554.vecunit).ptspervecunit); +call vect ( 7.1554, 3.5777). + + + +charcode 76; +charht (( 2.8090.vecunit).ptspervecunit); +chardp 0; +charwd (( 7.4906.vecunit).ptspervecunit); +call vect ( 7.4906, 2.8090). + + + +charcode 77; +charht (( 1.9403.vecunit).ptspervecunit); +chardp 0; +charwd (( 7.7611.vecunit).ptspervecunit); +call vect ( 7.7611, 1.9403). + + + +charcode 78; +charht (( 0.9923.vecunit).ptspervecunit); +chardp 0; +charwd (( 7.9382.vecunit).ptspervecunit); +call vect ( 7.9382, 0.9923). + + + +charcode 79; +charht (( 0.0000.vecunit).ptspervecunit); +chardp 0; +charwd (( 8.0000.vecunit).ptspervecunit); +call vect ( 8.0000, 0.0000). + + + +charcode 80; +charht 0; +chardp (( 0.9923.vecunit).ptspervecunit); +charwd (( 7.9382.vecunit).ptspervecunit); +call vect ( 7.9382, -0.9923). + + + +charcode 81; +charht 0; +chardp (( 1.9403.vecunit).ptspervecunit); +charwd (( 7.7611.vecunit).ptspervecunit); +call vect ( 7.7611, -1.9403). + + + +charcode 82; +charht 0; +chardp (( 2.8090.vecunit).ptspervecunit); +charwd (( 7.4906.vecunit).ptspervecunit); +call vect ( 7.4906, -2.8090). + + + +charcode 83; +charht 0; +chardp (( 3.5777.vecunit).ptspervecunit); +charwd (( 7.1554.vecunit).ptspervecunit); +call vect ( 7.1554, -3.5777). + + + +charcode 84; +charht 0; +chardp (( 4.2400.vecunit).ptspervecunit); +charwd (( 6.7840.vecunit).ptspervecunit); +call vect ( 6.7840, -4.2400). + + + +charcode 85; +charht 0; +chardp (( 4.8000.vecunit).ptspervecunit); +charwd (( 6.4000.vecunit).ptspervecunit); +call vect ( 6.4000, -4.8000). + + + +charcode 86; +charht 0; +chardp (( 5.2680.vecunit).ptspervecunit); +charwd (( 6.0206.vecunit).ptspervecunit); +call vect ( 6.0206, -5.2680). + + + +charcode 87; +charht 0; +chardp (( 5.6569.vecunit).ptspervecunit); +charwd (( 5.6569.vecunit).ptspervecunit); +call vect ( 5.6569, -5.6569). + + + +charcode 88; +charht 0; +chardp (( 6.0206.vecunit).ptspervecunit); +charwd (( 5.2680.vecunit).ptspervecunit); +call vect ( 5.2680, -6.0206). + + + +charcode 89; +charht 0; +chardp (( 6.4000.vecunit).ptspervecunit); +charwd (( 4.8000.vecunit).ptspervecunit); +call vect ( 4.8000, -6.4000). + + + +charcode 90; +charht 0; +chardp (( 6.7840.vecunit).ptspervecunit); +charwd (( 4.2400.vecunit).ptspervecunit); +call vect ( 4.2400, -6.7840). + + + +charcode 91; +charht 0; +chardp (( 7.1554.vecunit).ptspervecunit); +charwd (( 3.5777.vecunit).ptspervecunit); +call vect ( 3.5777, -7.1554). + + + +charcode 92; +charht 0; +chardp (( 7.4906.vecunit).ptspervecunit); +charwd (( 2.8090.vecunit).ptspervecunit); +call vect ( 2.8090, -7.4906). + + + +charcode 93; +charht 0; +chardp (( 7.7611.vecunit).ptspervecunit); +charwd (( 1.9403.vecunit).ptspervecunit); +call vect ( 1.9403, -7.7611). + + + +charcode 94; +charht 0; +chardp (( 7.9382.vecunit).ptspervecunit); +charwd (( 0.9923.vecunit).ptspervecunit); +call vect ( 0.9923, -7.9382). + + + +charcode 95; +charht 0; +chardp (( 8.0000.vecunit).ptspervecunit); +charwd (( -0.0000.vecunit).ptspervecunit); +call vect ( -0.0000, -8.0000). + + + +charcode 96; +charht (( 4.0000.vecunit).ptspervecunit); +chardp 0; +charwd (( -0.0000.vecunit).ptspervecunit); +call vect ( -0.0000, 4.0000). + + + +charcode 97; +charht (( 3.8806.vecunit).ptspervecunit); +chardp 0; +charwd (( 0.9701.vecunit).ptspervecunit); +call vect ( 0.9701, 3.8806). + + + +charcode 98; +charht (( 3.5777.vecunit).ptspervecunit); +chardp 0; +charwd (( 1.7889.vecunit).ptspervecunit); +call vect ( 1.7889, 3.5777). + + + +charcode 99; +charht (( 3.2000.vecunit).ptspervecunit); +chardp 0; +charwd (( 2.4000.vecunit).ptspervecunit); +call vect ( 2.4000, 3.2000). + + + +charcode 100; +charht (( 2.8284.vecunit).ptspervecunit); +chardp 0; +charwd (( 2.8284.vecunit).ptspervecunit); +call vect ( 2.8284, 2.8284). + + + +charcode 101; +charht (( 2.4000.vecunit).ptspervecunit); +chardp 0; +charwd (( 3.2000.vecunit).ptspervecunit); +call vect ( 3.2000, 2.4000). + + + +charcode 102; +charht (( 1.7889.vecunit).ptspervecunit); +chardp 0; +charwd (( 3.5777.vecunit).ptspervecunit); +call vect ( 3.5777, 1.7889). + + + +charcode 103; +charht (( 0.9701.vecunit).ptspervecunit); +chardp 0; +charwd (( 3.8806.vecunit).ptspervecunit); +call vect ( 3.8806, 0.9701). + + + +charcode 104; +charht (( 0.0000.vecunit).ptspervecunit); +chardp 0; +charwd (( 4.0000.vecunit).ptspervecunit); +call vect ( 4.0000, 0.0000). + + + +charcode 105; +charht 0; +chardp (( 0.9701.vecunit).ptspervecunit); +charwd (( 3.8806.vecunit).ptspervecunit); +call vect ( 3.8806, -0.9701). + + + +charcode 106; +charht 0; +chardp (( 1.7889.vecunit).ptspervecunit); +charwd (( 3.5777.vecunit).ptspervecunit); +call vect ( 3.5777, -1.7889). + + + +charcode 107; +charht 0; +chardp (( 2.4000.vecunit).ptspervecunit); +charwd (( 3.2000.vecunit).ptspervecunit); +call vect ( 3.2000, -2.4000). + + + +charcode 108; +charht 0; +chardp (( 2.8284.vecunit).ptspervecunit); +charwd (( 2.8284.vecunit).ptspervecunit); +call vect ( 2.8284, -2.8284). + + + +charcode 109; +charht 0; +chardp (( 3.2000.vecunit).ptspervecunit); +charwd (( 2.4000.vecunit).ptspervecunit); +call vect ( 2.4000, -3.2000). + + + +charcode 110; +charht 0; +chardp (( 3.5777.vecunit).ptspervecunit); +charwd (( 1.7889.vecunit).ptspervecunit); +call vect ( 1.7889, -3.5777). + + + +charcode 111; +charht 0; +chardp (( 3.8806.vecunit).ptspervecunit); +charwd (( 0.9701.vecunit).ptspervecunit); +call vect ( 0.9701, -3.8806). + + + +charcode 112; +charht 0; +chardp (( 4.0000.vecunit).ptspervecunit); +charwd (( -0.0000.vecunit).ptspervecunit); +call vect ( -0.0000, -4.0000). + + + +charcode 113; +charht (( 2.0000.vecunit).ptspervecunit); +chardp 0; +charwd (( -0.0000.vecunit).ptspervecunit); +call vect ( -0.0000, 2.0000). + + + +charcode 114; +charht (( 1.7889.vecunit).ptspervecunit); +chardp 0; +charwd (( 0.8944.vecunit).ptspervecunit); +call vect ( 0.8944, 1.7889). + + + +charcode 115; +charht (( 1.4142.vecunit).ptspervecunit); +chardp 0; +charwd (( 1.4142.vecunit).ptspervecunit); +call vect ( 1.4142, 1.4142). + + + +charcode 116; +charht (( 0.8944.vecunit).ptspervecunit); +chardp 0; +charwd (( 1.7889.vecunit).ptspervecunit); +call vect ( 1.7889, 0.8944). + + + +charcode 117; +charht (( 0.0000.vecunit).ptspervecunit); +chardp 0; +charwd (( 2.0000.vecunit).ptspervecunit); +call vect ( 2.0000, 0.0000). + + + +charcode 118; +charht 0; +chardp (( 0.8944.vecunit).ptspervecunit); +charwd (( 1.7889.vecunit).ptspervecunit); +call vect ( 1.7889, -0.8944). + + + +charcode 119; +charht 0; +chardp (( 1.4142.vecunit).ptspervecunit); +charwd (( 1.4142.vecunit).ptspervecunit); +call vect ( 1.4142, -1.4142). + + + +charcode 120; +charht 0; +chardp (( 1.7889.vecunit).ptspervecunit); +charwd (( 0.8944.vecunit).ptspervecunit); +call vect ( 0.8944, -1.7889). + + + +charcode 121; +charht 0; +chardp (( 2.0000.vecunit).ptspervecunit); +charwd (( -0.0000.vecunit).ptspervecunit); +call vect ( -0.0000, -2.0000). + + + +charcode 122; +charht (( 1.0000.vecunit).ptspervecunit); +chardp 0; +charwd (( -0.0000.vecunit).ptspervecunit); +call vect ( -0.0000, 1.0000). + + + +charcode 123; +charht (( 0.7071.vecunit).ptspervecunit); +chardp 0; +charwd (( 0.7071.vecunit).ptspervecunit); +call vect ( 0.7071, 0.7071). + + + +charcode 124; +charht (( 0.0000.vecunit).ptspervecunit); +chardp 0; +charwd (( 1.0000.vecunit).ptspervecunit); +call vect ( 1.0000, 0.0000). + + + +charcode 125; +charht 0; +chardp (( 0.7071.vecunit).ptspervecunit); +charwd (( 0.7071.vecunit).ptspervecunit); +call vect ( 0.7071, -0.7071). + + + +charcode 126; +charht 0; +chardp (( 1.0000.vecunit).ptspervecunit); +charwd (( -0.0000.vecunit).ptspervecunit); +call vect ( -0.0000, -1.0000). + + + +charcode 127; +charht (( 0.0000.vecunit).ptspervecunit); +chardp 0; +charwd ((1.vecunit).ptspervecunit); +call vect ( 0.0000, 0.0000). + + diff --git a/macros/latex209/contrib/textyl/vecfonts/mf/vecbase2.mf b/macros/latex209/contrib/textyl/vecfonts/mf/vecbase2.mf new file mode 100644 index 0000000000..f67b13b097 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/mf/vecbase2.mf @@ -0,0 +1,176 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% "VECBASE2.MF" Martin Costabel, 1987 +% Translation to METAFONT82 of: +% +% Vector font base ("VECBASE.MF") +% Copyright (c) 1984,1985,1986, 1987 John S. Renner +% All rights reserved. +% +% +% the following variables must be defined +% before inputting this file +% mode (the resolution:: e.g., islaprinter or isxerox, etc.) +% w0 (the width of the pen in "vec units") +% w1 (the height of the pen in "vec units") +% (note that w0 == w1 for a circular pen) +% no longer necessary (M.C.): +% the type of pen to use (cpen, vpen, hpen) + +mode_setup; + +numeric u#; +u# = 1/4pt#; +wx#:=w0*u#; wy#:=w1*u#; define_pixels(wx,wy); +autorounding:=0; +if w0<>w1: pickup pensquare xscaled wx yscaled wy ; + else : pickup pencircle xscaled wx yscaled wy ; fi; +vecpen:=savepen; + +def vecchar(expr code,vx,vy) = + numeric wd#,ht#,dp#,dx#,dy#; + dx# = vx*u#; dy# = vy*u#; + define_good_x_pixels(dx); define_good_y_pixels(dy); + wd# = dx#; + if vy < 0: ht# = 0; dp# = -dy#; + else: ht# = dy#; dp# = 0; fi; + if (vx,vy) = (0,0): wd# := u#; fi; + beginchar(code,wd#,ht#,dp#); + pickup vecpen; + draw (0,0)--(dx,dy); + endchar; +enddef; + +designsize := 16u#; +font_identifier:= "GRAPHIC-VECTORS"; +font_coding_scheme:= "ASCII"; +fontdimen 1 : 0, 0, wx#, wy#, 16u#, 16u#, 0; + +vecchar ( 0, 0.9981, 15.9688); +vecchar ( 1, 1.9846, 15.8764); +vecchar ( 2, 2.9486, 15.7260); +vecchar ( 3, 3.8806, 15.5223); +vecchar ( 4, 4.7724, 15.2717); +vecchar ( 5, 5.6180, 14.9813); +vecchar ( 6, 6.4131, 14.6585); +vecchar ( 7, 7.1554, 14.3108); +vecchar ( 8, 7.8442, 13.9452); +vecchar ( 9, 8.4800, 13.5680); +vecchar ( 10, 9.0645, 13.1847); +vecchar ( 11, 9.6000, 12.8000); +vecchar ( 12, 10.0895, 12.4178); +vecchar ( 13, 10.5361, 12.0412); +vecchar ( 14, 10.9431, 11.6726); +vecchar ( 15, 11.3137, 11.3137); +vecchar ( 16, 11.6726, 10.9431); +vecchar ( 17, 12.0412, 10.5361); +vecchar ( 18, 12.4178, 10.0895); +vecchar ( 19, 12.8000, 9.6000); +vecchar ( 20, 13.1847, 9.0645); +vecchar ( 21, 13.5680, 8.4800); +vecchar ( 22, 13.9452, 7.8442); +vecchar ( 23, 14.3108, 7.1554); +vecchar ( 24, 14.6585, 6.4131); +vecchar ( 25, 14.9813, 5.6180); +vecchar ( 26, 15.2717, 4.7724); +vecchar ( 27, 15.5223, 3.8806); +vecchar ( 28, 15.7260, 2.9486); +vecchar ( 29, 15.8764, 1.9846); +vecchar ( 30, 15.9688, 0.9981); +vecchar ( 31, 16.0000, 0.0000); +vecchar ( 32, 15.9688, -0.9981); +vecchar ( 33, 15.8764, -1.9846); +vecchar ( 34, 15.7260, -2.9486); +vecchar ( 35, 15.5223, -3.8806); +vecchar ( 36, 15.2717, -4.7724); +vecchar ( 37, 14.9813, -5.6180); +vecchar ( 38, 14.6585, -6.4131); +vecchar ( 39, 14.3108, -7.1554); +vecchar ( 40, 13.9452, -7.8442); +vecchar ( 41, 13.5680, -8.4800); +vecchar ( 42, 13.1847, -9.0645); +vecchar ( 43, 12.8000, -9.6000); +vecchar ( 44, 12.4178, -10.0895); +vecchar ( 45, 12.0412, -10.5361); +vecchar ( 46, 11.6726, -10.9431); +vecchar ( 47, 11.3137, -11.3137); +vecchar ( 48, 10.9431, -11.6726); +vecchar ( 49, 10.5361, -12.0412); +vecchar ( 50, 10.0895, -12.4178); +vecchar ( 51, 9.6000, -12.8000); +vecchar ( 52, 9.0645, -13.1847); +vecchar ( 53, 8.4800, -13.5680); +vecchar ( 54, 7.8442, -13.9452); +vecchar ( 55, 7.1554, -14.3108); +vecchar ( 56, 6.4131, -14.6585); +vecchar ( 57, 5.6180, -14.9813); +vecchar ( 58, 4.7724, -15.2717); +vecchar ( 59, 3.8806, -15.5223); +vecchar ( 60, 2.9486, -15.7260); +vecchar ( 61, 1.9846, -15.8764); +vecchar ( 62, 0.9981, -15.9688); +vecchar ( 63, -0.0000, 8.0000); +vecchar ( 64, 0.9923, 7.9382); +vecchar ( 65, 1.9403, 7.7611); +vecchar ( 66, 2.8090, 7.4906); +vecchar ( 67, 3.5777, 7.1554); +vecchar ( 68, 4.2400, 6.7840); +vecchar ( 69, 4.8000, 6.4000); +vecchar ( 70, 5.2680, 6.0206); +vecchar ( 71, 5.6569, 5.6569); +vecchar ( 72, 6.0206, 5.2680); +vecchar ( 73, 6.4000, 4.8000); +vecchar ( 74, 6.7840, 4.2400); +vecchar ( 75, 7.1554, 3.5777); +vecchar ( 76, 7.4906, 2.8090); +vecchar ( 77, 7.7611, 1.9403); +vecchar ( 78, 7.9382, 0.9923); +vecchar ( 79, 8.0000, 0.0000); +vecchar ( 80, 7.9382, -0.9923); +vecchar ( 81, 7.7611, -1.9403); +vecchar ( 82, 7.4906, -2.8090); +vecchar ( 83, 7.1554, -3.5777); +vecchar ( 84, 6.7840, -4.2400); +vecchar ( 85, 6.4000, -4.8000); +vecchar ( 86, 6.0206, -5.2680); +vecchar ( 87, 5.6569, -5.6569); +vecchar ( 88, 5.2680, -6.0206); +vecchar ( 89, 4.8000, -6.4000); +vecchar ( 90, 4.2400, -6.7840); +vecchar ( 91, 3.5777, -7.1554); +vecchar ( 92, 2.8090, -7.4906); +vecchar ( 93, 1.9403, -7.7611); +vecchar ( 94, 0.9923, -7.9382); +vecchar ( 95, -0.0000, -8.0000); +vecchar ( 96, -0.0000, 4.0000); +vecchar ( 97, 0.9701, 3.8806); +vecchar ( 98, 1.7889, 3.5777); +vecchar ( 99, 2.4000, 3.2000); +vecchar ( 100, 2.8284, 2.8284); +vecchar ( 101, 3.2000, 2.4000); +vecchar ( 102, 3.5777, 1.7889); +vecchar ( 103, 3.8806, 0.9701); +vecchar ( 104, 4.0000, 0.0000); +vecchar ( 105, 3.8806, -0.9701); +vecchar ( 106, 3.5777, -1.7889); +vecchar ( 107, 3.2000, -2.4000); +vecchar ( 108, 2.8284, -2.8284); +vecchar ( 109, 2.4000, -3.2000); +vecchar ( 110, 1.7889, -3.5777); +vecchar ( 111, 0.9701, -3.8806); +vecchar ( 112, -0.0000, -4.0000); +vecchar ( 113, -0.0000, 2.0000); +vecchar ( 114, 0.8944, 1.7889); +vecchar ( 115, 1.4142, 1.4142); +vecchar ( 116, 1.7889, 0.8944); +vecchar ( 117, 2.0000, 0.0000); +vecchar ( 118, 1.7889, -0.8944); +vecchar ( 119, 1.4142, -1.4142); +vecchar ( 120, 0.8944, -1.7889); +vecchar ( 121, -0.0000, -2.0000); +vecchar ( 122, -0.0000, 1.0000); +vecchar ( 123, 0.7071, 0.7071); +vecchar ( 124, 1.0000, 0.0000); +vecchar ( 125, 0.7071, -0.7071); +vecchar ( 126, -0.0000, -1.0000); +vecchar ( 127, 0.0000, 0.0000); +%%%%%%%%% End of VECBASE2.MF %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec1.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec1.300pk Binary files differnew file mode 100644 index 0000000000..3c39da6f29 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec1.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec1.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec1.tfm Binary files differnew file mode 100644 index 0000000000..f15f24f7cd --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec1.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec10.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec10.300pk Binary files differnew file mode 100644 index 0000000000..0dc35219a9 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec10.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec10.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec10.tfm Binary files differnew file mode 100644 index 0000000000..fe20e066fe --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec10.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec11.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec11.300pk Binary files differnew file mode 100644 index 0000000000..0dc35219a9 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec11.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec11.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec11.tfm Binary files differnew file mode 100644 index 0000000000..977c161971 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec11.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec12.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec12.300pk Binary files differnew file mode 100644 index 0000000000..c1dbb7cb23 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec12.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec12.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec12.tfm Binary files differnew file mode 100644 index 0000000000..60ebe0f76a --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec12.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec2.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec2.300pk Binary files differnew file mode 100644 index 0000000000..4bccb1940a --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec2.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec2.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec2.tfm Binary files differnew file mode 100644 index 0000000000..536afd6b5a --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec2.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec3.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec3.300pk Binary files differnew file mode 100644 index 0000000000..4bccb1940a --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec3.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec3.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec3.tfm Binary files differnew file mode 100644 index 0000000000..529da7659c --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec3.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec4.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec4.300pk Binary files differnew file mode 100644 index 0000000000..c6cfa9f899 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec4.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec4.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec4.tfm Binary files differnew file mode 100644 index 0000000000..a4d29faf30 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec4.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec5.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec5.300pk Binary files differnew file mode 100644 index 0000000000..c6cfa9f899 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec5.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec5.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec5.tfm Binary files differnew file mode 100644 index 0000000000..8d6e0be6d2 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec5.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec6.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec6.300pk Binary files differnew file mode 100644 index 0000000000..0fcdd5c8de --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec6.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec6.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec6.tfm Binary files differnew file mode 100644 index 0000000000..6bc4c13fb6 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec6.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec7.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec7.300pk Binary files differnew file mode 100644 index 0000000000..0fcdd5c8de --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec7.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec7.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec7.tfm Binary files differnew file mode 100644 index 0000000000..d0a39d4c4d --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec7.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec8.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec8.300pk Binary files differnew file mode 100644 index 0000000000..543bd2c9b7 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec8.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec8.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec8.tfm Binary files differnew file mode 100644 index 0000000000..a503d67168 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec8.tfm diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec9.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec9.300pk Binary files differnew file mode 100644 index 0000000000..543bd2c9b7 --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec9.300pk diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec9.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec9.tfm Binary files differnew file mode 100644 index 0000000000..89aadb973c --- /dev/null +++ b/macros/latex209/contrib/textyl/vecfonts/vvec9.tfm |