% \iffalse
%% File: fxeff.dtx
%%
%% Package |fxeff| provides an user interface for the GeX
%% plugin |fxeff| of V\TeX. The plugin implements effects
%% such as slanting, cascading or fading.
%%
%% Copyright 2001 Heiko Oberdiek.
%%
%% It may be distributed under the conditions of the LaTeX Project Public
%% License, either version 1.2 of this license or (at your option) any
%% later version.  The latest version of this license is in
%%    http://www.latex-project.org/lppl.txt
%% and version 1.2 or later is part of all distributions of LaTeX
%% version 1999/12/01 or later.
%%
%% Bugs and improvements to the author <oberdiek@uni-freiburg.de>
%% or Micropress <support@micropress-inc.com> which develops
%% VTeX and the plugin fxeff. See also their homepage
%%   http://www.micropress-inc.com
%%
%<!none>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{fxeff}
%<driver>\ProvidesFile{fxeff.drv}
%<test>\ProvidesFile{testfx.tex}
%<!none>  [2001/07/19 v1.1
%<package>  Support for VTeX's fxeff GeX plugin (HO)]
%<driver>  Documentation driver file for fxeff package]
%<test>  Test file for fxeff package]
%<*driver>
\documentclass{ltxdoc}
\EnableCrossrefs
\CodelineIndex
\begin{document}
  \GetFileInfo{fxeff.sty}
  \title{Package fxeff}
  \author{Heiko Oberdiek\\
    Email: \texttt{oberdiek@uni-freiburg.de}}
  \date{processed \today}
  \maketitle
  \tableofcontents
  \DocInput{fxeff.dtx}
  \PrintIndex
\end{document}
%</driver>
% \fi
% \CheckSum{394}
%
% \MakeShortVerb{|}
%
% \DoNotIndex{\def,\edef,\gdef,\xdef,\global,\long,\let}
% \DoNotIndex{\relax,\begingroup,\endgroup}
% \DoNotIndex{\a,\b,\c,\x}
%
%    \begin{abstract}
%    Package |fxeff| provides an user interface for
%    the GeX plugin |fxeff| of V\TeX. The plugin
%    implements effects such as slanting, cascading or
%    fading.
%    \end{abstract}
%
% \section{Installation}
%    A 7.3+ V\TeX\ compiler is needed for running the plugin
%    |fxeff| that will be installed in the directory
%    |vtex/bin/gex/|.
%
%    The package is unpacked by compiling |fxeff.ins| with \TeX:
%    \begin{quote}
%      |tex fxeff.ins| \qquad or\\
%      |vlatex fxeff.ins|
%    \end{quote}
%    The package file |fxeff.sty| is then moved to
%    the direcory:
%    \begin{quote}
%      |texmf/tex/latex/fxeff/|
%    \end{quote}
%
% \section{User interface}
%    The package |fxeff| is loaded
%    like other \LaTeX\ packages:
%    \begin{quote}
%        |\usepackage{fxeff}|
%    \end{quote}
%
%    \DescribeMacro{\fxeffdefinecolor}
%    Because colors are given by rgb values, the V\TeX\ color
%    definitions of package |color| cannot be used, because
%    the colors have an other format. The package defines
%    the basic colors. Other colors can be defined by
%    |\fxeffdefinecolor|. For example:
%    \begin{quote}
%        |\fxeffdefinecolor{mycolor}[1 0 .5]|
%    \end{quote}
%    The rgb value of the color are given in square brackets,
%    separated by spaces unlike the |color| package.
%
%    \DescribeEnv{fxeff}
%    The environment |fxeff| applies an effect for the GeX plugin
%    |fxeff| to its contents. Spaces before or after are ignored.
%    An optional argument for the position can contain one of
%    the letters |b|, |c|, or |t| with a similar meaning of the
%    argument for the |tabular| environment. The default is |b|.
%
%    The effect and its parameters are given by the syntax of
%    package |keyval|. Options for all effects:
%    \newcommand*{\opt}[1]{\item[\texttt{#1}]}
%    \begin{description}
%    \opt{width\textrm{, }height}
%      As argument any TeX length can be given. The natural
%      sizes are given by |\width|, |\height|, |\depth|, and
%      |\totalheight|.
%    \opt{outline} Either of the outline options activates
%      the outline.
%    \opt{outlinecolor} The color is given as rgb values in
%      square brackets, separated by spaces (|[0 .8 .5]|),
%      or by name in sharp brackets (|<red>|). Default is
%      black.
%    \opt{outlinewidth}
%      The width of the outline.
%      The default is 1\,bp.
%    \opt{fillcolor}
%      One or several colors as rgb values in square
%      brackets, separated by spaces or in sharp brackes
%      by name, see option |outlinecolor|.
%    \opt{gradient} The gradient is either |h| or |v|. It affects
%      color, if several fillcolors are given, otherwise brightness.
%    \end{description}
%
%    All arguments for the effects have to be in the range
%    between zero and one without zero itself.
%    The following effects know one argument:
%    \begin{description}
%    \opt{SlantUp\textrm{/}SlantDown}
%      The parameter defines the raise relative to the text height.
%    \opt{FadeUp\textrm{/}FadeDown\textrm{/}FadeRight\textrm{/}FadeLeft}
%      The parameter sets the width of the top/bottom/right/left
%      relative to the bottom/top/left/right.
%    \end{description}
%
%    Two parameters are needed for the rest of the effect options:
%    \begin{description}
%    \opt{CascadeUp\textrm{/}CascadeDown}
%      The parameters define the leftmost and the rightmost parts
%      relative to the height of the contents.
%    \opt{TriangleUp\textrm{/}TriangleDown}
%      The first parameter specifies the height relative to the text
%      height, the second parameter the location of the triangle's top
%      relative to the text width.
%    \opt{ChevronUp\textrm{/}ChevronDown}
%      The first parameter defines the relative height of
%      the chevron, the second the relative location of the top.
%    \opt{Stop} The first parameter defines the leftmost and
%      rightmost relative height, the second defines the
%      relative width of the left and right growing area
%      and should be less than 0.5 therefore.
%    \end{description}
%
%    The test file |testfx.tex| shows some examples of use.
%
% \StopEventually{}
%
% \section{Implementation}
%
% \subsection{Help macros and resource allocation}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
%    \begin{macro}{\fx@special}
%    The macro |\fx@special| takes a PostScript string
%    argument and calls GeX by a |\special| command.
%    \begin{macrocode}
\newcommand*{\fx@special}[1]{\special{pS:#1}}
%    \end{macrocode}
%    \end{macro}
%
%    This package supports the plugin |fxeff| for GeX,
%    therefore the plugin is loaded here:
%    \begin{macrocode}
\fx@special{(fxeff).extend}
%    \end{macrocode}
%
%    \begin{macro}{\@ReturnAfterFi}
%    The macro |\@ReturnAfterFi| helps to make recursive
%    macros tail recursive.
%    \begin{macrocode}
\long\def\@ReturnAfterFi#1\fi{\fi#1}
%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\fx@toks}
%    The token register |\fx@toks| is used by the plugin.
%    \begin{macrocode}
\newtoks\fx@toks
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\fx@toksno}
%    The register number is stored in |\fx@toksno|.
%    \begin{macrocode}
\begingroup
  \def\x#1#2#3#4#5#6\@nil{#6}%
  \xdef\fx@toksno{\expandafter\x\meaning\fx@toks\@nil}
\endgroup
%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\fx@box}
%    The box will be used later by the |fxeff| environment.
%    \begin{macrocode}
\newsavebox\fx@box
%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\iffx@outline}
%    This switch stored, whether the user has specified
%    at least one of the outline options.
%    \begin{macrocode}
\newif\iffx@outline
%    \end{macrocode}
%    \end{macro}
%
% \subsection{Colors}
%
%    \begin{macro}{\fx@define@colors}
%    Macro |\fx@define@colors| stores in the first argument
%    the parsed colors in the second argument.
%    \begin{macrocode}
\def\fx@define@colors#1#2{%
  \let\fx@colorlist\@empty
  \fx@scancolors#2\@nil
  \let#1\fx@colorlist
}
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\fx@scancolors}
%    If the argument is not empty, macro |\fx@scancolors|
%    calls |\fx@@scancolors| that reads in a color.
%    \begin{macrocode}
\def\fx@scancolors#1\@nil{%
  \ifx\\#1\\%
  \else
    \@ReturnAfterFi{%
      \fx@@scancolors#1\@nil
    }%
  \fi
}
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\fx@@scancolors}
%    This macro |\fx@@scancolors| looks for a color
%    specification, either rgb values or a name.
%    \begin{macrocode}
\def\fx@@scancolors#1{%
  \ifx[#1\relax
    \expandafter\fx@getcolorrgb
  \else
    \@ReturnAfterFi{%
      \ifx<#1\relax
        \expandafter\fx@getcolorname
      \else
        \PackageError{fxeff}{Color parse error}\@ehc
      \fi
    }%
  \fi
}
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\fx@getcolorrgb}
%    Macro |\fx@getcolorrgb| reads in a rgb tupel and appends
%    the color list |\fx@colorlist|.
%    \begin{macrocode}
\def\fx@getcolorrgb#1 #2 #3]{%
  \begingroup
    \fx@colorpart\a{#1}%
    \fx@colorpart\b{#2}%
    \fx@colorpart\c{#3}%
    \edef\x{\endgroup
      \def\noexpand\fx@colorlist{\fx@colorlist\a\space\b\space\c;}%
    }%
  \x
  \fx@scancolors
}
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\fx@colorpart}
%    Macro |\fx@colorpart| ensures that the second argument
%    is a rgb value in the allowed range and stores the valid
%    value in the first argument.
%    \begin{macrocode}
\def\fx@colorpart#1#2{%
  \begingroup
    \dimen@=#2pt\relax
    \ifdim\dimen@<0pt%
      \PackageWarning{fxeff}{Negative rgb value not allowed}%
      \dimen@=0pt\relax
    \fi
    \ifdim\dimen@>1pt%
      \PackageWarning{fxeff}{Rgb value too large}%
      \dimen@=1pt\relax
    \fi
    \edef\x{\endgroup
      \def\noexpand#1{\strip@pt\dimen@}%
    }%
  \x
}
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\fx@getcolorname}
%    This macro |\fx@getcolorname| reads in a color specification
%    by name and appends the color list |\fx@colorlist|.
%    \begin{macrocode}
\def\fx@getcolorname#1>{%
  \@ifundefined{fx@color@#1}{%
    \PackageWarning{fxeff}{Color `#1' undefined}%
  }{%
    \edef\fx@colorlist{\fx@colorlist\@nameuse{fx@color@#1};}%
  }%
  \fx@scancolors
}
%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\fxeffdefinecolor}
%    Similar to |\definecolor| the user macro |\fxeffdefinecolor|
%    defines a color by name. Only the rgb color model is supported.
%    The rgb values are put in square brackets and separated by
%    spaces unlike the |color| package.
%    \begin{macrocode}
\def\fxeffdefinecolor#1[#2]{%
  \@namedef{fx@color@#1}{#2}%
}
%    \end{macrocode}
%    \end{macro}
%    Now we can define some basic colors:
%    \begin{macrocode}
\fxeffdefinecolor{black}[0 0 0]
\fxeffdefinecolor{white}[1 1 1]
\fxeffdefinecolor{red}[1 0 0]
\fxeffdefinecolor{green}[0 1 0]
\fxeffdefinecolor{blue}[0 0 1]
\fxeffdefinecolor{yellow}[1 1 0]
\fxeffdefinecolor{magenta}[1 0 1]
\fxeffdefinecolor{cyan}[0 1 1]
%    \end{macrocode}
%
% \subsection{Options}
%
%    For an intuitive syntax package |keyval| is used.
%    \begin{macrocode}
\RequirePackage{keyval}
%    \end{macrocode}
%
%    \begin{macro}{\fx@define@length}
%    The width and height, or the outline width are given
%    in bp for the plugin |fxeff|.
%    This macro |\fx@define@length| defines a macro that
%    creates an options that processes a length as argument
%    and converts the length in bp.
%    \begin{macrocode}
\def\fx@define@length#1#2{%
  \define@key{fxeff}{#1}{%
    \begingroup
      \dimen@=##1\relax
      \dimen@=.99626401\dimen@
      \edef\x{\endgroup
        \def\expandafter\noexpand\csname fx@#1\endcsname
          {\strip@pt\dimen@}%
      }%
    \x
    #2%
  }%
}
%    \end{macrocode}
%    \end{macro}
%    Now the length options are defined:
%    \begin{macrocode}
\fx@define@length{width}{}
\fx@define@length{height}{}
\fx@define@length{outlinewidth}{\fx@outlinetrue}
%    \end{macrocode}
%
%    The other options follow:
%    \begin{macrocode}
\define@key{fxeff}{outlinecolor}{%
  \fx@outlinetrue
  \fx@define@colors\fx@outlinecolor{#1}%
}
\define@key{fxeff}{outline}[]{\fx@outlinetrue}
\define@key{fxeff}{fillcolor}{%
  \fx@define@colors\fx@fillcolor{#1}%
}
\define@key{fxeff}{gradient}{%
  \def\fx@gradient{#1}%
}
%    \end{macrocode}
%
%    \begin{macro}{\fx@define@effect@A}
%    The effects take one or two arguments.
%    So the next macros define commands that
%    define options with one or two arguments.
%    \begin{macrocode}
\def\fx@define@effect@A#1{%
  \define@key{fxeff}{#1}{%
    \edef\fx@effect{#1}%
    \fx@paramdef{A}{##1}%
    \let\fx@param@B\relax
  }%
}
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\fx@define@effect@B}
%    And the macro for two effect arguments:
%    \begin{macrocode}
\def\fx@define@effect@B#1{%
  \define@key{fxeff}{#1}{%
    \edef\fx@effect{#1}%
    \fx@paramsplit##1\@nil
  }%
}
%    \end{macrocode}
%    \end{macro}
%
%    \begin{macro}{\fx@paramdef}
%    Macro |\fx@paramdef| validates a parameter, a number
%    in the rage between zero and one.
%    \begin{macrocode}
\def\fx@paramdef#1#2{%
  \begingroup
    \dimen@=#2pt\relax
    \ifdim\dimen@>0pt%
    \else
      \PackageWarning{fxeff}{Value must be greater than zero}%
      \dimen@=1sp\relax
    \fi
    \ifdim\dimen@>1pt%
      \PackageWarning{fxeff}{Value too large}%
      \dimen@=1pt\relax
    \fi
    \edef\x{\endgroup
      \def\expandafter\noexpand\csname fx@param@#1\endcsname{%
        \strip@pt\dimen@
      }%
    }%
  \x
}
%    \end{macrocode}
%    \end{macro}
%    \begin{macro}{\fx@paramsplit}
%    The macro |\fx@paramsplit| extracts the two parameters
%    out of one option argument.
%    \begin{macrocode}
\def\fx@paramsplit#1,#2\@nil{%
  \fx@paramdef{A}{#1}%
  \fx@paramdef{B}{#2}%
}
%    \end{macrocode}
%    \end{macro}
%
%    The options for effects:
%    \begin{macrocode}
\fx@define@effect@A{SlantUp}
\fx@define@effect@A{SlantDown}
\fx@define@effect@A{FadeUp}
\fx@define@effect@A{FadeDown}
\fx@define@effect@A{FadeRight}
\fx@define@effect@A{FadeLeft}
\fx@define@effect@B{CascadeUp}
\fx@define@effect@B{CascadeDown}
\fx@define@effect@B{TriangleUp}
\fx@define@effect@B{TriangleDown}
\fx@define@effect@B{ChevronUp}
\fx@define@effect@B{ChevronDown}
\fx@define@effect@B{Stop}
%    \end{macrocode}
%
%    \begin{environment}{fxeff}
%    The content of the environment |fxeff| is stored in the
%    box |\fx@box| that is positioned according to the
%    optional positional argument. The properties of the
%    effect for the plugin |fxeff| is stored in a token
%    register that will be read by the plugin.
%    \begin{macrocode}
\newenvironment{fxeff}[2][b]{%
  \def\fx@pos{#1}%
  \@ifundefined{fx@pos@\fx@pos}{%
    \PackageWarning{fxeff}{Unknown positional parameter `\fx@pos'}%
    \def\fx@pos{b}%
  }{}%
  \def\fx@user{#2}%
  \begin{lrbox}{\fx@box}%
  \ignorespaces
}{%
  \unskip
  \end{lrbox}%
  \def\width{\wd\fx@box}%
  \def\height{\ht\fx@box}%
  \def\depth{\dp\fx@box}%
  \let\totalheight\@ovri
  \totalheight\height
  \advance\totalheight\depth
  % default settings
  \setkeys{fxeff}{%
    width=\width,height=\height,%
    outlinecolor=[0 0 0],outlinewidth={1bp},%
    fillcolor=[0 0 0],%
    gradient={},%
  }%
  \fx@outlinefalse
  \let\fx@effect\@empty
  % user settings
  \def\x##1\@nil{\setkeys{fxeff}{##1}}%
  \expandafter\x\fx@user\@nil
  \ifx\fx@effect\@empty
    \PackageError{fxeff}{Missing effect}{%
      See package `fx' documentation for a list of effects.%
    }%
  \fi
  \edef\x{%
    \fx@width\space\fx@height;%
    \iffx@outline\fx@outlinecolor\fx@outlinewidth\fi;%
    (\fx@fillcolor)\fx@gradient;%
    \fx@effect;%
    \fx@param@A
    \ifx\fx@param@B\relax\else\space\fx@param@B\fi;%
  }%
  \wd\fx@box=\fx@width bp\relax
  \ht\fx@box=\fx@height bp\relax
  \leavevmode
  $\csname fx@pos@\fx@pos\endcsname{%
    \hrule height 0pt\relax
    \hbox{%
      \raisebox{\ht\fx@box}[\ht\fx@box][0pt]{%
        \fx@special{%
          save currentpoint newpath%
          /show{true charpath}def%
          /fill{}def%
          /gsave{}def%
          /grestore{}def%
          /newpath{}def%
        }%
        \usebox\fx@box
        \fx@special{%
          moveto %
          false \fx@toksno(\x).tkwrite %
          \fx@toksno\space pathtest
          restore%
        }%
      }%
    }%
  }$%
}
%    \end{macrocode}
%    \end{environment}
%
%    Help macros for positioning the box in environment |fxexx|.
%    \begin{macrocode}
\let\fx@pos@b\vbox
\let\fx@pos@t\vtop
\let\fx@pos@c\vcenter
%</package>
%    \end{macrocode}
%
% \section{Test file}
%
%    \begin{macrocode}
%<*test>
\documentclass[12pt,a4paper]{article}
\usepackage{fxeff}
\setlength{\parindent}{0pt}
\begin{document}
\newcommand{\TEXT}{\textbf{SOME TEXT}}

SlantUp: \begin{fxeff}[c]{
  width=300bp, height=100bp,
  fillcolor=<red><yellow><green><cyan><blue>[.5 0 .5]<magenta>,
  gradient=h,
  SlantUp=.7
}\TEXT\end{fxeff}

SlantDown: \begin{fxeff}[c]{
  width=300bp, height=100bp,
  fillcolor=[.5 0 0],
  gradient=h,
  SlantDown=.5
}\TEXT\end{fxeff}

CascadeUp: \begin{fxeff}[c]{
  width=200bp, height=200bp,
  outlinecolor=[0 0 .7], outlinewidth=2bp,
  fillcolor=[0 0 .8],
  CascadeUp={.75, .4}
}\TEXT\end{fxeff}

CascadeDown: \begin{fxeff}[c]{
  width=300bp, height=150bp,
  CascadeDown={1, .5}
}\TEXT\end{fxeff}

TriangleUp (b): \begin{fxeff}[b]{
  width=200bp, height=80bp,
  outline,
  fillcolor=[.8 .8 .8],
  TriangleUp={.35, .5}
}\TEXT\end{fxeff}

TriangleDown (t): \begin{fxeff}[t]{
  width=200bp, height=100bp,
  fillcolor=[0 .8 0][0 0 .8],
  gradient=h,
  TriangleDown={.5, .5}
}\TEXT\end{fxeff}

ChevronUp: \begin{fxeff}[c]{
  width=250bp, height=100bp,
  fillcolor=[0 .8 .8],
  ChevronUp={.5, .3}
}\TEXT\end{fxeff}

ChevronDown: \begin{fxeff}[c]{
  width=150bp, height=100bp,
  fillcolor=[.8 0 0][.8 0 1],
  gradient=v,
  ChevronDown={.75, .5}
}\TEXT\end{fxeff}

FadeUp: \begin{fxeff}[c]{
  width=200bp, height=50bp,
  fillcolor=[0 0 .8][.8 0 1],
  gradient=v,
  FadeUp=.6
}\TEXT\end{fxeff}

FadeDown: \begin{fxeff}[c]{
  width=200bp, height=50bp,
  outline,
  FadeDown=.85
}\TEXT\end{fxeff}

FadeRight: \begin{fxeff}[c]{
  width=250bp, height=70bp,
  fillcolor=[.8 0 0][.5 .5 0],
  gradient=v,
  FadeRight=.3
}\TEXT\end{fxeff}

FadeLeft: \begin{fxeff}[c]{
  width=250bp, height=70bp,
  outlinewidth=.5bp,
  fillcolor=[.5 .5 .5]<black>[.5 .5 .5]<black>,
  gradient=v,
  FadeLeft=.6
}\TEXT\end{fxeff}

Stop: \begin{fxeff}[c]{
  width=250bp, height=50bp,
  outlinewidth=.5bp,
  fillcolor=[0 .7 .7],
  Stop={.6, .33}
}\TEXT\end{fxeff}
\end{document}
%</test>
%    \end{macrocode}
%
% \Finale
%
\endinput
