summaryrefslogtreecommitdiff
path: root/macros/latex209/contrib/textyl
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex209/contrib/textyl
Initial commit
Diffstat (limited to 'macros/latex209/contrib/textyl')
-rw-r--r--macros/latex209/contrib/textyl/README84
-rw-r--r--macros/latex209/contrib/textyl/README.27aug9129
-rw-r--r--macros/latex209/contrib/textyl/TODO.27aug915
-rw-r--r--macros/latex209/contrib/textyl/doc/textyl.tex42
-rw-r--r--macros/latex209/contrib/textyl/doc/tylman.dvibin0 -> 164556 bytes
-rw-r--r--macros/latex209/contrib/textyl/doc/tylman.tex3144
-rw-r--r--macros/latex209/contrib/textyl/doc/tylout.dvibin0 -> 245944 bytes
-rw-r--r--macros/latex209/contrib/textyl/psrc/h00vars.h252
-rw-r--r--macros/latex209/contrib/textyl/psrc/makefile23
-rw-r--r--macros/latex209/contrib/textyl/psrc/texpaths.h32
-rw-r--r--macros/latex209/contrib/textyl/psrc/textyl.pas7873
-rw-r--r--macros/latex209/contrib/textyl/psrc/textyl.pas.aa1000
-rw-r--r--macros/latex209/contrib/textyl/psrc/textyl.pas.ab1000
-rw-r--r--macros/latex209/contrib/textyl/psrc/textyl.pas.ac1000
-rw-r--r--macros/latex209/contrib/textyl/psrc/textyl.pas.ad1000
-rw-r--r--macros/latex209/contrib/textyl/psrc/textyl.pas.ae1000
-rw-r--r--macros/latex209/contrib/textyl/psrc/textyl.pas.af1000
-rw-r--r--macros/latex209/contrib/textyl/psrc/textyl.pas.ag1000
-rw-r--r--macros/latex209/contrib/textyl/psrc/textyl.pas.ah873
-rw-r--r--macros/latex209/contrib/textyl/psrc/tylext.c138
-rw-r--r--macros/latex209/contrib/textyl/psrc/tylext.h5
-rw-r--r--macros/latex209/contrib/textyl/src/Makefile23
-rw-r--r--macros/latex209/contrib/textyl/src/defs.h208
-rw-r--r--macros/latex209/contrib/textyl/src/globals.c22
-rw-r--r--macros/latex209/contrib/textyl/src/globals.h208
-rw-r--r--macros/latex209/contrib/textyl/src/io.c347
-rw-r--r--macros/latex209/contrib/textyl/src/spline.c660
-rw-r--r--macros/latex209/contrib/textyl/src/tables.c157
-rw-r--r--macros/latex209/contrib/textyl/src/tables.h10
-rw-r--r--macros/latex209/contrib/textyl/src/textyl.c3422
-rw-r--r--macros/latex209/contrib/textyl/src/tyl.c1509
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec1.300pkbin0 -> 2468 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec1.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec10.300pkbin0 -> 4208 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec10.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec11.300pkbin0 -> 4208 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec11.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec12.300pkbin0 -> 4644 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec12.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec2.300pkbin0 -> 2716 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec2.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec3.300pkbin0 -> 2716 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec3.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec4.300pkbin0 -> 3084 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec4.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec5.300pkbin0 -> 3084 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec5.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec6.300pkbin0 -> 3432 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec6.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec7.300pkbin0 -> 3432 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec7.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec8.300pkbin0 -> 3692 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec8.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec9.300pkbin0 -> 3692 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/cvec9.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec1.300pkbin0 -> 2468 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec1.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec10.300pkbin0 -> 2536 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec10.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec11.300pkbin0 -> 2536 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec11.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec12.300pkbin0 -> 2664 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec12.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec2.300pkbin0 -> 2504 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec2.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec3.300pkbin0 -> 2504 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec3.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec4.300pkbin0 -> 2516 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec4.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec5.300pkbin0 -> 2516 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec5.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec6.300pkbin0 -> 2516 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec6.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec7.300pkbin0 -> 2516 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec7.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec8.300pkbin0 -> 2520 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec8.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec9.300pkbin0 -> 2520 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/hvec9.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/mf/README9
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/mf/makevec.bat5
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/mf/makevec2.bat13
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/mf/makewrappers.sh7
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/mf/vecbase.mf1151
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/mf/vecbase2.mf176
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec1.300pkbin0 -> 2468 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec1.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec10.300pkbin0 -> 3132 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec10.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec11.300pkbin0 -> 3132 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec11.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec12.300pkbin0 -> 3192 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec12.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec2.300pkbin0 -> 2640 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec2.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec3.300pkbin0 -> 2640 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec3.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec4.300pkbin0 -> 2792 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec4.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec5.300pkbin0 -> 2792 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec5.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec6.300pkbin0 -> 2936 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec6.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec7.300pkbin0 -> 2936 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec7.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec8.300pkbin0 -> 3044 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec8.tfmbin0 -> 944 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec9.300pkbin0 -> 3044 bytes
-rw-r--r--macros/latex209/contrib/textyl/vecfonts/vvec9.tfmbin0 -> 944 bytes
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
new file mode 100644
index 0000000000..7bfac681a8
--- /dev/null
+++ b/macros/latex209/contrib/textyl/doc/tylman.dvi
Binary files differ
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
new file mode 100644
index 0000000000..839e64b1f8
--- /dev/null
+++ b/macros/latex209/contrib/textyl/doc/tylout.dvi
Binary files differ
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
new file mode 100644
index 0000000000..3c39da6f29
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec1.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec1.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec1.tfm
new file mode 100644
index 0000000000..f15f24f7cd
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec1.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec10.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec10.300pk
new file mode 100644
index 0000000000..9a1090b1bf
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec10.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec10.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec10.tfm
new file mode 100644
index 0000000000..bc11ebb747
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec10.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec11.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec11.300pk
new file mode 100644
index 0000000000..9a1090b1bf
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec11.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec11.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec11.tfm
new file mode 100644
index 0000000000..7424d046f7
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec11.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec12.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec12.300pk
new file mode 100644
index 0000000000..23bf540c9a
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec12.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec12.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec12.tfm
new file mode 100644
index 0000000000..3572250795
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec12.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec2.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec2.300pk
new file mode 100644
index 0000000000..8f7709b577
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec2.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec2.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec2.tfm
new file mode 100644
index 0000000000..481df4a70c
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec2.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec3.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec3.300pk
new file mode 100644
index 0000000000..8f7709b577
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec3.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec3.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec3.tfm
new file mode 100644
index 0000000000..da3837af01
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec3.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec4.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec4.300pk
new file mode 100644
index 0000000000..e03445d945
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec4.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec4.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec4.tfm
new file mode 100644
index 0000000000..2605898dab
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec4.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec5.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec5.300pk
new file mode 100644
index 0000000000..e03445d945
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec5.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec5.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec5.tfm
new file mode 100644
index 0000000000..4b28abc081
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec5.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec6.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec6.300pk
new file mode 100644
index 0000000000..d42181435b
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec6.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec6.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec6.tfm
new file mode 100644
index 0000000000..b6075890fe
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec6.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec7.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec7.300pk
new file mode 100644
index 0000000000..d42181435b
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec7.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec7.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec7.tfm
new file mode 100644
index 0000000000..66ac443f72
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec7.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec8.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec8.300pk
new file mode 100644
index 0000000000..a8447035b4
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec8.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec8.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec8.tfm
new file mode 100644
index 0000000000..499ec767a7
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec8.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec9.300pk b/macros/latex209/contrib/textyl/vecfonts/cvec9.300pk
new file mode 100644
index 0000000000..a8447035b4
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec9.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/cvec9.tfm b/macros/latex209/contrib/textyl/vecfonts/cvec9.tfm
new file mode 100644
index 0000000000..1bc6bd0a52
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/cvec9.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec1.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec1.300pk
new file mode 100644
index 0000000000..3c39da6f29
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec1.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec1.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec1.tfm
new file mode 100644
index 0000000000..f15f24f7cd
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec1.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec10.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec10.300pk
new file mode 100644
index 0000000000..45674bbc05
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec10.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec10.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec10.tfm
new file mode 100644
index 0000000000..7d795db2fe
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec10.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec11.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec11.300pk
new file mode 100644
index 0000000000..45674bbc05
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec11.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec11.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec11.tfm
new file mode 100644
index 0000000000..21dacc2855
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec11.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec12.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec12.300pk
new file mode 100644
index 0000000000..e15485356e
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec12.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec12.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec12.tfm
new file mode 100644
index 0000000000..ef0926a826
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec12.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec2.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec2.300pk
new file mode 100644
index 0000000000..994a8e36aa
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec2.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec2.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec2.tfm
new file mode 100644
index 0000000000..377b92782b
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec2.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec3.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec3.300pk
new file mode 100644
index 0000000000..994a8e36aa
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec3.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec3.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec3.tfm
new file mode 100644
index 0000000000..0a482b0d51
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec3.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec4.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec4.300pk
new file mode 100644
index 0000000000..8dad1e314a
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec4.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec4.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec4.tfm
new file mode 100644
index 0000000000..8d0dddacd3
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec4.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec5.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec5.300pk
new file mode 100644
index 0000000000..8dad1e314a
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec5.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec5.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec5.tfm
new file mode 100644
index 0000000000..08164eb704
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec5.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec6.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec6.300pk
new file mode 100644
index 0000000000..4fc472f53c
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec6.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec6.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec6.tfm
new file mode 100644
index 0000000000..bbcde71122
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec6.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec7.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec7.300pk
new file mode 100644
index 0000000000..4fc472f53c
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec7.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec7.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec7.tfm
new file mode 100644
index 0000000000..22ed363a84
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec7.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec8.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec8.300pk
new file mode 100644
index 0000000000..e23662dd66
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec8.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec8.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec8.tfm
new file mode 100644
index 0000000000..080ebcd67b
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec8.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec9.300pk b/macros/latex209/contrib/textyl/vecfonts/hvec9.300pk
new file mode 100644
index 0000000000..e23662dd66
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec9.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/hvec9.tfm b/macros/latex209/contrib/textyl/vecfonts/hvec9.tfm
new file mode 100644
index 0000000000..d1b7993f3d
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/hvec9.tfm
Binary files differ
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
new file mode 100644
index 0000000000..3c39da6f29
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec1.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec1.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec1.tfm
new file mode 100644
index 0000000000..f15f24f7cd
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec1.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec10.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec10.300pk
new file mode 100644
index 0000000000..0dc35219a9
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec10.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec10.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec10.tfm
new file mode 100644
index 0000000000..fe20e066fe
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec10.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec11.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec11.300pk
new file mode 100644
index 0000000000..0dc35219a9
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec11.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec11.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec11.tfm
new file mode 100644
index 0000000000..977c161971
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec11.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec12.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec12.300pk
new file mode 100644
index 0000000000..c1dbb7cb23
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec12.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec12.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec12.tfm
new file mode 100644
index 0000000000..60ebe0f76a
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec12.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec2.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec2.300pk
new file mode 100644
index 0000000000..4bccb1940a
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec2.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec2.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec2.tfm
new file mode 100644
index 0000000000..536afd6b5a
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec2.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec3.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec3.300pk
new file mode 100644
index 0000000000..4bccb1940a
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec3.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec3.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec3.tfm
new file mode 100644
index 0000000000..529da7659c
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec3.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec4.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec4.300pk
new file mode 100644
index 0000000000..c6cfa9f899
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec4.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec4.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec4.tfm
new file mode 100644
index 0000000000..a4d29faf30
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec4.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec5.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec5.300pk
new file mode 100644
index 0000000000..c6cfa9f899
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec5.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec5.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec5.tfm
new file mode 100644
index 0000000000..8d6e0be6d2
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec5.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec6.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec6.300pk
new file mode 100644
index 0000000000..0fcdd5c8de
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec6.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec6.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec6.tfm
new file mode 100644
index 0000000000..6bc4c13fb6
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec6.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec7.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec7.300pk
new file mode 100644
index 0000000000..0fcdd5c8de
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec7.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec7.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec7.tfm
new file mode 100644
index 0000000000..d0a39d4c4d
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec7.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec8.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec8.300pk
new file mode 100644
index 0000000000..543bd2c9b7
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec8.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec8.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec8.tfm
new file mode 100644
index 0000000000..a503d67168
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec8.tfm
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec9.300pk b/macros/latex209/contrib/textyl/vecfonts/vvec9.300pk
new file mode 100644
index 0000000000..543bd2c9b7
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec9.300pk
Binary files differ
diff --git a/macros/latex209/contrib/textyl/vecfonts/vvec9.tfm b/macros/latex209/contrib/textyl/vecfonts/vvec9.tfm
new file mode 100644
index 0000000000..89aadb973c
--- /dev/null
+++ b/macros/latex209/contrib/textyl/vecfonts/vvec9.tfm
Binary files differ