ltpictur.dtx

Johannes Braams  David Carlisle  Alan Jeffrey
Leslie Lamport  Frank Mittelbach  Chris Rowley

Rainer Schöpf

1995/10/27

1 Picture Mode

Picture mode commands. In addition to the commands available in L^{A}TEX2.09, This section adds the new \qbezier command for drawing curves.

\qbezier \qbezier[⟨N ⟩](⟨AX,AY ⟩)(⟨BX,BY ⟩)(⟨CX,CY ⟩) plots a quadratic Bezier curve from (⟨AX,AY ⟩) to (⟨CX,CY ⟩), with (⟨BX,BY ⟩) as the third Bezier point, using N + 1 points equally spaced parametrically. If N = 0 (the default value), then a sufficient number of points are used to draw a connected curve–except that at most \qbeziermax + 1 points are drawn. A “point” is a square of side

\@wholewidth.

\bezier In addition, to be compatible with the old bezier package, a variant of this command, \bezier, is defined, in which the first argument is not optional.

\unitlength = value of dimension argument \@wholewidth = current line width \@halfwidth = half of current line width \@linefnt = font for drawing lines \@circlefnt = font for drawing circles

\linethickness{DIM} : Sets the width of horizontal and vertical lines in a picture to DIM. Does not change width of slanted lines or circles. Width of all lines reset by \thinlines and

     \thicklines

\picture(XSIZE,YSIZE)(XORG,YORG)

BEGIN

     \@picht :=L YSIZE * \unitlength
     box \@picbox :=
          \hb@xt@ XSIZE * \unitlength
            {\hskip -XORG * \unitlength
             \lower YORG * \unitlength
             \hbox{

          \ignorespaces    %% added 13 June 89

END

\endpicture ==

BEGIN

                } \hss }
                heigth of \@picbox := \@picht

depth of \@picbox := 0

                \mbox{\box\@picbox}   %% change 26 Aug 91

END

\put(X, Y){OBJ} ==

BEGIN

  \@killglue
  \raise Y * \unitlength  \hb@xt@ 0pt { \hskip X * \unitlength
                                           OBJ \hss
}
  \ignorespaces

END

\multiput(X,Y)(DELX,DELY){N}{OBJ} == BEGIN

 \@killglue
 \@multicnt := N
 \@xdim := X * \unitlength
 \@ydim := Y * \unitlength
 while \@multicnt > 0
   do \raise \@ydim \hb@xt@ 0pt { \hskip \@xdim
                                          OBJ \hss   }
      \@multicnt := \@multicnt - 1
      \@xdim  := \@xdim + DELX * \unitlength
      \@ydim  := \@ydim + DELY * \unitlength

od

 \ignorespaces

END

\shortstack[POS]{TEXT} : Makes a \vbox containing TEXT stacked as a one-column array, positioned l, r or c as indicated by POS.

The ‘2ekernel’ code ensures that a \usepackage{autopict} is essentially ignored if a ‘full’ format is being used that has picture mode already in the format.

1 ⟨2ekernel⟩\expandafter\let\csname ver@autopict.sty\endcsname\fmtversion
\@wholewidth
\@halfwidth

2 ⟨∗2ekernel | autoload⟩

3 \newdimen\@wholewidth

 4 \newdimen\@halfwidth
\unitlength
 5 \newdimen\unitlength \unitlength =1pt
\@picbox \@picht
 6 \newbox\@picbox
 7 \newdimen\@picht

8 ⟨/2ekernel | autoload⟩

\picture #1 should be white space.

\pictur@ #1 should be a ( (eating any white space before the bracket),

9 ⟨∗2ekernel | def⟩

10 \long\gdef\picture#1{\pictur@#1}
11 \gdef\pictur@(#1){%
12 \@ifnextchar({\@picture(#1)}{\@picture(#1)(0,0)}}

13 ⟨/2ekernel | def⟩ 14 ⟨∗autoload⟩

15 \def\pictur@{\@autoload{pict}}
16 \def\picture{\pictur@\picture}

17 ⟨/autoload⟩

\@picture

18 ⟨∗2ekernel | def⟩

19 \gdef\@picture(#1,#2)(#3,#4){%
20 \@picht#2\unitlength
21 \setbox\@picbox\hb@xt@#1\unitlength\bgroup
22  \hskip -#3\unitlength
23  \lower #4\unitlength\hbox\bgroup
24  \ignorespaces}
\endpicture
25 \gdef\endpicture{%
26 \egroup\hss\egroup
27  \ht\@picbox\@picht\dp\@picbox\z@
28  \mbox{\box\@picbox}}

In the definitions of \put and \multiput, \hskip was replaced by \kern just in case arg #3 = “plus”. (Bug detected by Don Knuth. changed 20 Jul 87).

29 \long\gdef\put(#1,#2)#3{%
30 \@killglue\raise#2\unitlength
31 \hb@xt@\z@{\kern#1\unitlength #3\hss}%
32 \ignorespaces}

\multiput #3 had better be a (.

33 \gdef\multiput(#1,#2)#3{%
34 \@xdim #1\unitlength
35 \@ydim #2\unitlength
36 \@multiput(}

\multiput
37 \long\gdef\@multiput(#1,#2)#3#4{%
38 \@killglue\@multicnt #3\relax
39 \@whilenum \@multicnt >\z@\do
40  {\raise\@ydim\hb@xt@\z@{\kern\@xdim #4\hss}%
41  \advance\@multicnt\m@ne
42  \advance\@xdim#1\unitlength\advance\@ydim#2\unitlength}%
43 \ignorespaces}
\@killglue
44 \gdef\@killglue{\unskip\@whiledim \lastskip >\z@\do{\unskip}}

45 ⟨/2ekernel | def⟩

\thinlines \thicklines

46 ⟨∗2ekernel | def⟩

47 \gdef\thinlines{\let\@linefnt\tenln \let\@circlefnt\tencirc
48 \@wholewidth\fontdimen8\tenln \@halfwidth .5\@wholewidth}
49 \gdef\thicklines{\let\@linefnt\tenlnw \let\@circlefnt\tencircw
50 \@wholewidth\fontdimen8\tenlnw \@halfwidth .5\@wholewidth}

51 ⟨/2ekernel | def⟩ 52 ⟨∗autoload⟩

53 \def\thinlines{\pictur@\thinlines}
54 \def\thicklines{\pictur@\thicklines}

55 ⟨/autoload⟩

\linethickness

56 ⟨∗2ekernel | def⟩

57 \gdef\linethickness#1{\@wholewidth #1\relax \@halfwidth .5\@wholewidth}

58 ⟨/2ekernel | def⟩ 59 ⟨∗autoload⟩

60 \def\linethickness{\pictur@\linethickness}

61 ⟨/autoload⟩

\ishortstack

62 ⟨∗2ekernel | def⟩

63 \gdef\shortstack{\@ifnextchar[\@shortstack{\@shortstack[c]}}
\@ishortstack
64 \gdef\@shortstack[#1]{%
65 \leavevmode
66 \vbox\bgroup
67  \baselineskip-\p@\lineskip 3\p@
68  \let\mb@l\hss\let\mb@r\hss
69  \expandafter\let\csname mb@#1\endcsname\relax
70  \let\\\@stackcr
71  \@ishortstack}
\@ishortstack
72 \gdef\@ishortstack#1{\ialign{\mb@l {##}\unskip\mb@r\cr #1\crcr}\egroup}

\@stackcr \@ixstackcr
73 \gdef\@stackcr{\@ifstar\@ixstackcr\@ixstackcr}
74 \gdef\@ixstackcr{\@ifnextchar[\@istackcr{\cr\ignorespaces}}
\@istackcr
75 \gdef\@istackcr[#1]{\cr\noalign{\vskip #1}\ignorespaces}

\line(X,Y){LEN} == BEGIN

\@xarg  := X
\@yarg  := Y
\@linelen := LEN * \unitlength
if \@xarg = 0
   then \@vline

else if \@yarg = 0

          then \@hline
          else \@sline

if

if END

\@sline ==

BEGIN

  if \@xarg < 0

then @negarg := T

         \@xarg := -\@xarg
         \@yyarg := -\@yarg

else @negarg := F

         \@yyarg := \@yarg

fi

  \@tempcnta := |\@yyarg|
  if \@tempcnta > 6

then error: ’LATEX ERROR: Illegal \line or \vector argument.’

         \@tempcnta := 0

fi

  \box\@linechar := \hbox{\@linefnt \@getlinechar(\@xarg,\@yyarg)
}
   if \@yarg > 0 then \@upordown = \raise
                       \@clnht := 0
                 else \@upordown = \lower
                      \@clnht := height of \box\@linechar

fi

   \@clnwd := width of \box\@linechar

if @negarg

     then \hskip - width of \box\@linechar
          \reserved@a == \hskip - 2* width of box \@linechar

  else \reserved@a == \relax

fi %% Put out integral number of line segments

while \@clnwd <  \@linelen
  do \@upordown \@clnht \copy\@linechar
      \reserved@a
      \@clnht := \@clnht + ht of \box\@linechar
      \@clnwd := \@clnwd + width of \box\@linechar

od

%% Put out last segment

\@clnht := \@clnht - height of \box\@linechar
\@clnwd := \@clnwd - width of \box\@linechar
\@tempdima := \@linelen - \@clnwd
\@tempdimb := \@tempdima - width of \box\@linechar
if @negarg then \hskip -\@tempdimb
            else \hskip  \@tempdimb

fi

\@tempdima := 1000 * \@tempdima
\@tempcnta := \@tempdima / width of \box\@linechar
\@tempdima := (\@tempcnta * ht of \box\@linechar)/1000
\@clnht := \@clnht + \@tempdima
if \@linelen < width of box\@linechar
    then \hskip width of box\@linechar
    else \hbox{\@upordown \@clnht \copy\@linechar}

fi END

\@hline ==

BEGIN

if \@xarg < 0 then \hskip -\@linelen \fi
\vrule height \@halfwidth depth \@halfwidth width \@linelen
if \@xarg < 0 then \hskip -\@linelen \fi

END

\@vline == if \@yarg < 0 \@downline else \@upline fi

\@getlinechar(X,Y) ==

BEGIN

\@tempcnta := 8*X - 9

if Y > 0

  then \@tempcnta := \@tempcnta + Y
  else \@tempcnta := \@tempcnta - Y + 64

fi

\char\@tempcnta

END

\vector(X,Y){LEN} ==

BEGIN

\@xarg  := X
\@yarg  := Y
\@linelen := LEN * \unitlength
if \@xarg = 0
   then \@vvector

else if \@yarg = 0

          then \@hvector
          else \@svector

if

if END

\@hvector ==

BEGIN

   \@hline
   {\@linefnt if \@xarg < 0 then \@getlarrow(1,0)
                            else \@getrarrow(1,0)
               fi}

END

\@vvector == if \@yarg < 0 \@downvector else \@upvector fi
\@svector ==

BEGIN

 \@sline
 \@tempcnta := |\@yarg|
   if \@tempcnta < 5
      then \hskip - width of \box\@linechar
            \@upordown \@clnht \hbox
                     {\@linefnt
                      if @negarg then \@getlarrow(\@xarg,\@yyarg)
                                 else \@getrarrow(\@xarg,\@yyarg)
                      fi }

else error: ’LATEX ERROR: Illegal \line or \vector argument.’ fi

END

\@getlarrow(X,Y) ==

BEGIN if Y = 0

   then \@tempcnta := ’33

else \@tempcnta := 16 * X - 9

       \@tempcntb := 2 * Y
       if \@tempcntb > 0
         then \@tempcnta := \@tempcnta + \@tempcntb
         else \@tempcnta := \@tempcnta - \@tempcntb + 64

fi fi

\char\@tempcnta

END

\@getrarrow(X,Y) ==

BEGIN

\@tempcntb := |Y|
case of \@tempcntb
  0 : \@tempcnta := ’55

1 : if X < 3 then \@tempcnta := 24*X - 6 else if X = 3

               then \@tempcnta := 49
               else \@tempcnta := 58 fi

fi 2 : if X < 3

then \@tempcnta := 24*X - 3

else \@tempcnta := 51 % X must = 3 fi

  3 : \@tempcnta := 16*X - 2
  4 : \@tempcnta := 16*X + 7

endcase if Y < 0

  then \@tempcnta := \@tempcnta + 64

fi

\char\@tempcnta

END

\if@negarg
76 \newif\if@negarg
\line
77 \gdef\line(#1,#2)#3{\@xarg #1\relax \@yarg #2\relax
78 \@linelen #3\unitlength
79 \ifdim\@linelen<\z@\@badlinearg\else
80  \ifnum\@xarg =\z@ \@vline
81  \else \ifnum\@yarg =\z@ \@hline \else \@sline\fi
82  \fi
83 \fi}

\@sline
 84 \gdef\@sline{%
 85 \ifnum\@xarg<\z@ \@negargtrue \@xarg -\@xarg \@yyarg -\@yarg
 86 \else \@negargfalse \@yyarg \@yarg \fi
 87 \ifnum \@yyarg >\z@ \@tempcnta\@yyarg \else \@tempcnta -\@yyarg \fi
 88 \ifnum\@tempcnta>6 \@badlinearg\@tempcnta\z@ \fi
 89 \ifnum\@xarg>6 \@badlinearg\@xarg \@ne \fi
 90 \setbox\@linechar\hbox{\@linefnt\@getlinechar(\@xarg,\@yyarg)}%
 91 \ifnum \@yarg >\z@ \let\@upordown\raise \@clnht\z@
 92 \else\let\@upordown\lower \@clnht \ht\@linechar\fi
 93 \@clnwd \wd\@linechar
 94 \if@negarg
 95 \hskip -\wd\@linechar \def\reserved@a{\hskip -2\wd\@linechar}%
 96 \else
 97  \let\reserved@a\relax
 98 \fi
 99 \@whiledim \@clnwd <\@linelen \do
100 {\@upordown\@clnht\copy\@linechar
101 \reserved@a
102 \advance\@clnht \ht\@linechar
103 \advance\@clnwd \wd\@linechar}%
104 \advance\@clnht -\ht\@linechar
105 \advance\@clnwd -\wd\@linechar
106 \@tempdima\@linelen\advance\@tempdima -\@clnwd
107 \@tempdimb\@tempdima\advance\@tempdimb -\wd\@linechar
108 \if@negarg \hskip -\@tempdimb \else \hskip \@tempdimb \fi
109 \multiply\@tempdima \@m
110 \@tempcnta \@tempdima
111 \@tempdima \wd\@linechar \divide\@tempcnta \@tempdima
112 \@tempdima \ht\@linechar \multiply\@tempdima \@tempcnta
113 \divide\@tempdima \@m
114 \advance\@clnht \@tempdima
115 \ifdim \@linelen <\wd\@linechar
116 \hskip \wd\@linechar
117 \else\@upordown\@clnht\copy\@linechar\fi}
\@hline
118 \gdef\@hline{\ifnum \@xarg <\z@ \hskip -\@linelen \fi
119 \vrule \@height \@halfwidth \@depth \@halfwidth \@width \@linelen
120 \ifnum \@xarg <\z@ \hskip -\@linelen \fi}
\getlinechar
121 \gdef\@getlinechar(#1,#2){\@tempcnta#1\relax\multiply\@tempcnta 8%
122 \advance\@tempcnta -9\ifnum #2>\z@ \advance\@tempcnta #2\relax\else
123 \advance\@tempcnta -#2\relax\advance\@tempcnta 64 \fi
124 \char\@tempcnta}
\vector
125 \gdef\vector(#1,#2)#3{\@xarg #1\relax \@yarg #2\relax

126 \@tempcnta \ifnum\@xarg<\z@ -\@xarg\else\@xarg\fi
127 \ifnum\@tempcnta<5\relax
128 \@linelen #3\unitlength
129 \ifdim\@linelen<\z@\@badlinearg\else
130  \ifnum\@xarg =\z@ \@vvector
131  \else \ifnum\@yarg =\z@ \@hvector \else \@svector\fi
132  \fi
133 \fi
134 \else\@badlinearg\fi}
\@hvector
135 \gdef\@hvector{\@hline\hb@xt@\z@{\@linefnt
136 \ifnum \@xarg <\z@ \@getlarrow(1,0)\hss\else
137  \hss\@getrarrow(1,0)\fi}}
\@vvector
138 \gdef\@vvector{\ifnum \@yarg <\z@ \@downvector \else \@upvector \fi}
\@svector
139 \gdef\@svector{\@sline
140 \@tempcnta\@yarg \ifnum\@tempcnta <\z@ \@tempcnta -\@tempcnta\fi
141 \ifnum\@tempcnta <5%
142  \hskip -\wd\@linechar
143  \@upordown\@clnht \hbox{\@linefnt  \if@negarg
144  \@getlarrow(\@xarg,\@yyarg)\else \@getrarrow(\@xarg,\@yyarg)\fi}%
145 \else\@badlinearg\fi}
\@getlarrow
146 \gdef\@getlarrow(#1,#2){\ifnum #2=\z@ \@tempcnta'33 \else
147 \@tempcnta #1\relax\multiply\@tempcnta \sixt@@n \advance\@tempcnta
148 -9 \@tempcntb #2\relax\multiply\@tempcntb \tw@
149 \ifnum \@tempcntb >\z@ \advance\@tempcnta \@tempcntb
150 \else\advance\@tempcnta -\@tempcntb\advance\@tempcnta 64
151 \fi\fi\char\@tempcnta}
\@getrarrow
152 \gdef\@getrarrow(#1,#2){\@tempcntb #2\relax
153 \ifnum\@tempcntb <\z@ \@tempcntb -\@tempcntb\relax\fi
154 \ifcase \@tempcntb\relax \@tempcnta'55 \or
155 \ifnum #1<\thr@@ \@tempcnta #1\relax\multiply\@tempcnta
156 24\advance\@tempcnta -6 \else \ifnum #1=\thr@@ \@tempcnta 49
157 \else\@tempcnta 58 \fi\fi\or
158 \ifnum #1<\thr@@ \@tempcnta=#1\relax\multiply\@tempcnta
159 24\advance\@tempcnta -\thr@@ \else \@tempcnta 51 \fi\or
160 \@tempcnta #1\relax\multiply\@tempcnta
161 \sixt@@n \advance\@tempcnta -\tw@ \else
162 \@tempcnta #1\relax\multiply\@tempcnta
163 \sixt@@n \advance\@tempcnta 7 \fi\ifnum #2<\z@ \advance\@tempcnta 64 \fi
164 \char\@tempcnta}

\@vline
165 \gdef\@vline{\ifnum \@yarg <\z@ \@downline \else \@upline\fi}
\@upline
166 \gdef\@upline{%
167 \hb@xt@\z@{\hskip -\@halfwidth \vrule \@width \@wholewidth
168 \@height \@linelen \@depth \z@\hss}}
\@downline
169 \gdef\@downline{%
170 \hb@xt@\z@{\hskip -\@halfwidth \vrule \@width \@wholewidth
171 \@height \z@ \@depth \@linelen \hss}}
\@upvector
172 \gdef\@upvector{\@upline\setbox\@tempboxa\hbox{\@linefnt\char'66}\raise
173  \@linelen \hb@xt@\z@{\lower \ht\@tempboxa\box\@tempboxa\hss}}
\@downvector
174 \gdef\@downvector{\@downline\lower \@linelen
175  \hb@xt@\z@{\@linefnt\char'77\hss}}
\dashbox{D}(X,Y) ==

BEGIN leave vertical mode

\hb@xt@ 0pt {
\baselineskip := 0pt
\lineskip  := 0pt

%% HORIZONTAL DASHES

\@dashdim := X * \unitlength

\@dashcnt := \@dashdim + 200 % to prevent roundoff error

\@dashdim := D * \unitlength
\@dashcnt := \@dashcnt / \@dashdim
if \@dashcnt is odd
  then \@dashdim := 0pt
       \@dashcnt := (\@dashcnt + 1) / 2
  else \@dashdim := \@dashdim / 2
       \@dashcnt := \@dashcnt / 2 - 1
       \box\@dashbox := \hbox{\vrule height \@halfwidth
                      depth \@halfwidth width \@dashdim}
       \put(0,0){\copy\@dashbox}
       \put(0,Y){\copy\@dashbox}
       \put(X,0){\hskip -\@dashdim\copy\@dashbox}
       \put(X,Y){\hskip -\@dashdim\box\@dashbox}
       \@dashdim := 3 * \@dashdim

fi

\box\@dashbox := \hbox{\vrule height \@halfwidth
                  depth \@halfwidth width D * \unitlength

                  \hskip D * \unitlength}
\@tempcnta := 0
\put(0,0){\hskip \@dashdim
         while \@tempcnta < \@dascnt
           do \copy\@dashbox
              \@tempcnta := \@tempcnta + 1

od

        }
\@tempcnta := 0
put(0,Y){\hskip \@dashdim
         while \@tempcnta < \@dascnt
           do \copy\@dashbox
              \@tempcnta := \@tempcnta + 1

od

        }

%% vertical dashes

\@dashdim := Y * \unitlength

\@dashcnt := \@dashdim + 200 % to prevent roundoff error

\@dashdim := D * \unitlength
\@dashcnt := \@dashcnt / \@dashdim
if \@dashcnt is odd
  then \@dashdim := 0pt
       \@dashcnt := (\@dashcnt + 1) / 2
  else \@dashdim := \@dashdim / 2
       \@dashcnt := \@dashcnt / 2 - 1
       \box\@dashbox := \hbox{\hskip -\@halfwidth
                                \vrule width \@wholewidth
                                         height \@dashdim  }
       \put(0,0){\copy\@dashbox}
       \put(X,0){\copy\@dashbox}
       \put(0,Y){\lower\@dashdim\copy\@dashbox}
       \put(X,Y){\lower\@dashdim\copy\@dashbox}
       \@dashdim := 3 * \@dashdim

fi

\box\@dashbox := \hbox{\vrule width \@wholewidth
                          height D * \unitlength       }
\@tempcnta := 0
put(0,0){\hskip -\halfwidth
         \vbox{while \@tempcnta < \@dashcnt
                do \vskip D*\unitlength
                   \copy\@dashbox
                   \@tempcnta := \@tempcnta + 1

od

               \vskip \@dashdim
              } }

        \@tempcnta := 0
        put(X,0){\hskip -\halfwidth
                 \vbox{while \@tempcnta < \@dashcnt
                        do \vskip D*\unitlength
                           \copy\@dashbox
                           \@tempcnta := \@tempcnta + 1

od

                       \vskip \@dashdim
                      }
                }

} % END DASHES

   \@imakepicbox(X,Y)

END

\dashbox
176 \gdef\dashbox#1(#2,#3){\leavevmode\hb@xt@\z@{\baselineskip \z@skip
177 \lineskip \z@skip
178 \@dashdim #2\unitlength
179 \@dashcnt \@dashdim \advance\@dashcnt 200
180 \@dashdim #1\unitlength\divide\@dashcnt \@dashdim
181 \ifodd\@dashcnt\@dashdim \z@
182 \advance\@dashcnt \@ne \divide\@dashcnt \tw@
183 \else \divide\@dashdim \tw@ \divide\@dashcnt \tw@
184 \advance\@dashcnt \m@ne
185 \setbox\@dashbox \hbox{\vrule \@height \@halfwidth \@depth \@halfwidth
186 \@width \@dashdim}\put(0,0){\copy\@dashbox}%
187 \put(0,#3){\copy\@dashbox}%
188 \put(#2,0){\hskip-\@dashdim\copy\@dashbox}%
189 \put(#2,#3){\hskip-\@dashdim\box\@dashbox}%
190 \multiply\@dashdim \thr@@
191 \fi
192 \setbox\@dashbox \hbox{\vrule \@height \@halfwidth \@depth \@halfwidth
193 \@width #1\unitlength\hskip #1\unitlength}\@tempcnta\z@
194 \put(0,0){\hskip\@dashdim \@whilenum \@tempcnta <\@dashcnt
195 \do{\copy\@dashbox\advance\@tempcnta \@ne }}\@tempcnta\z@
196 \put(0,#3){\hskip\@dashdim \@whilenum \@tempcnta <\@dashcnt
197 \do{\copy\@dashbox\advance\@tempcnta \@ne }}%
198 \@dashdim #3\unitlength
199 \@dashcnt \@dashdim \advance\@dashcnt 200
200 \@dashdim #1\unitlength\divide\@dashcnt \@dashdim
201 \ifodd\@dashcnt \@dashdim \z@
202 \advance\@dashcnt \@ne \divide\@dashcnt \tw@
203 \else
204 \divide\@dashdim \tw@ \divide\@dashcnt \tw@
205 \advance\@dashcnt \m@ne
206 \setbox\@dashbox\hbox{\hskip -\@halfwidth
207 \vrule \@width \@wholewidth

208 \@height \@dashdim}\put(0,0){\copy\@dashbox}%
209 \put(#2,0){\copy\@dashbox}%
210 \put(0,#3){\lower\@dashdim\copy\@dashbox}%
211 \put(#2,#3){\lower\@dashdim\copy\@dashbox}%
212 \multiply\@dashdim \thr@@
213 \fi
214 \setbox\@dashbox\hbox{\vrule \@width \@wholewidth
215 \@height #1\unitlength}\@tempcnta\z@
216 \put(0,0){\hskip -\@halfwidth \vbox{\@whilenum \@tempcnta <\@dashcnt
217 \do{\vskip #1\unitlength\copy\@dashbox\advance\@tempcnta \@ne }%
218 \vskip\@dashdim}}\@tempcnta\z@
219 \put(#2,0){\hskip -\@halfwidth \vbox{\@whilenum \@tempcnta<\@dashcnt
220 \do{\vskip #1\unitlength\copy\@dashbox\advance\@tempcnta \@ne }%
221 \vskip\@dashdim}}}\@makepicbox(#2,#3)}

CIRCLES AND OVALS

USER COMMANDS:

\circle{D} : Produces the circle with the diameter as close as

           possible to D * \unitlength.  \put(X,Y){\circle{D}}

puts the circle with its center at (X,Y).

\oval(X,Y) : Makes an oval as round as possible that fits in the rectangle of width X * \unitlength and height Y * \unitlength. The reference point is the center.

\oval(X,Y)[POS] : Save as \oval(X,Y) except it draws only the half or quadrant of the oval indicated by POS. E.G., \oval(X,Y)[t] draws just the top half and \oval(X,Y)[br] draws just the bottom right quadrant. In all cases, the reference point is the same as the unqualified \oval(X,Y) command.

\@ovvert {DELTA1} {DELTA2} : Makes a vbox containing either the left side or the right side of the oval being constructed. The baseline will coincide with the outside bottom edge of the oval; the left side of the box will coincide with the left edge of the vertical rule. The width of the box will be \@tempdima. DELTA1 and DELTA2 are added to the character number in

\@tempcnta

to get the characters for the top and bottom quarter circle pieces.

\@ovhorz : Makes an hbox containing the straight rule for either the top or the bottom of the oval being constructed. The baseline will coincide with bottom edge of the rule; the left side of the box will coincide with the left side of the oval.

The width of the box will be \@ovxx.

\@getcirc {DIAM} : Sets \@tempcnta to the character number of the top-right quarter circle with the largest diameter less than or equal to DIAM. Sets \@tempboxa to an hbox containing that character.

        Sets \@tempdima to \wd \@tempboxa, which is the distance

from the circle’s left outside edge to its right

inside edge.

(These characters are like those described in the

TeXbook, pp. 389-90.)

\@getcirc {DIAM} ==

BEGIN

\@tempcnta := integer coercion of (DIAM + 2pt)

+ 2pt added 1 Nov 88

\@tempcnta := \@tempcnta / integer coercion of 4pt

if \@tempcnta > 10
then \@tempcnta := 10 fi
if \@tempcnta > 0
then \@tempcnta := \@tempcnta-1

else LaTeX Warning: Oval too small. fi

\@tempcnta  := 4 * \@tempcnta
\@tempboxa  := \hbox{\@circlefnt \char \@tempcnta}
\@tempdima  := \wd \@tempboxa

END

\@put{X}{Y}{OBJ} ==

BEGIN

\raise Y \hb@xt@ 0pt{\hskip X OBJ \hss}

END

\@oval(X,Y)[POS] ==

BEGIN

\begingroup
\boxmaxdepth := \maxdimen

@ovt := @ovb := @ovl := @ovr := true for all E in POS

do @ovE := false od

\@ovxx  := X * \unitlength
\@ovyy  := Y * \unitlength
\@tempdimb := min(\@ovxx,\@ovyy)
\@getcirc{\@tempdimb-2pt}   %% ”-2pt” added 7 Dec 89
\@ovro  := \ht \@tempboxa
\@ovri  := \dp \@tempboxa

\@ovdx  := \@ovxx - \@tempdima
\@ovdx  := \@ovdx/2
\@ovdy  := \@ovyy - \@tempdima
\@ovdy  := \@ovyy/2
\@circlefnt
\@tempboxa :=
    \hbox{

if @ovr

            then \@ovvert{3}{2} \kern -\@tempdima

fi

if @ovl

            then \kern \@ovxx \@ovvert{0}{1} \kern
-\@tempdima
                 \kern -\@ovxx

fi

if @ovt

            then \@ovhorz \kern -\@ovxx

fi

if @ovb

            then \raise \@ovyy \@ovhorz

fi

         }
\@ovdx  := \@ovdx + \@ovro
\@ovdy  := \@ovdy + \@ovro
\ht\@tempboxa := \dp\@tempboxa := 0
\@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}
\endgroup

END

\@ovvert {DELTA1} {DELTA2} ==

BEGIN

\vbox to \@ovyy {

if @ovb

                 then \@tempcntb := \@tempcnta + DELTA1
                      \kern -\@ovro
                      \hbox { \char \@tempcntb }
                      \nointerlineskip
                 else \kern \@ovri \kern \@ovdy

fi

               \leaders \vrule width \@wholewidth \vfil
               \nointerlineskip

if @ovt

                 then \@tempcntb := \@tempcnta + DELTA2
                      \hbox { \char \@tempcntb }
                 else \kern \@ovdy \kern \@ovro

fi

  }

END

\@ovhorz ==

BEGIN

\hb@xt@ \@ovxx{
\kern \@ovro

if @ovr then

  else \kern \@ovdx

fi

\leaders \hrule height \@wholewidth \hfil

if @ovl then

  else \kern \@ovdx

fi

\kern \@ovri
}

END

\circle{DIAM} ==

BEGIN

\begingroup
\boxmaxdepth := maxdimen
\@tempdimb := DIAM *\unitlength
if \@tempdimb > 15.5pt
then \@getcirc{\@tempdimb}
\@ovro := \ht \@tempboxa
\@tempboxa := \hbox{
\@circlefnt
\@tempcnta := \@tempcnta + 2
\char \@tempcnta
\@tempcnta := \@tempcnta - 1
\char \@tempcnta
\kern -2\@tempdima
\@tempcnta := \@tempcnta + 2
\raise \@tempdima \hbox { \char \@tempcnta }
\raise \@tempdima \box\@tempboxa
}
\ht\@tempboxa := \dp\@tempboxa := 0
\@put{-\@ovro}{-\@ovro}{\@tempboxa}

else

\@circ{\@tempdimb}{96}

fi

\endgroup

END

  \circle*{DIAM} == \@dot{DIAM} ==
 \@circ{DIAM*\unitlength}{112}
  \@circ{DIAM}{CHAR} ==

BEGIN \@tempcnta := integer coercion of (DIAM + .5pt)/1pt.

    if \@tempcnta > 15 then \@tempcnta := 15 fi
    if \@tempcnta > 1 then \@tempcnta := \@tempcnta - 1 fi
    \@tempcnta := \@tempcnta + CHAR
    \@circlefnt
    \char \@tempcnta

END

\if@ovt \if@ovb \if@ovl \if@ovr If producing the Top Bottom Left or Right of an oval.

222 \newif\if@ovt
223 \newif\if@ovb
224 \newif\if@ovl
225 \newif\if@ovr

226 ⟨/2ekernel | def⟩ 227 ⟨∗2ekernel | autoload⟩

\@ovxx
\@ovyy
\@ovdx
\@ovdy
\@ovro
\@ovri

228 \newdimen\@ovxx
229 \newdimen\@ovyy
230 \newdimen\@ovdx
231 \newdimen\@ovdy
232 \newdimen\@ovro
233 \newdimen\@ovri

234 ⟨/2ekernel | autoload⟩

\advance\@tempdima 2pt\relax added 1 Nov 88 to fix bug in which size of drawn circle not monotonic function of argument of \circle, caused by different rounding for dimensions of large and small circles.

235 ⟨∗2ekernel | def⟩

\@getcirc
236 \gdef\@getcirc#1{\@tempdima #1\relax \advance\@tempdima 2\p@
237 \@tempcnta\@tempdima
238 \@tempdima 4\p@ \divide\@tempcnta\@tempdima
239 \ifnum \@tempcnta >10\relax \@tempcnta 10\relax\fi
240 \ifnum \@tempcnta >\z@ \advance\@tempcnta\m@ne
241  \else \@latex@warning{Oval too small}\fi
242 \multiply\@tempcnta 4\relax
243 \setbox \@tempboxa \hbox{\@circlefnt
244 \char \@tempcnta}\@tempdima \wd \@tempboxa}

\@put
245 \gdef\@put#1#2#3{\raise #2\hb@xt@\z@{\hskip #1#3\hss}}
\oval
246 \gdef\oval(#1,#2){\@ifnextchar[{\@oval(#1,#2)}{\@oval(#1,#2)[]}}
\@oval
247 \gdef\@oval(#1,#2)[#3]{\begingroup\boxmaxdepth \maxdimen
248 \@ovttrue \@ovbtrue \@ovltrue \@ovrtrue
249 \@tfor\reserved@a :=#3\do{\csname @ov\reserved@a false\endcsname}%
250 \@ovxx
251 #1\unitlength \@ovyy #2\unitlength
252 \@tempdimb \ifdim \@ovyy >\@ovxx \@ovxx\else \@ovyy \fi
253 \advance \@tempdimb -2\p@
254 \@getcirc \@tempdimb
255 \@ovro \ht\@tempboxa \@ovri \dp\@tempboxa
256 \@ovdx\@ovxx \advance\@ovdx -\@tempdima \divide\@ovdx \tw@
257 \@ovdy\@ovyy \advance\@ovdy -\@tempdima \divide\@ovdy \tw@
258 \@circlefnt \setbox\@tempboxa
259 \hbox{\if@ovr \@ovvert32\kern -\@tempdima \fi
260 \if@ovl \kern \@ovxx \@ovvert01\kern -\@tempdima \kern -\@ovxx \fi
261 \if@ovt \@ovhorz \kern -\@ovxx \fi
262 \if@ovb \raise \@ovyy \@ovhorz \fi}\advance\@ovdx\@ovro
263 \advance\@ovdy\@ovro \ht\@tempboxa\z@ \dp\@tempboxa\z@
264 \@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}%
265 \endgroup}
\@ovvert
266 \gdef\@ovvert#1#2{\vbox to\@ovyy{%
267  \if@ovb \@tempcntb \@tempcnta \advance \@tempcntb #1\relax
268  \kern -\@ovro \hbox{\char \@tempcntb}\nointerlineskip
269  \else \kern \@ovri \kern \@ovdy \fi
270  \leaders\vrule \@width \@wholewidth\vfil \nointerlineskip
271  \if@ovt \@tempcntb \@tempcnta \advance \@tempcntb #2\relax
272  \hbox{\char \@tempcntb}%
273  \else \kern \@ovdy \kern \@ovro \fi}}
\@ovhorz
274 \gdef\@ovhorz{\hb@xt@\@ovxx{\kern \@ovro
275  \if@ovr \else \kern \@ovdx \fi
276  \leaders \hrule \@height \@wholewidth \hfil
277  \if@ovl \else \kern \@ovdx \fi
278  \kern \@ovri}}
\circle
279 \gdef\circle{\@inmatherr\circle\@ifstar\@dot\@circle}
\@circle
280 \gdef\@circle#1{%

281 \begingroup \boxmaxdepth \maxdimen \@tempdimb #1\unitlength
282 \ifdim \@tempdimb >15.5\p@ \@getcirc\@tempdimb
283  \@ovro\ht\@tempboxa
284  \setbox\@tempboxa\hbox{\@circlefnt
285  \advance\@tempcnta\tw@ \char \@tempcnta
286  \advance\@tempcnta\m@ne \char \@tempcnta \kern -2\@tempdima
287  \advance\@tempcnta\tw@
288  \raise \@tempdima \hbox{\char\@tempcnta}\raise \@tempdima
289  \box\@tempboxa}\ht\@tempboxa\z@ \dp\@tempboxa\z@
290  \@put{-\@ovro}{-\@ovro}{\box\@tempboxa}%
291 \else  \@circ\@tempdimb{96}\fi\endgroup}

\@dot Internal form of \circle*.

292 \gdef\@dot#1{\@tempdimb #1\unitlength \@circ\@tempdimb{112}}
\@circ
293 \gdef\@circ#1#2{\@tempdima #1\relax \advance\@tempdima .5\p@
294 \@tempcnta\@tempdima \@tempdima \p@
295 \divide\@tempcnta\@tempdima
296 \ifnum\@tempcnta >15\relax \@tempcnta 15\relax \fi
297 \ifnum \@tempcnta >\z@ \advance\@tempcnta\m@ne\fi
298 \advance\@tempcnta #2\relax
299 \@circlefnt \char\@tempcnta}

300 ⟨/2ekernel | def⟩

301 ⟨∗2ekernel | autoload⟩

\@xarg \@yarg \@yyarg Counters used for manipulating the ‘slope’ arguments.

302 \newcount\@xarg
303 \newcount\@yarg
304 \newcount\@yyarg
\@multicnt Counter used in \multiput, and also \multicolumn.
305 \newcount\@multicnt

\@xdim \yxdim Length registers.

306 \newdimen\@xdim
307 \newdimen\@ydim

\@linechar Box for holding a line segment character, for sloping lines.

308 \newbox\@linechar

\@linelen Length of the line currently being built.

309 \newdimen\@linelen

\@clnwd \@clnht Height and width of current line segment.

310 \newdimen\@clnwd
311 \newdimen\@clnht

\@dashdim \@dashbox \@dashcnt  \dashbox internal registers.
312 \newdimen\@dashdim
313 \newbox\@dashbox
314 \newcount\@dashcnt

Initialization: “\thinlines”

315 \let\@linefnt\tenln
316 \let\@circlefnt\tencirc
317 \@wholewidth\fontdimen8\tenln
318 \@halfwidth .5\@wholewidth

319 ⟨/2ekernel | autoload⟩

1.1 Curves

The new \qbezier command, based on the old \bezier defined in bezier.sty.

\qbezier[N] == \bezier{N}

\bezier{N}(AX,AY)(BX,BY)(CX,CY) ==

BEGIN

IF N = 0

THEN \@xdima := |BX - AX| \@xb := |CX - BX|

\@xa := Max(\@xa, \@xb)

\@ya := |BY - AY| \@yb := |CY - BY|

\@ya := Max(\@ya, \@yb)
@sc := Max(\@xa, \@ya)

%% The coefficient .5 below is the degree of overlap of %% successive points, where 1 is no overlap and 0 is %% complete overlap. A coefficient of C multiplies %% the number of points plotted by 1/C.

%%
\@xa := .5 * \@halfwidth
@sc := @sc / \@halfwidth

@sc := Max(@sc, qbeziermax) ELSE @sc := N

@scp := @sc+1

\@xb := 2 * (BX - AX) * \unitlength
\@xa := ((CX-AX)*\unitlength - \@xb)/@sc
\@yb := 2 * (BY - AY) * \unitlength
\@ya := ((CY-AY)*\unitlength - \@yb)/@sc
\@pictdot := square rule of width \@wholewidth
\count@ := 0

WHILE \count@ < @scp

DO \@xdim := ((\count@*\@xa + @xb) / @sc) * \count@

             \@ydim := ((\count@*\@ya + @yb) / @sc) * \count@

plot pt with relative coords (\@xdim,\@ydim)

             \count@ := \count@+1

OD

\qbeziermax The maximum number of points to plot.

320 ⟨∗2ekernel | def⟩

321 ⟨def⟩\ifx\qbeziermax\@undefined
322 \gdef\qbeziermax{500}

323 ⟨def⟩\fi

In the code below, to save registers \@a … are not used. Instead other registers are reused.

    \newcounter{@sc} -> \c@multicnt
    \newcounter{@scp} -> \@tempcnta
    \newdimen\@xa ->  \@ovxx
    \newdimen\@xb ->  \@ovdx
    \newdimen\@ya ->  \@ovyy
    \newdimen\@yb ->  \@ovdy
    \newsavebox{\@pictdot} -> \@tempboxa

\qbezier Main user-level command to plot quadratic bezier curves. #2 should be (.

324 \newcommand\qbezier[2][0]{\bezier{#1}#2}

\bezier Form of \bezier compatible with 2.09 bezier.sty, but modified to ignore spaces between its arguments. #2 should be white space, and #4 should be (.

325 \gdef\bezier#1)#2(#3)#4({\@bezier#1)(#3)(}
\@bezier
326 \gdef\@bezier#1(#2,#3)(#4,#5)(#6,#7){%
327 \ifnum #1=\z@
328  \@ovxx #4\unitlength
329  \advance\@ovxx -#2\unitlength
330  \ifdim \@ovxx<\z@ \@ovxx -\@ovxx \fi
331  \@ovdx #6\unitlength
332  \advance\@ovdx -#4\unitlength
333  \ifdim \@ovdx<\z@ \@ovdx -\@ovdx \fi
334  \ifdim \@ovxx<\@ovdx \@ovxx \@ovdx \fi
335  \@ovyy #5\unitlength
336  \advance\@ovyy -#3\unitlength
337  \ifdim \@ovyy<\z@ \@ovyy -\@ovyy \fi
338  \@ovdy #7\unitlength
339  \advance\@ovdy -#5\unitlength
340  \ifdim \@ovdy<\z@  \@ovdy -\@ovdy \fi
341  \ifdim \@ovyy<\@ovdy \@ovyy  \@ovdy \fi
342  \@multicnt
343  \ifdim \@ovxx>\@ovyy \@ovxx \else \@ovyy \fi

344  \@ovxx .5\@halfwidth \divide\@multicnt\@ovxx
345  \ifnum \qbeziermax<\@multicnt \@multicnt\qbeziermax\relax \fi
346 \else \@multicnt#1\relax \fi
347 \@tempcnta\@multicnt \advance\@tempcnta\@ne
348 \@ovdx #4\unitlength \advance\@ovdx -#2\unitlength
349  \multiply\@ovdx \tw@
350 \@ovxx #6\unitlength \advance\@ovxx -#2\unitlength
351  \advance\@ovxx -\@ovdx \divide\@ovxx\@multicnt
352 \@ovdy #5\unitlength \advance\@ovdy -#3\unitlength
353  \multiply\@ovdy \tw@
354 \@ovyy #7\unitlength \advance\@ovyy -#3\unitlength
355  \advance\@ovyy -\@ovdy \divide\@ovyy\@multicnt
356 \setbox\@tempboxa\hbox{\vrule \@height\@halfwidth
357  \@depth \@halfwidth
358  \@width \@wholewidth}%
359 \put(#2,#3){%
360  \count@\z@
361  \@whilenum{\count@<\@tempcnta}\do
362  {\@xdim\count@\@ovxx
363  \advance\@xdim\@ovdx
364  \divide\@xdim\@multicnt
365  \multiply\@xdim\count@
366  \@ydim\count@\@ovyy
367  \advance\@ydim\@ovdy
368  \divide\@ydim\@multicnt
369  \multiply\@ydim\count@
370  \raise \@ydim
371  \hb@xt@\z@{\kern\@xdim
372  \unhcopy\@tempboxa\hss}%
373  \advance\count@\@ne}}}

374 ⟨/2ekernel | def⟩