%---------------------------------------------------------------
% PostScript transformations for DVIPS        (c) BOP 1993, 1994
%   BOP s.c.
%   ul. Piastowska 70, 80-363 Gda\'nsk, Poland
%   tel. +48 58 53-46-59
%   email: staszek@ipipan.gda.pl
%   
%---------------------------------------------------------------
% USAGE:
%
%   1) 
%      x_scale and y_scale are given in percents:
%      \zscale changes uniformly x_size and y_size (x_scale=y_scale=scale);
%      \xscale changes only x_size (y_scale=100);
%      \yscale changes only y_size (x_scale=100);
%
%         \zscale{scale} followed by an \hbox or a \vbox
%         \xyscale{x_scale}{y_scale} followed by an \hbox or a \vbox
%         \yxscale{y_scale}{x_scale} followed by an \hbox or a \vbox
%         \xscale{x_scale} followed by an \hbox or a \vbox
%         \yscale{y_scale} followed by an \hbox or a \vbox
%
%   2) 
%      \xyscaleto resizes a box uniformly such that the resulting wd=x_dimen;
%      \yxscaleto resizes a box uniformly such that the resulting ht=y_dimen;
%      \xscaleto resizes a box horizontally such that the resulting wd=x_dimen;
%      \yscaleto resizes a box verically such that the resulting ht=y_dimen;
%
%         \xyscaleto{x_size} followed by an \hbox or a \vbox
%         \yxscaleto{y_size} followed by an \hbox or a \vbox
%         \xscaleto{x_size} followed by an \hbox or a \vbox
%         \yscaleto{y_size} followed by an \hbox or a \vbox
%
%   3)
%      \revolve rotates anticlockwise the box (either \hbox or \vbox
%      following the command) by 90 degree; for the resulting box
%      width = height + depth of the original box, height = width
%      of the original box, and the reference point is the left top corner
%      of the original box; this means that revolving a box four times
%      yields the original box if and only if its depth is zero.
%      \revolvedir- is equivalent to \revolve, \revolvedir+ does almost
%      the same, but rotates the box clockwise;
%     
%         \revolve followed by an \hbox or a \vbox
%         \revolvedir+ followed by an \hbox or a \vbox
%         \revolvedir- followed by an \hbox or a \vbox
%     
%   4) 
%      \rotate rotates a box bay an arbitrary angle, clockwise for angle>0,
%      the resulting box width=height=depth=0pt;
%
%         \rotate{angle} followed by an \hbox or a \vbox
%
%   5)
%      \xflip and \yflip flip the box horizontally and vertically, resp.,
%      i.e., with respect to a vertical and horizontal axis of the box,
%      without changing dimensions of the \box;
%     
%         \xflip followed by an \hbox or a \vbox
%         \yflip followed by an \hbox or a \vbox
%     
%   6) 
%      \slant slopes a box by the angle alpha such that tan(alpha)=slant,
%      without changing dimensions of the \box;
%
%         \slant{slant} followed by an \hbox or a \vbox
%     
%---------------------------------------------------------------
% HISTORY:
% 18 VIII 1993 ver. 0.1
%    * first release
% 30--31 VIII 1993 ver. 0.2
%    * third parameter eliminated from \scale (via \afterassignment
%      and \aftergroup hackery)
%    * added \zscale, \xyscale, \yxscale, \xscale, and \yscale
%      with scaling given in percents
%    * added \scaleto, \xyscaleto, \yxscaleto, \xscaleto, and \yscaleto
% 3 IX 1993 ver. 0.21
%    * \the_scale renamed to \lastscale and made global, thus it became 
%      available to a user
% 8 IX 1993 ver. 0.22
%    * all transformations return \hbox, because of currentpoint
%      positioning
%    * the old version of \scale is become undefined
%    * \slant and \rotate fit the new convention of parameter's
%      hackery -- they are assumed to be followed by an \hbox
%      or a \vbox
% 6 XII 1993 ver. 0.23
%    * \revolve added
%    * \rotate with \vbox patched
% 10 II 1994 ver. 0.24
%    * \revolvedir+, \revolvedir-, \xflip, and \yflip  added
%---------------------------------------------------------------
\edef\undtranscode{\the\catcode`\_} \catcode`\_11
%---------------------------------------------------------------
\newbox\box_tmp % temporary box register
\newdimen\dim_tmp % temporary dimen register (for arithmetic manipulation)
%---------------------------------------------------------------
\def\jump_setbox{\aftergroup\after_setbox}% a general trick
%---------------------------------------------------------------
% ``floating point arithmetic'' (excerpted from T. Rokicki):
% r  y
%
% ^
% |
% |
% |
% |
% |
% 0--------------> t   x
%
\def\resize
    % dimen registers:
    #1% y   make y such that y/r=x/t
    #2% r
    #3% x
    #4% t
%   We have a sticky problem here:  TeX doesn't do floating point arithmetic!
%   Our goal is to compute y = rx/t. The following loop does this reasonably
%   fast, with an error of at most about 16 sp (about 1/4000 pt).
    {%
    % save parameters to the internal variables:
    \dim_r#2\relax \dim_x#3\relax \dim_t#4\relax
    \dim_tmp=\dim_r \divide\dim_tmp\dim_t
    \dim_y=\dim_x \multiply\dim_y\dim_tmp
    \multiply\dim_tmp\dim_t \advance\dim_r-\dim_tmp
    \dim_tmp=\dim_x
    \loop \advance\dim_r\dim_r \divide\dim_tmp 2
    \ifnum\dim_tmp>0
      \ifnum\dim_r<\dim_t\else
        \advance\dim_r-\dim_t \advance\dim_y\dim_tmp \fi
    \repeat
    % assign result:
    #1\dim_y\relax
    }
\newdimen\dim_x    % horizontal size after scaling
\newdimen\dim_y    % vertical size after scaling
\newdimen\dim_t    % horizontal size before scaling
\newdimen\dim_r    % vertical size before scaling
%\newdimen\dim_tmp % register for arithmetic manipulation (already declared)
%---------------------------------------------------------------
\def\perc_scale#1#2{% #1 -- xscale, #2 -- yscale, in percents,
                    % to be followed by an \hbox or a \vbox
  \def\after_setbox{%
    \hbox\bgroup
    \special{ps: gsave currentpoint #2 100 div div exch #1 100 div div exch
             currentpoint neg #2 100 div mul exch neg #1 100 div mul exch
             translate #1 100 div #2 100 div scale translate}%
    \dim_tmp\wd\box_tmp \divide\dim_tmp100 \wd\box_tmp#1\dim_tmp
    \dim_tmp\ht\box_tmp \divide\dim_tmp100 \ht\box_tmp#2\dim_tmp
    \dim_tmp\dp\box_tmp \divide\dim_tmp100 \dp\box_tmp#2\dim_tmp
    \box\box_tmp \special{ps: grestore}\egroup}%
    \afterassignment\jump_setbox\setbox\box_tmp =
}%
%---------------------------------------------------------------
{\catcode`\p12 \catcode`\t12 \gdef\PT_{pt}}
\def\hull_num{\expandafter\hull_num_}
\expandafter\def\expandafter\hull_num_\expandafter#\expandafter1\PT_{#1}
%---------------------------------------------------------------
\def\find_scale#1#2{% #1 -- size after rescaling, #2 -- \wd or \ht
% Finds a scale (\lastscale macro) such that the box following the macro
% call would have the respective dimen (i.e., #2) equal to #1 after rescaling.
% NOTE: it is assumed that prior to calling \find_scale a macro
%       \extra_complete is defined.
  \def\after_setbox{%
    \resize\dim_tmp{100pt}{#1}{#2\box_tmp}%
    \xdef\lastscale{\hull_num\the\dim_tmp}\extra_complete}%
  \afterassignment\jump_setbox\setbox\box_tmp =
}
%---------------------------------------------------------------
\def\scaleto#1#2#3#4{% #1 -- size of dimen #2 (\wd or \ht) after scaling
                     % #3 -- actual x-size, #4 -- actual y-size
  \def\extra_complete{\perc_scale{#3}{#4}\hbox{\box\box_tmp}}%
  \find_scale{#1}#2}
%---------------------------------------------------------------
\let\xyscale\perc_scale
\def\zscale#1{\xyscale{#1}{#1}}
\def\yxscale#1#2{\xyscale{#2}{#1}}
\def\xscale#1{\xyscale{#1}{100}}
\def\yscale#1{\xyscale{100}{#1}}
%---------------------------------------------------------------
\def\xyscaleto#1{\scaleto{#1}\wd\lastscale\lastscale}
\def\yxscaleto#1{\scaleto{#1}\ht\lastscale\lastscale}
\def\xscaleto#1{\scaleto{#1}\wd\lastscale{100}}
\def\yscaleto#1{\scaleto{#1}\ht{100}\lastscale}
%---------------------------------------------------------------
\def\slant#1{% #1 (slant) = tan(alpha), where alpha is the "italic" angle.
             % To be followed by an \hbox or a \vbox
  \hbox\bgroup
  \def\after_setbox{%
    \special{ps: gsave 0 currentpoint neg exch pop 0 currentpoint exch pop
             translate [1 0 #1 1 0 0] concat translate}%
    \box\box_tmp \special{ps: grestore}\egroup}%
  \afterassignment\jump_setbox\setbox\box_tmp =
}%
%---------------------------------------------------------------
\def\rotate#1{% #1 -- angle,
              % to be followed by an \hbox or a \vbox
  \hbox\bgroup
  \def\after_setbox{%
    \setbox\box_tmp\hbox{\box\box_tmp}% otherwise does not work with \vbox
    \wd\box_tmp 0pt \ht\box_tmp 0pt \dp\box_tmp 0pt
    \special{ps: gsave currentpoint currentpoint translate
             #1 rotate neg exch neg exch translate}%
    \box\box_tmp
    \special{ps: grestore}%
    \egroup}%
  \afterassignment\jump_setbox\setbox\box_tmp =
}%
%---------------------------------------------------------------
\newdimen\box_tmp_dim_a
\newdimen\box_tmp_dim_b
\newdimen\box_tmp_dim_c
\def\plus_{+}
\def\minus_{-}
\def\revolvedir#1{% to be followed by an \hbox or a \vbox
  \hbox\bgroup
% check parameter:
   \def\param_{#1}%
   \ifx\param_\plus_ \else \ifx\param_\minus_
   \else
     \errhelp{I would rather suggest to stop immediately.}%
     \errmessage{Argument to \noexpand\revolvedir should be either + or -}%
   \fi\fi
  \def\after_setbox{%
    \box_tmp_dim_a\wd\box_tmp
% prepare to revolving:
    \setbox\box_tmp\hbox{%
     \ifx\param_\plus_\kern-\box_tmp_dim_a\fi
     \box\box_tmp
     \ifx\param_\plus_\kern\box_tmp_dim_a\fi}%
% compute dimensions of the box to be revolved:
    \box_tmp_dim_a\ht\box_tmp \advance\box_tmp_dim_a\dp\box_tmp
    \box_tmp_dim_b\ht\box_tmp \box_tmp_dim_c\dp\box_tmp
    \dp\box_tmp0pt \ht\box_tmp\wd\box_tmp \wd\box_tmp\box_tmp_dim_a
% revolve:
    \kern \ifx\param_\plus_ \box_tmp_dim_c \else \box_tmp_dim_b \fi
    \special{ps: gsave currentpoint currentpoint translate
             #190 rotate neg exch neg exch translate}%
    \box\box_tmp
    \special{ps: grestore}%
    \kern -\ifx\param_\plus_ \box_tmp_dim_c \else \box_tmp_dim_b \fi
    \egroup}%
  \afterassignment\jump_setbox\setbox\box_tmp =
}%
\def\revolve{\revolvedir-}
%---------------------------------------------------------------
\def\xflip{% to be followed by an \hbox or a \vbox
  \hbox\bgroup
  \def\after_setbox{%
    \box_tmp_dim_a.5\wd\box_tmp
% prepare to flipping:
   \setbox\box_tmp
     \hbox{\kern-\box_tmp_dim_a \box\box_tmp \kern\box_tmp_dim_a}%
% flip:
   \kern\box_tmp_dim_a
    \special{ps: gsave currentpoint currentpoint translate
         [-1 0 0 1 0 0] concat neg exch neg exch translate}%
    \box\box_tmp
    \special{ps: grestore}%
    \kern-\box_tmp_dim_a
    \egroup}%
  \afterassignment\jump_setbox\setbox\box_tmp =
}%
%---------------------------------------------------------------
\def\yflip{% to be followed by an \hbox or a \vbox
  \hbox\bgroup
  \def\after_setbox{%
    \box_tmp_dim_a\ht\box_tmp \box_tmp_dim_b\dp\box_tmp
    \box_tmp_dim_c\box_tmp_dim_a \advance\box_tmp_dim_c\box_tmp_dim_b
    \box_tmp_dim_c.5\box_tmp_dim_c
% prepare to flipping:
   \setbox\box_tmp\hbox{\vbox{%
     \kern\box_tmp_dim_c\box\box_tmp\kern-\box_tmp_dim_c}}%
% flip:
   \advance\box_tmp_dim_c-\box_tmp_dim_b
   \setbox\box_tmp\hbox{%
     \special{ps: gsave currentpoint currentpoint translate
         [1 0 0 -1 0 0] concat neg exch neg exch translate}%
     \lower\box_tmp_dim_c\box\box_tmp
     \special{ps: grestore}}%
% restore dimensions of the flipped box:
    \ht\box_tmp\box_tmp_dim_a \dp\box_tmp\box_tmp_dim_b
    \box\box_tmp
    \egroup}%
  \afterassignment\jump_setbox\setbox\box_tmp =
}%
%---------------------------------------------------------------
\catcode`\_\undtranscode
%---------------------------------------------------------------
\endinput
