colo-ini.tex / last modification: 2007-09-17 12:39
%D \module
%D   [       file=colo-ini,
%D        version=1997.04.01,
%D          title=\CONTEXT\ Color Macros,
%D       subtitle=Initialization,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\writestatus{loading}{Context Color Macros / initialization}

%D Possible optimization: store level in mark instead of name

\unprotect

%D Color support is not present in \TEX. Colorful output can
%D however be accomplished by using specials. This also means
%D that this support depends on the \DVI\ driver used. At the
%D moment this module was written, still no decent standard on
%D color specials has been agreed upon. We therefore decided to
%D implement a mechanism that is as independant as possible of
%D drivers.
%D
%D Color support shares with fonts that is must be implemented
%D in a way that permits processing of individual \DVI\ pages.
%D Furthermore it should honour grouping. The first condition
%D forces us to use a scheme that keeps track of colors at
%D page boundaries. This can be done by means of \TEX's
%D marking mechanism (\type{\mark}).
%D
%D When building pages, \TEX\ periodically looks at the
%D accumulated typeset contents and breaks the page when
%D suitable. At that moment, control is transfered to the
%D output routine. This routine takes care of building the
%D pagebody and for instance adds headers and footers. The page
%D can be broken in the middle of some colored text, but
%D headers and footers are often in black upon white or
%D background. If colors are applied there, they definitely
%D are used local, which means that they don't cross page
%D borders.
%D
%D Boxes are handled as a whole, which means that when we
%D apply colors inside a box, those colors don't cross page
%D boundaries, unless of course boxes are split or unboxed.
%D Especially in interactive texts, colors are often used in
%D such a local way: in boxes (buttons and navigational tools)
%D or in the pagebody (backgrounds).
%D
%D So we can distinguish local colors, that don't cross
%D pages from global colors, of which we can end many pages
%D later. The color macros will treat both types in a different
%D way, thus gaining some speed.
%D
%D This module also deals with gray scales. Because similar
%D colors can end up in the same gray scale when printed in
%D black and white, we also implement a palet system that deals
%D with these matters. Because of fundamental differences
%D between color and gray scale printing, in \CONTEXT\ we also
%D differ between these. For historic reasons |<|we first
%D implemented gray scales using patterns of tiny periods|>|
%D and therefore called them {\em rasters}. So don't be
%D surprised if this term shows up.

\startmessages  dutch  library: colors
  title: kleur
      1: systeem -- is globaal actief
      2: systeem -- is lokaal actief
      3: -- is niet gedefinieerd --
      4: systeem -- wordt geladen
      5: onbekend systeem --
      6: palet -- is beschikbaar
      7: palet -- is niet beschikbaar
      8: specificatie -- bij -- wordt zwart
      9: -- kleurruimte wordt niet ondersteund
     10: -- kleurruimte wordt ondersteund
     11: kleur wordt vertaald in grijs
     12: -- is geregistreerd
\stopmessages

\startmessages  english  library: colors
  title: color
      1: system -- is global activated
      2: system -- is local activated
      3: -- is not defined --
      4: system -- is loaded
      5: unknown system --
      6: palette -- is available
      7: palette -- is not available
      8: specification -- at color -- becomes black
      9: -- color space is not supported
     10: -- color space is supported
     11: color is converted to gray
     12: -- is registered
\stopmessages

\startmessages  german  library: colors
  title: farbe
      1: system -- ist global aktiviert
      2: system -- ist lokal aktiviert
      3: -- ist undefiniert --
      4: system -- ist geladen
      5: unbekanntes System --
      6: palette -- ist verfuegbar
      7: palette -- ist nicht verfuegbar
      8: Spezifikation -- bei Farbe -- wird schwarz
      9: -- Farbraum wird nicht unterstuetzt
     10: -- Farbraum wird unterstuetzt
     11: Farbe wird in Grau umgewandelt
     12: -- is registered
\stopmessages

\startmessages  czech  library: colors
  title: barva
      1: system -- je globalne aktivovana
      2: system -- je lokalne activovana
      3: -- neni definovana --
      4: system -- je nacten
      5: neznamy system --
      6: palette -- je k dispozici
      7: palette -- neni k dispozici
      8: specifikace -- v barve -- bude cerna
      9: -- prostor barev neni podporovan
     10: -- prostor barev je podporovan
     11: barva je prevedena na sed
     12: -- is registered
\stopmessages

\startmessages  italian  library: colors
  title: colore
      1: sistema -- attivato globalmente
      2: sistema -- attivato localmente
      3: -- non definito --
      4: sistema -- caricato
      5: sistema -- sconosciuto
      6: tavolozza -- resa disponibile
      7: tavolozza -- non disponibile
      8: specifica -- del colore -- convertita in nero
      9: spazio dei colori -- non supportato
     10: spazio dei colori -- supportato
     11: il colore ø convertito in grigio
     12: -- is registered
\stopmessages

\startmessages  norwegian  library: colors
  title: farge
      1: system -- er aktivert globalt
      2: system -- er aktivert lokalt
      3: -- er udefinert --
      4: system -- er lest inn
      5: ukjent system --
      6: palett -- er tilgjengelig
      7: palett -- er ikke tilgjengelig
      8: spesifikasjon -- for farge -- gir kun svart
      9: -- fargerom er ikke støttet
     10: -- fargerom er støttet
     11: fargen vil bli vist som grø
     12: -- is registered
\stopmessages

\startmessages  romanian  library: colors
  title: culori
      1: sistem -- este activata global
      2: sistem -- este activata local
      3: -- nu este definita --
      4: sistem -- este incarcata
      5: sistem -- necunoscuta
      6: paleta -- este disponibila
      7: palette -- nu este disponibila
      8: specificatia -- la culoarea -- devine neagra
      9: spatiul de culoare -- nu este suportat
     10: spatiul de culoare -- este suportat
     11: culoarea este convertita la gri
     12: -- is registered
\stopmessages

\startmessages  french  library: colors
  title: couleurs
      1: le système -- est globalement activé
      2: le système -- est localement activé
      3: -- n'est pas défini --
      4: le système -- est chargé
      5: système -- inconnu
      6: la palette -- est disponible
      7: le palette -- n'est pas disponible
      8: la spécification -- de la couleur -- devient noire
      9: l'espace de couleur -- n'est pas supporté
     10: -- l'espace de couleur est supporté
     11: la couleur est convertie en niveau de gris
     12: -- est enregistré
\stopmessages

%D We use a couple of local registers. That way we don't have
%D to group when converting colors. By the way, this is not
%D really faster. We can sqeeze half a second runtime for 50K
%D switches on a 1G machine, but the macros will become rather
%D ugly then. To mention one such improvement: no colon
%D after the key character (.25 sec).

\newdimen\colordimen
\newcount\colorcount

%D \macros
%D   {definecolor}
%D
%D We will enable users to specify colors in \cap{RGB} and
%D \cap{CMYK} color spaces or gray scales using
%D
%D \showsetup{definecolor}
%D
%D For example:
%D
%D \starttyping
%D \definecolor [SomeKindOfRed] [r=.8,g=.05,b=.05]
%D \stoptyping
%D
%D Such color specifications are saved in a macro in the
%D following way:
%D
%D \starttyping
%D \setvalue{\??cr name}{R:r:g:b}
%D \setvalue{\??cr name}{C:c:m:y:k}
%D \setvalue{\??cr name}{S:s}
%D \stoptyping
%D
%D Gray scales are specified with the \type{s} parameter,
%D where the \type {s} is derived from {\em screen}.
%D
%D Starting with \PDF\ 1.4 (2001) \CONTEXT\ supports
%D transparent colors. The transparency factor is represented
%D by a \type {t} and the transparency method by an \type {a}
%D (alternative). Later we will implement more control
%D (probably by symbolic methods. So, currently the data is
%D stored as follows:
%D
%D \starttyping
%D \setvalue{\??cr name}{R:r:g:b:a:t}
%D \setvalue{\??cr name}{C:c:m:y:k:a:t}
%D \setvalue{\??cr name}{S:s:a:t}
%D \stoptyping

% beware: comparisons asked/current on name, not value

\newif\iffreezecolors  \freezecolorsfalse

\let\colorlist       \empty
\let\currentspotcolor\empty

\def\@@cl@@z{0}
\def\@@cl@@o{1}

% \def\@@resetcolorparameters
%   {\let\@@cl@@r\@@cl@@z\let\@@cl@@g\@@cl@@z\let\@@cl@@b\@@cl@@z
%    \let\@@cl@@c\@@cl@@z\let\@@cl@@m\@@cl@@z\let\@@cl@@y\@@cl@@z\let\@@cl@@k\@@cl@@z
%    \let\@@cl@@s\@@cl@@z\let\@@cl@@p\@@cl@@o
%    \let\@@cl@@t\@@cl@@z\let\@@cl@@a\@@cl@@z
%    \let\@@cl@@h\empty  \let\@@cl@@n\empty}

% r g b   : rbg
% c m y k : cmyk
% s       : gray
% p n d f : spot
% h       : hexadecimal
% t a     : transparency
% e       : equivalent (spotcolors)

\def\@@resetcolorparameters
  {\let\@@cl@@r\@@cl@@z \let\@@cl@@g\@@cl@@z \let\@@cl@@b\@@cl@@z
   \let\@@cl@@c\@@cl@@z \let\@@cl@@m\@@cl@@z \let\@@cl@@y\@@cl@@z \let\@@cl@@k\@@cl@@z
   \let\@@cl@@s\@@cl@@z
   \let\@@cl@@p\@@cl@@o \let\@@cl@@n\empty \let\@@cl@@d\empty \let\@@cl@@f\@@cl@@o
   \let\@@cl@@h\empty
   \let\@@cl@@e\empty
   \let\@@cl@@t\@@cl@@z \let\@@cl@@a\@@cl@@z}

\@@resetcolorparameters

\def\@@cl@@A{\@@cl@@a} % a hook for symbolic conversion, see below

%D Handling a few nested \type{\cs}'s is no problem (\type
%D {\@EA\@EAEAEA\@EA}) but we need a full expansion, so I
%D tried one of the fully expandable primitives using a sort
%D of delimited thing. I tried \type {\number} first, but this
%D does not work, but \type {\romannumeral} does. Actually,
%D \type{\romannumeral0} returns nothing, so it's a perfect
%D candidate for this kind of hackery. This reminds me that I
%D have to look into David Kastrup's Euro\TeX\ 2002 article
%D because he is using \type {\romannumeral} for loops
%D (repetitive \quote {m} stuff).

% \def\x{\y}\def\y{\z}\def\z{0:1:1:1}
%
% \def\bla #1:#2:#3\end{}
%
% \@EA\bla\romannumeral\x\end

\def\colorXpattern{0S:\@@cl@@z:\@@cl@@z:\@@cl@@z}
\def\colorZpattern{0S:\@@cl@@z:\@@cl@@A:\@@cl@@t}
\def\colorSpattern{0S:\@@cl@@s:\@@cl@@A:\@@cl@@t}
\def\colorCpattern{0C:\@@cl@@c:\@@cl@@m:\@@cl@@y:\@@cl@@k:\@@cl@@A:\@@cl@@t}
\def\colorRpattern{0R:\@@cl@@r:\@@cl@@g:\@@cl@@b:\@@cl@@A:\@@cl@@t}

%def\colorPpattern{0P:\@@cl@@n:\@@cl@@p:\@@cl@@A:\@@cl@@t}

\def\colorPpattern{0P:\@@cl@@n:\@@cl@@f:\@@cl@@d:\@@cl@@p:\@@cl@@A:\@@cl@@t}

%D The extra 0 catches empty colors specs (needed for the
%D \type {\MPcolor} and \type {\PDFcolor} conversion (\type
%D {\@@cr} equals \type {\relax}!).

\def\handlecolorwith#1{\@EA#1\romannumeral0}

%D Next comes the main definition macro.

\def\definecolor      {\dodoubleargument\dodefinecolor}
\def\defineglobalcolor{\dodoubleargument\dodefineglobalcolor}
\def\definenamedcolor {\dodoubleargument\dodefinenamedcolor}

\def\dodefinecolor      {\dododefinecolor\relax   \setvalue \setevalue1}
\def\dodefineglobalcolor{\dododefinecolor\doglobal\setgvalue\setxvalue1}
\def\dodefinenamedcolor {\dododefinecolor\doglobal\setvalue \setevalue0}

\def\dododefinecolor#1#2#3#4[#5][#6]% #2==set(g)value #3==set[e|x]value -- maybe add fake [#7] here
  {#1\addtocommalist{#5}\colorlist % optional
   \doifassignmentelse{#6}
     {\@@resetcolorparameters
      \getparameters[\??cl @@][#6]%
      \ifx\@@cl@@h\empty
        \doifelse{\@@cl@@r\@@cl@@g\@@cl@@b}{\@@cl@@z\@@cl@@z\@@cl@@z}
          {\doifelse{\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k}{\@@cl@@z\@@cl@@z\@@cl@@z\@@cl@@z}
             {\doifelse\@@cl@@s\@@cl@@z
                {\showmessage\m!colors8{{[#6]},#5}%
                 #3{\??cr#5}{\colorZpattern}}
                {#3{\??cr#5}{\colorSpattern}}}
             {#3{\??cr#5}{\colorCpattern}}}
          {#3{\??cr#5}{\colorRpattern}}%
      \else
        \setxvalue{\??cr#5}{\colorHpattern}%
      \fi
      % new: e=external spot color name
      \ifx\@@cl@@e\empty \else
        \doregisterspotcolorname{#5}\@@cl@@e
      \fi}
     {\doifelsenothing\currentpalet
         \donefalse
        {\doifdefinedelse{\??cr\currentpalet#6}\donetrue\donefalse}%
      \ifdone
        \doifnot{#5}{#6}
           {#2{\??cr#5}{\paletcolorspec{#6}}}%
      \else
        \doifdefinedelse{\??cr#6}
           {\doifelse{#5}{#6}
              {% this way we can freeze \definecolor[somecolor][somecolor]
               % and still prevent cyclic definitions
               \iffreezecolors#3{\??cr#5}{\csname\??cr#6\endcsname}\fi}
              {\iffreezecolors\@EA#3\else\@EA#2\fi{\??cr#5}{\csname\??cr#6\endcsname}}}
           {\showmessage\m!colors3{#5 (def)}}%
       \fi}%
   \ifcase#4\or
     \unexpanded#2{#5}{\switchtocolor[#5]}% \unexpanded toegevoegd
   \fi}

\def\paletcolorspec#1%
  {\csname\??cr\currentpalet#1\endcsname}

%D Hex color support is not enabled by default. You need to say \type
%D {\setupcolor [hex]} to get this working.

\ifx\colorHpattern\undefined \let\colorHpattern\colorZpattern \fi

%D New and experimental.

\let\allspotcolors    \empty
\let\usedspotcolors   \empty
\let\usedcolorchannels\empty

\def\definespotcolor % [name] [color] [p=,t=,a=]
  {\dotripleempty\dodefinespotcolor}

\def\dodefinespotcolor[#1][#2][#3]% todo: always global
  {\doifnot{#1}{#2}
     {\@@resetcolorparameters
\doglobal\addtocommalist{#1}\colorlist % optional
      \edef\@@cl@@n{#2}%
      \getparameters[\??cl @@][#3]%
      \doifnothing\@@cl@@p{\let\@@cl@@p\!!plusone}%
      \ifx\@@cl@@e\empty \else
        \doregisterspotcolorname{#2}\@@cl@@e
      \fi
      \doglobal\addtocommalist{#2}\allspotcolors
      \setxvalue{\??cr#1}{\colorPpattern}% was \setevalue
      \setgvalue{#1}{\switchtocolor[#1]}}} % was \setvalue

\def\registerusedspotcolors
  {\ifx\allspotcolors\empty \else
     \bgroup
     \let\usedspotcolors\empty
     \def\docommand##1%
       {\doifdefined{\??cs##1}{\addtocommalist{##1}\usedspotcolors}}%
     \processcommacommand[\allspotcolors]\docommand
     \savecurrentvalue\usedspotcolors\usedspotcolors
     \egroup
   \fi}

\def\registerusedcolorchannels
  {\bgroup
   \doifdefinedelse{\??cs c}
     {\def\usedcolorchannels{c,m,y,k}}%
     {\let\usedcolorchannels\empty}%
   \doifdefined{\??cs r}
     {\addtocommalist{r,g,b}\usedcolorchannels}%
   \doifdefined{\??cs s}
     {\ExpandBothAfter\doifnotinset{k}\usedcolorchannels
        {\addtocommalist{s}\usedcolorchannels}}%
   \savecurrentvalue\usedcolorchannels\usedcolorchannels
   \egroup}

\prependtoks
  \registerusedspotcolors
  \registerusedcolorchannels
\to \everylastshipout

\def\registerusedspotcolor#1%
  {\global\@EA\chardef\csname\??cs#1\endcsname\zerocount}

%D On top of spotcolors, we define multitone colors. You'd better know
%D what you're doing because invalid definitions will lead to invalid
%D documents (i.e.\ resources).

% \definecolor [darkblue]   [c=.5,m=.5]
% \definecolor [darkyellow] [y=.5]
%
% \definemultitonecolor [whatever] [darkblue=.5,darkyellow=.5] [c=.25,m=.25,y=.25] [a=1,t=.5]
% \definemultitonecolor [another]  [darkblue=.5,darkyellow=.5] [c=.25,m=.25,y=.25]

\def\definemultitonecolor
  {\doquadrupleempty\dodefinemultitonecolor}

\def\dodefinemultitonecolor[#1][#2][#3][#4]%
  {\let\@@cl@@cl@@D\empty % n's
   \let\@@cl@@cl@@P\empty % p's
   \let\@@cl@@cl@@N\empty % name
   \scratchcounter\zerocount
   \processcommacommand[#2]\dododefinemultitonecolor
   \bgroup
     \lccode`\.=`\_%
     \lccode`\,=`\_%
     \lccode`\:=`\_%
     \lccode`\;=`\_%
     \lccode`\+=`\_%
     \lccode`\-=`\_%
     \lccode`\*=`\_%
     \lccode`\/=`\_%
%      \lccode`\_=`\_%
     % not needed, other attribute in driver:
     %
     % \@@resetcolorparameters
     % \getparameters[#4]%
     % \ifx\@@cl@@t\@@cl@@z\else
     %   \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\@@cl@@t_\@@cl@@a}%
     % \fi
     \lowercase\@EA{\@EA\xdef\@EA\@@cleancolor\@EA{\@@cl@@cl@@N}}%
   \egroup
   \setxvalue{\??cl\@@cleancolor\s!check}{\noexpand\docheckmultitonecolor{\@@cl@@cl@@D}}%
   \expanded{\defineglobalcolor[\@@cleancolor][#3,#4]}%
   \expanded{\definespotcolor[#1][\@@cleancolor][#4,f=\the\scratchcounter,p={\@@cl@@cl@@P},d={\@@cl@@cl@@D}]}}

\def\docheckmultitonecolor#1%
  {\flushatshipout
     {\let\checkmultitonecolor\gobbleoneargument
      \def\docommand##1{\hbox{\definecolor[\s!dummy-100][##1][p=1]\color[\s!dummy-100]}}%
      \processcommalist[#1]\docommand}}

\def\checkmultitonecolor#1%
  {\csname\??cl#1\s!check\endcsname\letgvalue{\??cl#1\s!check}\relax}

\def\dodefinespotcolor[#1][#2][#3]% todo: always global (REDEFINED)
  {\doifnot{#1}{#2}
     {\@@resetcolorparameters
\doglobal\addtocommalist{#1}\colorlist % optional
      \edef\@@cl@@n{#2}%
      \getparameters[\??cl @@][#3]%
      \doifnothing  \@@cl@@p{\let\@@cl@@p\!!plusone}%
      \doifsomething\@@cl@@e{\doregisterspotcolorname{#2}\@@cl@@e}%
      \doglobal\addtocommalist{#2}\allspotcolors
      \setxvalue{\??cr#1}{\colorPpattern}% was \setevalue
      \setgvalue{#1}{\switchtocolor[#1]}}}% was \setvalue

\def\dododefinemultitonecolor#1%
  {\advance\scratchcounter\plusone
   \splitstring#1\at=\to\!!stringa\and\!!stringb
   \ifx\@@cl@@cl@@D\empty
     \let\@@cl@@cl@@D\!!stringa
     \let\@@cl@@cl@@P\!!stringb
     \normalizecolor\!!stringb
     \edef\@@cl@@cl@@N{\!!stringa_\!!stringb}%
   \else
     \edef\@@cl@@cl@@D{\@@cl@@cl@@D,\!!stringa}%
     \edef\@@cl@@cl@@P{\@@cl@@cl@@P,\!!stringb}%
     \normalizecolor\!!stringb
     \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\!!stringa_\!!stringb}%
   \fi}

% \def\dododefinemultitonecolor#1% a/b safe
%   {\advance\scratchcounter\plusone
%    \splitstring#1\at=\to\@@cl@@one\and\@@cl@@two
%    \ifx\@@cl@@cl@@D\empty
%      \let\@@cl@@cl@@D\@@cl@@one
%      \let\@@cl@@cl@@P\@@cl@@two
%      \normalizecolor\@@cl@@two
%      \edef\@@cl@@cl@@N{\@@cl@@one_\@@cl@@two}%
%    \else
%      \edef\@@cl@@cl@@D{\@@cl@@cl@@D,\@@cl@@one}%
%      \edef\@@cl@@cl@@P{\@@cl@@cl@@P,\@@cl@@two}%
%      \normalizecolor\@@cl@@two
%      \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\@@cl@@one_\@@cl@@two}%
%    \fi}

%D We now redefine the color definition macro so that you
%D can define both normal and spotcolors.

%D This messy method will become obsolete in mkiv.

\def\definecolor
  {\dotripleempty\dodefinewhatevercolor}

\def\dodefinewhatevercolor[#1][#2][#3]%
  {\ifthirdargument
     \dodefinespotcolor[#1][#2][#3]% this is the prefered method !
   \else
     \dodefinecolor[#1][#2]%
   \fi}

%D The names of colors are stored in a comma separated list
%D only for the purpose of showing them with \type {\showcolor}.
%D
%D \startbuffer
%D \definecolor [SomeKindOfRed] [r=.8,g=.05,b=.05]
%D \stopbuffer
%D
%D \typebuffer
%D \getbuffer
%D
%D This color shows up as \color [SomeKindOfRed] {some kind
%D of red}.
%D
%D \starttyping
%D \setupcolors[state=start]
%D
%D \definecolor[mygreen][green]
%D \definecolor[green][g=.5]
%D
%D \startcolor[mygreen]test\stopcolor
%D
%D \setupcolors[expansion=no]
%D
%D \definecolor[mygreen][green]
%D \definecolor[green][g=.5]
%D
%D \startcolor[mygreen]test\stopcolor
%D \stoptyping

%D \macros
%D   {setupcolor}
%D
%D Color definitions can be grouped in files with the name:
%D
%D \starttyping
%D \f!colorprefix-identifier.tex
%D \stoptyping
%D
%D where \type{\f!colorprefix} is \unprotect {\tttf \f!colorprefix}.
%D Loading such a file is done by \protect
%D
%D \showsetup{setupcolor}
%D
%D Some default colors are specified in \type{colo-rgb.tex},
%D which is loaded into the format by:
%D
%D \starttyping
%D \setupcolor[rgb]
%D \stoptyping

\let\colorstyle\empty

\def\setupcolor
  {\dosingleargument\dosetupcolor}

\def\dosetupcolor[#1]%
  {\doifnot{#1}\colorstyle
     {\def\colorstyle{#1}%
      \processcommalist[#1]\dodosetupcolor}}

\def\dodosetupcolor#1%
  {\makeshortfilename[\truefilename{\f!colorprefix#1}]%
   \startreadingfile
     \readsysfile\shortfilename
       {\showmessage\m!colors4\colorstyle}
       {\showmessage\m!colors5\colorstyle}%
   \stopreadingfile}

\let\usecolors\setupcolor

%D When typesetting for paper, we prefer using the \cap{CMYK}
%D color space, but for on||screen viewing we prefer \cap{RGB}
%D (the previous implementation supported only this scheme).
%D Independant of such specifications, we support some automatic
%D conversions:
%D
%D \startitemize[packed]
%D \item  convert all colors to \cap{RGB}
%D \item  convert all colors to \cap{CMYK}
%D \item  convert all colors to gray scales
%D \stopitemize
%D
%D We also support optimization of colors to gray scales.
%D
%D \startitemize[continue]
%D \item  reduce gray colors to gray scales
%D \item  reduce \cap{CMY} components to \cap{K}
%D \stopitemize
%D
%D These options are communicated by means of:

\newif\ifRGBsupported
\newif\ifCMYKsupported
\newif\ifSPOTsupported
\newif\ifpreferGRAY
\newif\ifGRAYprefered
\newif\ifreduceCMYK

%D The last boolean controls reduction of \cap{CMYK} to
%D \cap{CMY} colors. When set to true, the black component
%D is added to the other ones.
%D
%D Prefering gray is not the same as converting to gray.
%D Conversion treats each color components in a different way,
%D while prefering is just a reduction and thus a
%D space||saving option.

%D The next (internal) switch suppresses duplicate messages.

\newif\ifconverttoGRAY

%D \macros
%D   {startcolormode,stopcolormode,permitcolormode}
%D
%D We use \type{\stopcolormode} to reset the color in
%D whatever color space and do so by calling the corresponding
%D special. Both commands can be used for fast color
%D switching, like in colored verbatim,

\newif\ifpermitcolormode \permitcolormodetrue

\def\startregistercolor[#1]%
  {\permitcolormodefalse\startcolor[#1]\permitcolormodetrue}

\def\stopregistercolor
  {\permitcolormodefalse\stopcolor\permitcolormodetrue}

\def\dowithcolor#1#2% #1=\action #2=color
  {\ifincolor\ifpermitcolormode
     \ifcsname\??cr\currentpalet#2\endcsname
       \handlecolorwith#1\csname\??cr\currentpalet#2\endcsname\od
     \else\ifcsname\??cr#2\endcsname
       \handlecolorwith#1\csname\??cr#2\endcsname\od
     \fi\fi
   \fi\fi}

\def\startcolormode % includes \ifincolor\ifpermitcolormode
  {%\dostoptransparency % needed for: {test \trans test \notrans test}
   \conditionalstoptransparency
   \dowithcolor\execcolorRCSP}

\def\stopcolormode
  {\ifincolor\ifpermitcolormode
     \supportedstoptransparency
     \dostopcolormode
   \fi\fi}

\def\restorecolormode
  {\ifincolor\ifpermitcolormode
     \supportedstoptransparency
     \dostopcolormode
     \ifx\maintextcolor\empty \else
       \startcolormode\maintextcolor
     \fi
   \fi\fi}

%D Color modes are entered using the next set of commands.
%D The \type{\stop} alternatives are implemented in a way
%D that permits non||grouped use.
%D
%D The, for this module redundant, check if we are in color
%D mode is needed when we use these macros in other modules.

\chardef\currentcolorchannel=0

\newif\iffilterspotcolor \filterspotcolorfalse
\newif\ifdoingspotcolor  \doingspotcolorfalse

\def\registercolorchannel#1%
  {\ifdoingspotcolor \else
     \global\expandafter\chardef\csname\??cs#1\endcsname\zerocount
   \fi}

\def\execcolorRCSP#1:%
  {\csname execcolor#1\endcsname}

\def\execcolorR
  {\iffilterspotcolor
     \@EA\noexeccolorR
   \else
     \@EA\doexeccolorR
   \fi}

\def\execcolorC
  {\iffilterspotcolor
     \@EA\noexeccolorC
   \else
     \@EA\doexeccolorC
   \fi}

\def\execcolorS
  {\iffilterspotcolor
     \@EA\noexeccolorS
   \else
     \@EA\doexeccolorS
   \fi}

\def\execcolorP
  {\iffilterspotcolor
     \@EA\doexeccolorPP
   \else\ifcase\currentcolorchannel
     \@EAEAEA\doexeccolorP
   \else
     \@EAEAEA\noexeccolorP
   \fi\fi}

\def\doexeccolorR#1:#2:#3:%
  {\edef\@@cl@@r{#1}\edef\@@cl@@g{#2}\edef\@@cl@@b{#3}%
   \ifpreferGRAY\ifx\@@cl@@r\@@cr@@g\ifx\@@cl@@r\@@cl@@b
     \GRAYpreferedtrue
   \fi\fi\fi
   \ifincolor\else\RGBsupportedfalse\CMYKsupportedfalse\fi
   \ifGRAYprefered
     \registercolorchannel\c!s
     \let\@@cl@@s\@@cl@@r
     \normalizeGRAY
     \doexeccolorgray
   \else\ifRGBsupported
     \registercolorchannel\c!r
     \normalizeRGB
     \doexeccolorrgb
   \else\ifCMYKsupported
     \registercolorchannel\c!c
     \convertRGBtoCMYK\@@cl@@r\@@cl@@g\@@cl@@b
     \normalizeCMYK
     \doexeccolorcmyk
   \else
     \registercolorchannel\c!s
     \convertRGBtoGRAY\@@cl@@r\@@cl@@g\@@cl@@b
     \normalizeGRAY
     \doexeccolorgray
   \fi\fi\fi
   \exectransparency}

\def\doexeccolorC#1:#2:#3:#4:%
  {\edef\@@cl@@c{#1}\edef\@@cl@@m{#2}\edef\@@cl@@y{#3}\edef\@@cl@@k{#4}%
   \ifpreferGRAY\ifx\@@cl@@k\@@cl@@z\ifx\@@cl@@c\@@cr@@m\ifx\@@cl@@c\@@cl@@y
     \GRAYpreferedtrue
   \fi\fi\fi\fi
   \ifincolor\else\RGBsupportedfalse\CMYKsupportedfalse\fi
   \ifGRAYprefered
     \registercolorchannel\c!s
     \let\@@cl@@s\@@cl@@c
     \normalizeGRAY
     \doexeccolorgray
   \else\ifCMYKsupported
     \registercolorchannel\c!c
     \ifreduceCMYK
       \convertCMYKtoCMY\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
     \fi
     \normalizeCMYK
     \doexeccolorcmyk
   \else\ifRGBsupported
     \registercolorchannel\c!r
     \convertCMYKtoRGB\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
     \normalizeRGB
     \doexeccolorrgb
   \else
     \registercolorchannel\c!s
     \convertCMYKtoGRAY\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k
     \normalizeGRAY
     \doexeccolorgray
   \fi\fi\fi
   \exectransparency}

\def\doexeccolorS#1:%
  {\edef\@@cl@@s{#1}%
   \registercolorchannel\c!s
   \normalizeGRAY
   \doexeccolorgray
   \exectransparency}

% \def\doexeccolorP#1:#2:%
%   {\edef\@@cl@@n{#1}%
%    \edef\@@cl@@p{#2}%
%    \registerusedspotcolor\@@cl@@n
%    \ifSPOTsupported
%      \dowithcolor\registerspotcolor\@@cl@@n
%      \dostartspotcolormode\@@cl@@n\@@cl@@p
%    \else
%      \doingspotcolortrue
%      \let\spotcolorfactor\@@cl@@p
%      \factorizecolortrue            % using counter and array
%      \dowithcolor\execcolorRCSP\@@cl@@n
%      \factorizecolorfalse
%      \let\spotcolorfactor\@@cl@@o
%      \doingspotcolorfalse
%    \fi
%    \exectransparency}

\def\doexeccolorP#1:#2:#3:#4:%
  {\edef\@@cl@@n{#1}% name
   \edef\@@cl@@f{#2}% fractions
   \edef\@@cl@@d{#3}% definitions
   \edef\@@cl@@p{#4}%
   \ifx\@@cl@@d\empty
     \let\@@cl@@d\@@cl@@n
   \fi
   \registerusedspotcolor\@@cl@@n
   \ifSPOTsupported
     \checkmultitonecolor\@@cl@@n
     \dowithcolor\registerspotcolor\@@cl@@n
     \dostartspotcolormode\@@cl@@n\@@cl@@p
   \else
     \doingspotcolortrue
     \normalizespotcolor\@@cl@@p
     \let\spotcolorfactor\@@cl@@p
     \factorizecolortrue            % using counter and array
     \dowithcolor\execcolorRCSP\@@cl@@n
     \factorizecolorfalse
     \let\spotcolorfactor\@@cl@@o
     \doingspotcolorfalse
   \fi
   \exectransparency}

\def\doexeccolorPindex#1:#2:#3:#4:%
  {\edef\@@cl@@n{#1}%
   \edef\@@cl@@f{#2}%
   \edef\@@cl@@d{#3}%
   \edef\@@cl@@p{#4}%
   \ifx\@@cl@@d\empty
     \let\@@cl@@d\@@cl@@n
   \fi
   \ifSPOTsupported
     \checkmultitonecolor\@@cl@@n
     \dowithcolor\registerindexcolor\@@cl@@n
   \fi
   \noexectransparency}

\def\doexeccolorPP#1:#2:%
  {\edef\@@cl@@n{#1}%
   \edef\@@cl@@p{#2}%
   \registerusedspotcolor\@@cl@@n
   \ifx\@@cl@@n\currentspotcolor
     \normalizeSPOT
     \dostartgraycolormode\@@cl@@p % was spotcolormode
   \else
     \dovidecolor\@@cl@@p\@@cl@@o
   \fi
   \exectransparency}

\def\doexeccolorrgb
  {\ifcase\currentcolorchannel
     \dostartrgbcolormode