% included are the changes required to make it work with DVIPS
% It should be modifiable to any other decent driver too
% This is the complete texgraph macros ... for use with the INRS/Beebe
% Postscript driver
% This is the INRSTEX version
% Graphics macros for TeX using POSTCRIPT
% ----- Needs mod to count characters in special ... some drivers have an
% input limit of 500 characters in a \special
% ===============================================================
% THIS VERSION IS FOR USE with a PostScript Driver with
% \p@sfile to signal a file name
% \p@sinline to signal inline PostScript
% processes \specials and dvi commands in order.
% does not place a (save restore) pair about a \special.
%
% \printhv defines scale/directions for inline Postscript
% \filehv defines scale/directions for file Postscript
%
% Both INRS's modification of Beebe's DVIALW and ArborText's PostScript
% drivers satisfy these minimal requirements.
% It assumes that the underlying units are 300 pix/in
% Standard PostScript Conventions
% This is easily changed by changing the \hpix or \vpix
% It assumes that x,y are in the "normal" up/left direction.
% File inclusions require the existence of a bounding box for the correct
% spacing to be left.
% ===============================
% Most arguments, excepting file names, are delimited by spaces. Thus
% braces { .... } will usually only occur around inserted text ... which
% still must be followed by a space or end of line.
% ======================
\catcode`\@=11
% =============== Driver Signal Forms =======================
%\xdef\p@sfile{ps: } % file signal INRS DVIALW
\xdef\p@sfile{ps: plotfile } % file signal DVIPS
\xdef\p@sinline{ps:: } % inline signal DVIPS ... INRS DVIALW
% This translates the direction of the page if the printer assumptions
% are different than TeX. The values should be +-1.
\gdef\printhv #1 #2 {\gdef\p@hv{ #1 #2 scale }}
\gdef\filehv #1 #2 {\gdef\f@schv{ #1 #2 scale }}
\gdef\rtdir #1 {\gdef\r@tdir{ #1 }} % neg or nothing PS has no pos
% ============== LateX support =================
%\newenvironment{TeXgraph}{\btg}{\etg}
% This is the only change between the LateX and INRSTeX versions
% ======= Simple Plotfile support ===========
% These are vanilla forms for inserting an encapsulated PostScript file
% or creating a centered graphics environment.
% \centergraph needs to be very \long
\long\gdef\centergraph#1{\hbox to
\hsize{\hss\vbox{#1\vgraphskip}\hgraphskip\hss}}
\gdef\centerplotfile#1{\centergraph{\btg\includefile {#1} \etg}}
% if you use the Latex command to create the new texgraph environment,
% then you will automatically be "inside" Texgraph. This
% means that you should use such commands as
% \includefile \incscmvfile \incscfile
% ========= error messages =========
% \language=0 -- English, 1 - French
\ifnum \language=0 \message{<< WARNING -- TeXGraph needs DVIPS >>}
\xdef\bbmess{Searching for BoundingBox }
\xdef\incfile{Graphics file}
\xdef\badincfile{Size/Format Error in Graphics File}
\xdef\noincfile{Missing Graphics File}
\else
\message{<< AVERTISSMENT -- TeXGraph a besoin du DVIPS >>}
\xdef\bbmess{Searching for BoundingBox }
\xdef\incfile{Graphics file}
\xdef\badincfile{Size/Format Error in Graphics File}
\xdef\noincfile{Missing Graphics File}
\fi
% ===== debugging code =====
% will send out specials as messages
\gdef\dmess #1{}
\gdef\bmess #1{}
% ======== \global\newif =======
% Plain defines the \newif as a local variable. We need a global
% version if TeXgraph is to be brought in while inside a group.
% This is a simpler, but less elegant version of \newif
%#1 is \if<..> #2 -...true #3 ...false
\gdef\gnewif#1#2#3{\global\let#1=\iffalse \gdef#2{\let#1=\iftrue}\relax
\gdef#3{\let#1=\iffalse}}
% ======== TeXGraph Macros ==========
% Postcript allows for arbitrary translation, scaling, rotation and clipping.
% This version saves the current segment scale(s), unit scale(s), rotation
% and translation and painfully computes and retores the correct form after
% a segment exit. The reason for this is that Postcript can stack only one
% CTM, text needs to have correct rotation and translation but default
% scaling ...
% It would be preferable not to convert any of the units. However, it is
% necessary to know the maximum excursions. Since the PS currentpoint is
% not accessible to TeX, we must keep it ourselves.
% Since negative numbers can be used both maximum and minimum excursions
% are required.
% ====== begin -- end graphics =======
% The maximum and minimum extent in the h and v direction is recorded
% and is accessible
% at the end of a \btg \etg pair (in points). The same value, in pixels is accessible at
% all times
\newcount\maxhpospix
\newcount\maxvpospix
\newcount\minhpospix
\newcount\minvpospix
\newdimen\hgraphsize
\newdimen\vgraphsize
% ========== TeXGraph Nesting Depth ==========
\newcount\g@depth \global\g@depth=0 % initializes at zero
\gdef\i@ncgdepth{\global\advance\g@depth by 1 }
\gdef\d@ecgdepth{\global\advance\g@depth by -1 }
% =========== Complete Graph Scaling ===============
% There is a separate scaling for the horizontal, vertical, and text
%pixels /dim unit
\newcount\h@pix % sp/pixel
\gdef\hpix#1/#2 {\wd0=1true#2\relax
\h@pix=\wd0 \divide\h@pix by #1 \relax}
\newcount\v@pix % sp/pixel
\gdef\vpix#1/#2 {\wd0=1true#2\relax
\v@pix=\wd0 \divide\v@pix by #1 \relax}
% Assumes #1 is dimension #2 is count in pixels, #3 sp/pix, #4 scalefactor (real)
% #2 is returned
\gdef\gendimtopix#1#2#3#4{\wd0=#1\dimen0=#4\wd0\relax
\wd0=\dimen0 #2=\wd0 \divide #2 by #3\relax}
% #1 is returned, #5 -\global or {}
\gdef\genpixtopt#1#2#3#4#5{\multiply #2 by #3\relax\wd0=#2sp
#5#1=#4\wd0\relax}
% ---------- Converts maxpix to maxdim removes offset -----
\gdef\maxhvpos{\global\advance\maxhpospix by -\minhpospix\relax
\genpixtopt{\hgraphsize}{\maxhpospix}{\h@pix}{\h@grsc}{\global}\relax
\global\advance\maxvpospix by -\minvpospix\relax
\genpixtopt{\vgraphsize}{\maxvpospix}{\v@pix}{\v@grsc}{\global}}
% ======== The vector offsets my be relative or absolute =====
% ====== update #1 by #2 r@elpos to #3, #4 is max #5 is min=======
\gdef\u@pdate#1#2#3#4#5{\ifr@elpos \advance #1 by #2\else
\advance #2 by #3\relax
#1=#2\fi
\ifnum #1>#4\global #4=#1\fi
\ifnum #1<#5\global #5=#1\fi
}
\gdef\h@update #1{\u@pdate{\h@pos}{#1}{\h@segoff}{\maxhpospix}{\minhpospix}}
\gdef\v@update #1{\u@pdate{\v@pos}{#1}{\v@segoff}{\maxvpospix}{\minvpospix}}
% === pixel position r@elpos to initial offset starting position
\newcount\h@pos \h@pos=0
\newcount\v@pos \v@pos=0
\newcount\r@ang \r@ang=0 % 1000 times degrees ?
% ===== Check for pen up moves only =====
% penup/down are used to determine whether a line needs to be stroked
% when a line pattern or penwidth is changed.
\gnewif{\ifp@down}{\p@downtrue}{\p@downfalse}
% ===== present segment origin and rotation ==========
\newcount\h@segoff
\newcount\v@segoff
\newcount\r@segoff % 1000 times degrees
% segment initialization is a trifle messy
\gdef\s@eginit{\h@segoff =\h@pos \v@segoff=\v@pos}
% PS has the concept of a path that is either
% completed with a "stroke" or "fill" ... stroking
% at the end or beginning of a segment, the special is written out. This is
% to ensure that the input order of the graphics reflects what entities are
% on top of what others. Further it is assumed that the origin does not
% change during an entire \btg ...\etg section. This means that every special
% must first move to the point where the previous one left off. \s@save
% defines \s@restore that restores, in case they had been modified, the line
% width, pattern, hpos, vpos, ... and any future things that need restoration.
% all graphic specials are ended with a stroke (st), whether it needs it not.
% we need a special form to force a space after a \the\nnn form or \p@w
\gdef\b@{ }
\gdef\endsegment{\g@raphout\endgroup
\edef\o@form{}\s@save}
\gdef\s@pout #1#2{\edef\e@form{\special{#1\s@restore\o@form#2}}\dmess{\e@form}\e@form
\edef\o@form{}\s@save}
%\h@vset if there is a move before each special
\gdef\g@raphout{\ifx\empty\o@form \else \ifp@down
\s@pout{\p@sinline td begin }{ st end }\fi\fi\p@downfalse}
\global\let\graphout=\g@raphout
% ====== Segment and units scaling ========
% The units in any segment may be scaled arbitrarily. A unit scale is local
% to a segment but affects enclosed segments unless specifically overidden
% in that segment. In addition there is a graph or segment scale. This
% scaling factor is accumulative and is applied on top of the unit scale.
% These two scaling factors allow for a segment to be designed in nominal
% units, scaled to a nominal size and then be affected by relative scaling
% of an entire graph or segment. In addition there is a relative/absolute
% scale switch that allows for any segment to be unaffected by a graphscale.
% \u@nitsc -- present unit scale, \s@egsc -- present segment scale
% \g@rsc -- present graphscale ... changes when ever either of the former do.
% present implementation does not allow separate v h scaling
% ---- Graph Scale --------
% This changes whenever either of the above change
\gdef\newgraphscale{\realmult{\u@nitsc}{\s@egsc}{\g@rsc}}
% ------ "Real" Multiplication --------
% These functions use the fact that a box dimension may be scaled by
% a real. The final step is to "clean" off the pt on the resulting dim
% Cleans off the pt in a dimension ... pt has catcode 12
{\catcode`\p=12 \catcode`\t=12
\gdef\c@lean#1pt{\edef\cx{#1}}}
% #1 and #2 are multiplicands #3 is a command to capture result
\gdef\realmult#1#2#3{\wd0=1pt\dimen0=#1\wd0\wd0=\dimen0\dimen0=#2\wd0
\edef\R@M{\the\dimen0}\expandafter\c@lean\R@M\edef#3{\cx}}
\gdef\realadd#1#2#3{\dimen0=#1pt\dimen2=#2pt\advance\dimen0by\dimen2
\edef\R@M{\the\dimen0}\expandafter\c@lean\R@M\edef#3{\cx}}
% -------- Command to convert nominal values to pixels ------
% #1 is a decimal number, #2 must be a count, #3 is sp/pix
% This includes all scalings
\gdef\grdimtopix#1#2#3{\gendimtopix{#1\g@dim}{#2}{#3}{\g@rsc}}
% ------- special forms to update positions ------
%============== puts TeX text at this position
% These are pure TeX macros that use \h@pos and \v@pos for orientation
% Text may be put horizontally (left/right) or vertically (down/up)
% ======== sp form of \h@pos and \v@pos respectively ========
\newdimen\t@hpos
\newdimen\t@vpos
\gdef\s@ettpos{\d@umc=\h@pos
\genpixtopt{\t@hpos}{\d@umc}{\h@pix}{}{}\relax
\d@umc=\v@pos
\genpixtopt{\t@vpos}{\d@umc}{\v@pix}{}{}\relax}
% any one of nine reference point may be specified on the
% TeX box. This is Vertical T,C,B and Horizontal L,C,R
% The actual box is 0 height and width.
\newbox\t@box
% #1 LCR default/error L #2 TCB default/error T #3 text -- in hbox
% #1 text #2 - begin rotation form #3 - end rotation form
\long\gdef\m@text#1#2#3{\g@raphout\h@oldmaxpos=\maxhpospix\relax
\v@oldmaxpos=\maxvpospix\relax
\edef\h@oldgrsc{\h@grsc}\edef\v@oldgrsc{\v@grsc}\s@ettpos
\setbox\t@box=\vbox{\normalbaselines
\vskip\t@vpos\hbox{\hskip\t@hpos
\t@init{#2}\relax
\vbox to 0pt{\normalbaselines
\tvglue\hbox to 0pt{\lhglue\hbox{#1}\rhglue
}\bvglue}}}\relax
\dp\t@box=0pt\ht\t@box=0pt\wd\t@box=0pt
\box\t@box
\t@fin{#3}
\global\maxhpospix=\h@oldmaxpos\relax
\global\maxvpospix=\v@oldmaxpos\relax
\xdef\h@grsc{\h@oldgrsc}\edef\v@grsc{\v@oldgrsc}}
% saves maxh(v)pospix on stack
% ========== PS text initializations and terminations ===========
\gdef\t@init#1{\special{\p@sinline td begin \h@vinit gr gs
\t@rhv #1 \t@rneghv end }}
\gdef\t@fin#1{\special{\p@sinline td begin \h@vinit gr gs \m@vhv \t@rhv \p@hv end }}
% .... special test
%\gdef\t@init#1{}
%\gdef\t@fin#1{}
% ... end special test
% ======== circle, arcs =========
% The PS arc will connect the center of the arc to the circumference
% if the newpath includes the move to this point. Thus we define a
% set of arc functions that include/exclude this feature. The default
% does not include this form.
\gdef\larc r:#1 sd:#2 ed:#3 {\h@num{#1}{\d@umc}\p@downtrue
\e@xtend{\o@form}{ st np \the\h@pos\b@ \the\v@pos\b@ \the\d@umc\b@ #2 #3 arc
st np \the\h@pos\b@ \the\v@pos\b@ mv }}
\gdef\lcir r:#1 {\larc r:#1 sd:0 ed:360 }
% ------ this is a raw arc ... can be used in fills --------
% ======= fill command ==========
% The fill command is essentially a polygonal fill ... not a point spreading
% this means that it is possible to erase with white ... The form here
% completes with a closepath applies the fill, starts a newpath and moves
% to the current point. Pattern is a grey level.
% 0 is black 1 is white
% this form both fills and strokes around the path
\gdef\lpfill p:#1 {\p@downtrue
\e@xtend{\o@form}{cp gs #1 sg fill gr st np \the\h@pos\b@ \the\v@pos\b@ mv }}
% ======== Postscript special forms ========
% This allows "raw" postscript to be put in the graph.
\gdef\pst #1{\e@xtend{\o@form}{#1 }}
% These are some useful postscript compatible forms.
% ========= including external files ==========
% an external file is included at the present point on the graph area
% moves are required to get there
% The actual file is placed inside a \t@box and tex commands are used
% to get to the place ... They probably can be nested
% #1 is the filename
% The file is opened, if possible, to read its size. If this exists, it
% is used to update the maximum h/v position.
% The BoundingBox is determined
\newread\q@file
% #1 is the file name
\gnewif{\ifq@read}{\q@readtrue}{\q@readfalse}
\gnewif{\ifq@file}{\q@filetrue}{\q@filefalse}
\gnewif{\ifb@boxexists}{\b@boxexiststrue}{\b@boxexistsfalse}
% #1 == %%BoundingBox, #2 llh #3 llv #4 urh #5 urv #6 rest of line
\gdef\uncat{\catcode`"=12}
{\catcode`\%=12
\gdef\l@shift{\ifx\l@lh\empty \xdef\l@lh{\l@lv}\xdef\l@lv{\u@rh}\xdef
\u@rh{\u@rv}\xdef\u@rv{\e@xt}\fi}
\gdef\B@Box{%%BoundingBox}
\gdef\a@tend{(atend)}
\gdef\a@tendtest{\l@shift\ifx\l@lh\a@tend\relax\else
\global\b@boxexiststrue\q@readfalse\bmess{<< At End Test >>}\fi}
% ============ Design Grid ==============
% This will lay down a grid at the present location. The grid nominally
% at unit dimension intervals. The scale factor sc modifies this. The
% sc is local only to the grid
% =========== Arrow Vectors ==============
% There are three types of arrow heads, filled, open V and triangle
% These are always placed on the end of a vector.
% The basic design has the arrow head which is placed on the vector
% It theoretically can be placed on any curve where the angle is known or
% computable.
\newcount\a@len
\newcount\a@wid
% Parameter specification for arrowheads.
% #1 -- length #2 -- width
% The dimensions are interpreted at current graphscale in force and
% are local to the segment group.
\gdef\arrowheadscale{\arrowheadsize l:.16 w:.04 }
\gdef\arrowheadsize l:#1 w:#2 {\grdimtopix{#1}{\a@len}{\h@pix
}\grdimtopix{#2}{\a@wid}{\h@pix
}}
% postcript commands for inidividual arrow form
\gdef\arrowheadtype t:#1 {\ifx#1T\edef\a@com{cp gs 1 sg fill gr st }\else
\ifx#1F\edef\a@com{cp 0 sg fill }\else
\edef\a@com{st }\fi\fi}
\newcount\h@lp
\newcount\v@lp
% assumes that the dh and dv is in \h@lp \v@lp and present location is tip
% of arrowhead
\gdef\a@draw{st np \the\h@pos\b@ \the\v@pos\b@ mx
\the\v@lp\b@ neg \the\h@lp\b@ at
-\the\a@len\b@ \the\a@wid\b@ mv 0 0 lv
-\the\a@len\b@ -\the\a@wid\b@ lv
\a@com gr }
\gdef\avec h:#1 v:#2 {\h@lp=\h@pos\relax \v@lp=\v@pos\relax
\lvec h:#1 v:#2 \advance\h@lp by -\h@pos\relax
\advance\v@lp by -\v@pos\relax
\e@xtend{\o@form}{\a@draw}}
% ============= End Arrow Vectors =============
% ========= Bezier Curve ==========
% this is a cubic spline that is determined by four points. The initial
% point is assumed to be the current point. An arrow is easily added.