%D \module
%D   [       file=colo-ini,
%D        version=2007.08.08,
%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.

%D We need to clean this up further but first we hav eto make sure that mkiv
%D code works ok.

\writestatus{loading}{ConTeXt Color Macros / Initialization}

%D This module implements color. Since \MKII\ and \MKIV\ use a completely
%D different approach, this module only implements a few generic mechanisms.

\registerctxluafile{colo-ini}{1.000}
\registerctxluafile{lpdf-col}{1.000}

\unprotect

%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).

\newcount\colorcount

%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
\newif\ifconverttoGRAY
\newif\ifweightGRAY       \weightGRAYtrue

\newif\ifconvertMPcolors
\newif\ifreduceMPcolors
\newif\ifforcegrayMPcolors

%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.

\newif\iffreezecolors  \freezecolorsfalse
\newif\ifincolor                          % true if colors enabled

\let\colorlist        \empty
\let\currentspotcolor \empty
\let\allspotcolors    \empty
\let\usedspotcolors   \empty
\let\currentpalet     \empty

%D \macros
%D   {definecolor,defineglobalcolor,definenamedcolor,definespotcolor,definemultitonecolor}
%D
%D \startbuffer
%D \definecolor [blue]   [c=1,m=.38,y=0,k=.64] % pantone pms 2965 uncoated m
%D \definecolor [yellow] [c=0,m=.28,y=1,k=.06] % pantone pms  124 uncoated m
%D
%D \definespotcolor [blue-100]   [blue]   [p=1]
%D \definespotcolor [yellow-100] [yellow] [p=1]
%D
%D \definemultitonecolor [pdftoolscolor] [blue=.12,yellow=.28] [c=.1,m=.1,y=.3,k=.1]
%D
%D \useexternalfigure[demofig][mill.png][object=no]
%D
%D \startcombination[4*1]
%D   {\externalfigure[demofig]}                      {no color}
%D   {\externalfigure[demofig][color=pdftoolscolor]} {indexed duotone}
%D   {\externalfigure[demofig][color=blue-100]}      {spot color}
%D   {\externalfigure[demofig][color=yellow-100]}    {spot color}
%D \stopcombination
%D \stopbuffer
%D
%D \getbuffer \typebuffer

\def\definecolor         {\dodoubleargument\dodefinecolor}
\def\defineglobalcolor   {\dodoubleargument\dodefineglobalcolor}
\def\definenamedcolor    {\dodoubleargument\dodefinenamedcolor}
\def\definespotcolor     {\dotripleargument\dodefinespotcolor}
\def\definemultitonecolor{\doquadrupleempty\dodefinemultitonecolor}

%D \macros
%D   {startcolor,stopcolor,
%D    faststartcolor,faststopcolor,
%D    startraster,stopraster,raster,
%D    color,graycolor}
%D
%D The local and global and raster commands are here just
%D for compatibility with \MKII.
%D
%D \showsetup{startcolor}
%D
%D \macros
%D   {color,graycolor}
%D
%D This leaves the simple color command:
%D
%D \showsetup{color}
%D \showsetup{graycolor}
%D
%D This leaves the simple color command:
%D
%D \showsetup{color}
%D \showsetup{graycolor}

           \def\switchtocolor      [#1]{\getvalue{#1}}
\unexpanded\def\color              [#1]{\groupedcommand{\doactivatecolor{#1}}{}}
\unexpanded\def\startcolor         [#1]{\begingroup\doactivatecolor{#1}}
\unexpanded\def\stopcolor              {\endgroup}
\unexpanded\def\graycolor          [#1]{\groupedcommand{\setcolormodel{gray}\getvalue{#1}}{}}
\unexpanded\def\colored            [#1]{\groupedcommand{\definecolor[@colored@][#1]\doactivatecolor{@colored@}}{}}
\unexpanded\def\fastcolored      [#1]#2{\begingroup\dodefinefastcolor[@colored@][#1]\doactivatecolor{@colored@}#2\endgroup}
           \def\predefinecolor     [#1]{\flushatshipout{\hbox{\color[#1]{}}}}
           \def\predefineindexcolor[#1]{\flushatshipout{\hbox{\color[#1]{}}}}
           \def\startcolorpage         {\startcolor[\ifx\maintextcolor\empty\defaulttextcolor\else\maintextcolor\fi]}
           \def\stopcolorpage          {\stopcolor}
           \def\startraster        [#1]{\dosetrastercolor{#1}}
           \def\stopraster             {}
           \def\raster             [#1]{\groupedcommand{\dosetrastercolor{#1}}{}}
           \def\faststartcolor     [#1]{\doactivatecolor{#1}}
           \def\faststopcolor          {}
\unexpanded\def\dosetcolorattribute#1#2{\ifcsname#1#2\endcsname\doactivatecolor{\csname#1#2\endcsname}\fi}

\let\grey\graycolor

%D \macros
%D   {startcurrentcolor,stopcurrentcolor}

\def\startcurrentcolor{\startcolor[\outercolorname]}
\def\stopcurrentcolor {\stopcolor}

%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
       {\showcolormessage\m!colors4\colorstyle}
       {\showcolormessage\m!colors5\colorstyle}%
   \stopreadingfile}

\let\usecolors\setupcolor

% check: \startcolormode

%D \macros
%D   {definetransparency}
%D
%D This command numbers to names:

\def\definetransparency
  {\dodoubleargument\dodefinetransparency}

\unexpanded\def\setupcolors
  {\dosingleargument\dosetupcolors}

\let\showcolormessage\gobblethreearguments

\def\dosetupcolors[#1]% some no longer make sense in MkIV
  {\getparameters[\??cl][#1]%
   \doifelse\@@clspot\v!yes
     \SPOTsupportedtrue
     \SPOTsupportedfalse
   \doifelse\@@clreduction\v!yes
     \reduceCMYKtrue
     \reduceCMYKfalse
   \doifelse\@@clexpansion\v!yes
     \freezecolorstrue
     \freezecolorsfalse
   \doifelse\@@clfactor\v!no
     \weightGRAYfalse
     \weightGRAYtrue
   \doifelse\@@clrgb\v!no
     {\ifRGBsupported      \showcolormessage\m!colors {9}\v!rgb        \RGBsupportedfalse \fi}
     {\ifRGBsupported \else\showcolormessage\m!colors{10}\v!rgb        \RGBsupportedtrue  \fi}%
   \doifelse\@@clcmyk\v!no
     {\ifCMYKsupported     \showcolormessage\m!colors {9}\v!cmyk       \CMYKsupportedfalse\fi}
     {\ifCMYKsupported\else\showcolormessage\m!colors{10}\v!cmyk       \CMYKsupportedtrue \fi}%
   \doifelse\@@clmpcmyk\v!no
     {\ifMPcmykcolors      \showcolormessage\m!colors {9}{\v!mp\v!cmyk}\MPcmykcolorsfalse \fi}
     {\ifMPcmykcolors \else\showcolormessage\m!colors{10}{\v!mp\v!cmyk}\MPcmykcolorstrue  \fi}%
   \doifelse\@@clmpspot\v!no
     {\ifMPspotcolors      \showcolormessage\m!colors {9}{\v!mp\v!spot}\MPspotcolorsfalse \fi}
     {\ifMPspotcolors \else\showcolormessage\m!colors{10}{\v!mp\v!spot}\MPspotcolorstrue  \fi}%
   \preferGRAYfalse
   \processaction
     [\@@clconversion]
     [    \v!yes=>\preferGRAYtrue,
       \v!always=>\preferGRAYtrue\RGBsupportedfalse\CMYKsupportedfalse]%
   \ifRGBsupported
     \converttoGRAYfalse
     \forcegrayMPcolorsfalse
   \else\ifCMYKsupported
     \converttoGRAYfalse
     \forcegrayMPcolorsfalse
     \convertMPcolorstrue
     \ifreduceCMYK
       \reduceMPcolorstrue
     \fi
   \else
     \ifconverttoGRAY\else\showcolormessage\m!colors{11}\empty\fi
     \converttoGRAYtrue
     \forcegrayMPcolorstrue
     \convertMPcolorsfalse
     \reduceMPcolorsfalse
   \fi\fi
   \doifelse\@@clstate\v!stop
     {\incolorfalse\forcegrayMPcolorstrue}%
     {\ifincolor\else\showcolormessage\m!colors1\colorstyle\fi\incolortrue\let\@@clstate\v!start}%
   \dosetupcolormodel
   \initializemaintextcolor}

%D In this documentation we will not go into too much details
%D on palets. Curious users can find more information on this
%D topic in \from[use of color].
%D
%D At the moment we implemented color in \CONTEXT\ color
%D printing was not yet on the desktop. In spite of this lack our
%D graphics designer made colorfull illustrations. When printed
%D on a black and white printer, distinctive colors can come
%D out equally gray. We therefore decided to use only colors
%D that were distinctive in colors as well as in black and
%D white print.
%D
%D Although none of the graphic packages we used supported
%D logical colors and global color redefition, we build this
%D support into \CONTEXT. This enabled us to experiment and
%D also prepared us for the future.

%D \macros
%D   {definepalet}
%D
%D Colors are grouped in palets. The colors in such a palet can
%D have colorful names, but best is to use names that specify
%D their use, like {\em important} or {\em danger}. As a sort
%D of example \CONTEXT\ has some palets predefined,
%D like:\footnote{At the time I wrote the palet support, I was
%D reading 'A hort history of time' of S.~Hawkins, so that's
%D why we stuck to quarks.}
%D
%D \starttyping
%D \definepalet
%D   [alfa]
%D   [     top=rood:7,
%D      bottom=groen:6,
%D          up=blauw:5,
%D        down=cyaan:4,
%D     strange=magenta:3,
%D       charm=geel:2]
%D \stoptyping
%D
%D It's formal definition is:
%D
%D \showsetup{definepalet}
%D
%D Visualized, such a palet looks like:
%D
%D \startbuffer[palet]
%D \showpalet [alfa] [horizontal,name,number,value]
%D \stopbuffer
%D
%D \startlinecorrection
%D \getbuffer[palet]
%D \stoplinecorrection
%D
%D This bar shows both the color and gray alternatives of the
%D palet components (not visible in black and white print).
%D
%D When needed, one can copy a palet by saying:
%D
%D \starttyping
%D \definepalet [TEXcolorpretty] [colorpretty]
%D \stoptyping
%D
%D This saves us some typing in for instance the modules that
%D deal with pretty verbatim typesetting.

\def\definepalet
  {\dodoubleargument\dodefinepalet}

\def\dodefinepalet[#1][#2]%
  {\doifassignmentelse{#2}
     {%\showcolormessage\m!colors6{#1}%
      \letvalue{\??pa#1}\empty
      \setevalue{\??pa\??pa#1}{#2}%
      \def\dodododefinepalet[##1=##2]%
        {\doifvaluesomething{\??pa#1}
           {\setevalue{\??pa#1}{\csname\??pa#1\endcsname,}}%
         \setevalue{\??pa#1}{\csname\??pa#1\endcsname##1}%
         \dodefinepaletcolor{#1}{##1}{##2}}%
      \def\dododefinepalet##1%
        {\dodododefinepalet[##1]}%
      \processcommalist[#2]\dododefinepalet}
     {\doifdefined{\??pa#2}
        {\expanded{\dodefinepalet[#1][\csname\??pa\??pa#2\endcsname]}}}}

\let\paletsize\!!zerocount

\def\getpaletsize[#1]%
  {\getcommacommandsize[\csname\??pa\??pa#1\endcsname]%
   \edef\paletsize{\number\commalistsize}}

%D Instead of refering to colors, one can also directly specify
%D a color:
%D
%D \starttyping
%D \definepalet[test][xx=green]
%D \definepalet[test][xx={y=.4}]
%D \stoptyping

%D \macros
%D   {setuppalet}
%D
%D Colors are taken from the current palet, if defined.
%D Setting the current palet is done by:
%D
%D \showsetup{setuppalet}

\let\currentpalet\empty

\def\setuppalet
  {\dosingleempty\dosetuppalet}

\def\dosetuppalet[#1]%
  {\edef\currentpalet{#1}%
   \ifx\currentpalet\empty
     % seems to be a reset
   \else\ifcsname\??pa\currentpalet\endcsname
     \edef\currentpalet{#1:}%
   \else
     \showcolormessage\m!colors7\currentpalet
     \let\currentpalet\empty
   \fi\fi
   \initializemaintextcolor}

%D \macros
%D   {showpalet}
%D
%D The previous visualization was typeset with:
%D
%D \typebuffer[palet]
%D
%D This commands is defined as:
%D
%D \showsetup{showpalet}

\fetchruntimecommand \showpalet {\f!colorprefix\s!run}

%D \macros
%D   {showcolorcomponents}
%D
%D \starttyping
%D \showcolorcomponents[color-1,color-2]
%D \stoptyping

\fetchruntimecommand \showcolorcomponents {\f!colorprefix\s!run}

%D \macros
%D   {definecolorgroup}
%D
%D The naming of the colors in this palet suggests some
%D ordening, which in turn is suported by color grouping.
%D
%D \starttyping
%D \definecolorgroup
%D   [red]
%D   [1.00:0.90:0.90,
%D    1.00:0.80:0.80,
%D    1.00:0.70:0.70,
%D    1.00:0.55:0.55,
%D    1.00:0.40:0.40,
%D    1.00:0.25:0.25,
%D    1.00:0.15:0.15,
%D    0.90:0.00:0.00]
%D \stoptyping
%D
%D In such a color group colors are numbered from~$1$ to~$n$.
%D
%D \showsetup{definecolorgroup}
%D
%D This kind of specification is not only more compact than
%D defining each color separate, it also loads faster and takes
%D less bytes.

\def\definecolorgroup
  {\dotripleempty\dodefinecolorgroup}

\def\dododefinecolorgroupgray         [#1][#2:#3]{\definecolor    [#1:\the\colorcount][s=#2]}
\def\dododefinecolorgrouprgb    [#1][#2:#3:#4:#5]{\definecolor    [#1:\the\colorcount][r=#2,g=#3,b=#4]}
\def\dododefinecolorgroupcmyk[#1][#2:#3:#4:#5:#6]{\definecolor    [#1:\the\colorcount][c=#2,m=#3=,y=#4,k=#5]}
\def\dododefinecolorgroupspot      [#1][#2:#3:#4]{\definespotcolor[#1:\the\colorcount][#2][p=#3]}

\def\dododefinecolorgroup#1#2%
  {\advance\colorcount\plusone
   \getvalue{dododefinecolorgroup\currentcolorspace}[#1][#2:0:0:0:0]}

\def\dodefinecolorgroup[#1][#2][#3]% obsolete, just use palets
  {\ifthirdargument
     \doifelsenothing{#2}{\let\currentcolorspace\v!rgb}{\def\currentcolorspace{#2}}%
     \colorcount\zerocount
     \processcommalist[#3]{\dododefinecolorgroup{#1}}%
   \else
     \doifinstringelse{:}{#2}
       {\definecolorgroup[#1][\v!rgb][#2]}
       {\doloop
          {\ifcsname\??cr#2:\recurselevel\endcsname
             \setevalue{\??cr#1:\recurselevel}{\csname\??cr#2:\recurselevel\endcsname}%
           \else
             \exitloop
           \fi}}%
   \fi}

%D \macros
%D   {showcolorgroup}
%D
%D We can show the group by:
%D
%D \startbuffer
%D \showcolorgroup [blue] [horizontal,name,number,value]
%D \stopbuffer
%D
%D \typebuffer
%D
%D or in color:
%D
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection
%D
%D which uses:
%D
%D \showsetup{showcolorgroup}

\fetchruntimecommand \showcolorgroup {\f!colorprefix\s!run}

%D There are ten predefined color groups, like
%D \color[green]{\em groen}, \color[red]{\em rood},
%D \color[blue]{\em blauw}, \color[cyan]{\em cyaan},
%D \color[magenta]{\em magenta} and \color[yellow]{\em geel}.
%D
%D \startlinecorrection
%D \hbox to \hsize
%D   {\hss
%D    \showcolorgroup [red]    [vertical,name,number]\hss
%D    \showcolorgroup [green]  [vertical,name]\hss
%D    \showcolorgroup [blue]   [vertical,name]\hss
%D    \showcolorgroup [cyan]   [vertical,name]\hss
%D    \showcolorgroup [magenta][vertical,name]\hss
%D    \showcolorgroup [yellow] [vertical,name]\hss}
%D \stoplinecorrection
%D
%D These groups are used to define palets {\em alfa} upto {\em
%D zeta}. As long as we don't use colors from the same row, we
%D get ourselves distinctive palets. By activating such a palet
%D one gains access to its members {\em top} to {\em charm} (of
%D course one should use more suitable names than these).
%D
%D \startlinecorrection
%D \hbox to \hsize
%D   {\showpalet [alfa]    [vertical,name,number]\hss
%D    \showpalet [beta]    [vertical,name]\hss
%D    \showpalet [gamma]   [vertical,name]\hss
%D    \showpalet [delta]   [vertical,name]\hss
%D    \showpalet [epsilon] [vertical,name]\hss
%D    \showpalet [zeta]    [vertical,name]}
%D \stoplinecorrection
%D
%D By using the keyword \type {value} the individual color
%D components are shown too. When printed in color, these
%D showcases show both the colors and the gray value.

%D \macros
%D   {comparepalet}
%D
%D There are some more testing macros available:
%D
%D \startbuffer
%D \comparepalet [alfa]
%D \stopbuffer
%D
%D \typebuffer
%D
%D shows the palet colors against a background:
%D
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection
%D
%D The formal definition is:
%D
%D \showsetup{comparepalet}

\fetchruntimecommand \comparepalet {\f!colorprefix\s!run}

%D \macros
%D   {comparecolorgroup}
%D
%D The similar command:
%D
%D \startbuffer
%D \comparecolorgroup [blue]
%D \stopbuffer
%D
%D \typebuffer
%D
%D shows color groups:
%D
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection
%D
%D this commands are defined as:
%D
%D \showsetup{comparecolorgroup}

\fetchruntimecommand \comparecolorgroup {\f!colorprefix\s!run}

%D \macros
%D   {showcolor}
%D
%D But let's not forget that we also have the more traditional
%D non||related colors. These show up after:
%D
%D \starttyping
%D \showcolor [name]
%D \stoptyping
%D
%D Where \type{name} for instance can be \type{rgb}.
%D
%D \showsetup{showcolor}

\fetchruntimecommand \showcolor {\f!colorprefix\s!run}

%D It would make sense to put the following code in \type
%D {colo-mps}, but it it rather low level.

%D \macros
%D   {negatecolorcomponent,negatedcolorcomponent}
%D
%D These speak for themselves. See \type {colo-ext} for usage.

\def\negatecolorcomponent#1% #1 = \macro
  {\scratchdimen\onepoint\advance\scratchdimen-#1\onepoint
   \ifdim\scratchdimen<\zeropoint\scratchdimen\zeropoint\fi
   \edef#1{\withoutpt\the\scratchdimen}}

\let\negatedcolorcomponent\firstofoneargument

\def\negatedcolorcomponent#1%
  {\ifdim\dimexpr\onepoint-#1\onepoint\relax<\zeropoint
     \!!zerocount
   \else
     \expandafter\withoutpt\the\dimexpr\onepoint-#1\onepoint\relax
   \fi}

\def\negatecolorcomponent#1% #1 = \macro
  {\edef#1{\negatedcolorcomponent{#1}}}

%D \macros
%D   {ifMPgraphics, ifMPcmykcolors, MPcolor}
%D
%D A very special macro is \type{\MPcolor}. This one can be
%D used to pass a \CONTEXT\ color to \METAPOST.
%D
%D \starttyping
%D \MPcolor{my own red}
%D \stoptyping
%D
%D This macro returns a \METAPOST\ triplet \type{(R,G,B)}.
%D Unless \CMYK\ color support is turned on with \type
%D {MPcmyk}, only \cap{RGB} colors and gray scales are
%D supported.

\newif\ifMPcmykcolors % \MPcmykcolorsfalse
\newif\ifMPspotcolors % \MPspotcolorsfalse

\ifx\MPcolor\undefined
    \def\MPcolor#1{(0,0,0)}
\fi

%D For the moment we keep the next downward compatibility
%D switch, i.e.\ expanded colors. However, predefined colors
%D and palets are no longer expanded (which is what I wanted
%D in the first place).
%D
%D Well, in case we want to do color separation and use CMYK
%D colors only, this is dangerous since unwanted remapping may
%D take place. Especially when we redefine already defined
%D colors in another color space (e.g. darkgreen is
%D predefined in RGB color space, so a redefinition in CMYK
%D coordinates before RGB mode is disabled, would give
%D unexpected results due to the already frozen color spec.)

%D In \MKIV\ we don't support color separation as we might now assume
%D that printing houses have the right programs to do it themselves.
%D The \MKII\ color separator was implemented as part of a project
%D that needed. If it's ever needed in \MKIV\ i'll do it in the
%D backend.

\let\doifseparatingcolorselse\secondoftwoarguments
\let\doifcolorchannelelse    \secondofthreearguments
\let\resetcolorseparation    \relax
\let\colorchannelprefix      \empty
\let\colorchannelsuffix      \empty

%D We now define the low level macros:

% todo: palets in definecolor
% todo: {\red xx} vs \red{xx}

% check: registerusedspotcolors
% check: \currentcolorname
% check: \outercolorname
% check: \startcolormode

% \def\mptexcolor#1{"\dogetattributeid\s!color \somecolorattribute{#1} A"}
%
% \startMPpage
%     fill fullcircle scaled 10cm  ;
%     fill fullcircle scaled 5cm withprescript \mptexcolor{red} withpostscript \mptexcolor{black} ;
%     fill fullcircle scaled 3cm  ;
%     draw btex test etex withprescript \mptexcolor{blue}  ;
% \stopMPpage

\ifx\currentcolormodel\undefined \newcount\currentcolormodel \fi

\def\setcolormodel#1%
  {\showcolormessage\m!colors1{#1}%
   \currentcolormodel\ctxlua{tex.print(colors.setmodel('#1',\ifweightGRAY true\else false\fi))}%
   \dosetattribute{colormodel}{\the\currentcolormodel}}

\setcolormodel{all}

\def\dosetupcolormodel
  {\ifincolor
     \ifRGBsupported
       \ifCMYKsupported
         \setcolormodel{all}%
       \else
         \setcolormodel{rgb}%
       \fi
     \else
       \ifCMYKsupported
         \setcolormodel{cmyk}%
       \else
         \setcolormodel{gray}%
       \fi
     \fi
   \else
     \setcolormodel{gray}%
   \fi
   }%\aftergroup\dosetupcolormodel}

\appendtoks
    \dosetupcolormodel
\to \everyjob

% Currently in mkiv transparency is implemented independent of color. This costs
% a bit more processing time but gives the possibility to apply transparency
% independently in the future. Is this useful? If not we may as well combine them
% again in the future. By coupling we are downward compatible. When we decouple we
% need to do more tricky housekeeping (e.g. persist color independent transparencies
% when color bound ones are nil.

% Since we couple definitions, we could stick to one test. Todo. Same for mpcolor.

\letvalue{(cs:-}\empty
\letvalue{(ts:-}\empty

\def\doactivatecolor#1% : in currentpalet, maybe not, ugly
  {\def\currentcolorname{#1}%
   \ifcsname(cs:\currentpalet#1)\endcsname
     \csname(cs:\currentpalet#1)\endcsname
     \csname(ts:\currentpalet#1)\endcsname
   \else\ifcsname(cs:#1)\endcsname
     \csname(cs:#1)\endcsname
     \csname(ts:#1)\endcsname
   \fi\fi}

\let\normaldoactivatecolor\doactivatecolor

% if it becomes a bottleneck we can set up a more complex system with one shared
% attribute for colorspace, color and transparency

\def\doactivatecolor
  {\ifproductionrun
     \ctxlua{colors.enabled=true transparencies.enabled=true}% not that efficient but at least robust
     \let\doactivatecolor\normaldoactivatecolor
     \expandafter\doactivatecolor
   \else
     \expandafter\normaldoactivatecolor
   \fi}

\def\deactivatecolor
  {\let\currentcolorname\s!black
   \attribute\colorattribute\attributeunsetvalue
   \attribute\transparencyattribute\attributeunsetvalue}

\def\dodefinecolorcommand#1#2%
  {\unexpanded#1{#2}{\doactivatecolor{#2}}}

\let\colorlist\empty % not really used, only for colo-run
\setfalse\collectcolorsinlist
\def\collectcolorinlist#1{\doglobal\addtocommalist{#1}\colorlist}

\def\doregistercolor#1#2{\ctxlua{colors.defineprocesscolor("#1","#2",false,\iffreezecolors true\else false\fi)}}

\def\dodefinecolor[#1][#2]%
  {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
   \ctxlua{colors.defineprocesscolor("#1","#2",false,\iffreezecolors true\else false\fi)}%
   \dodefinecolorcommand\setvalue{#1}}

\def\dodefineglobalcolor[#1][#2]%
  {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
   \ctxlua{colors.defineprocesscolor("#1","#2",true,\iffreezecolors true\else false\fi)}%
   \dodefinecolorcommand\setgvalue{#1}}

\def\dodefinenamedcolor[#1][#2]%
  {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
   \ctxlua{colors.defineprocesscolor("#1","#2",false,\iffreezecolors true\else false\fi)}%
   \dodefinecolorcommand\setvalue{#1}}

\def\dodefinespotcolor[#1][#2][#3]%
  {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
   \ctxlua{colors.definespotcolor("#1","#2","#3",true)}%
   \dodefinecolorcommand\setxvalue{#1}}

\def\dodefinemultitonecolor[#1][#2][#3][#4]%
  {\ctxlua{colors.definemultitonecolor("#1","#2","#3","#4",true)}%
   \dodefinecolorcommand\setxvalue{#1}}

\def\dodefinetransparency[#1][#2]%
  {\ctxlua{colors.definetransparency("#1",#2)}}

\def\dosetrastercolor#1% slow, we need a fast one
  {\edef\@@rastervalue{#1}%
   \ifx\@@rastervalue\empty
     \let\@@rastervalue\@@rsscreen
   \fi
   \dosetattribute\s!color{\ctxlua{tex.sprint(colors.definesimplegray("_raster_",\@@rastervalue))}}}

\def\dodefinefastcolor[#1][#2]% still not fast but ok
  {\ctxlua{colors.defineprocesscolor("#1","#2",false,\iffreezecolors true\else false\fi)}%
   \dodefinecolorcommand\setvalue{#1}}

%D \macros
%D   {doifcolorelse, doifcolor}
%D
%D Switching to a color is done by means of the following
%D command. Later on we will explain the use of palets.  We
%D define ourselves a color conditional first.

\def\doifcolorelse#1%
  {\ifcsname(ca:\currentpalet#1)\endcsname
     \@EA\firstoftwoarguments
   \else\ifcsname(ca:#1)\endcsname
     \@EAEAEA\firstoftwoarguments
   \else
     \@EAEAEA\secondoftwoarguments
   \fi\fi}

\def\doifcolor#1%
  {\ifcsname(ca:\currentpalet#1)\endcsname
     \@EA\firstofoneargument
   \else\ifcsname(ca:#1)\endcsname
     \@EAEAEA\firstofoneargument
   \else
     \@EAEAEA\gobbleoneargument
   \fi\fi}

%D \macros
%D   {colored}
%D
%D A bit like \type {\definedfont}:

\unexpanded\def\colored[#1]%
  {\ctxlua{colors.defineprocesscolor("@colored@","#1",false,false)}%
   \groupedcommand{\doactivatecolor{@colored@}}{}}

%D \macros
%D   {startregistercolor,stopregistercolor,permitcolormode}
%D
%D If you only want to register a color, the switch \type
%D {\ifpermitcolormode} can be used. That way the nested
%D colors know where to go back to.
%D
%D We use these macros for implementing text colors
%D (actually, the first application was in foreground
%D colors).
%D
%D \starttyping
%D \starttextcolor[red]
%D   \dorecurse{10}{\input tufte \color[green]{oeps} \par}
%D \stoptextcolor
%D \stoptyping
%D
%D This is more efficient than the alternative:
%D
%D \starttyping
%D \setupbackgrounds[text][foregroundcolor=red]
%D \startregistercolor[red]
%D   \dorecurse{10}{\input tufte \color[green]{oeps} \par}
%D \stopregistercolor
%D \stoptyping

% can be cleaned up

\let\maintextcolor     \empty
\def\defaulttextcolor  {black}
\def\@@themaintextcolor{themaintextcolor}

\appendtoks\deactivatecolor\to\everybeforeoutput

\def\startregistercolor[#1]% probably obsolete
  {\doifelsenothing{#1}
     {\let\stopregistercolor\relax}
     {\edef\stopregistercolor
        {\dosetattribute\s!color       {\dogetattribute\s!color       }%
         \dosetattribute\s!transparency{\dogetattribute\s!transparency}}%
      \doactivatecolor{#1}}}

\def\registermaintextcolor{\ctxlua{colors.main = \thecolorattribute\maintextcolor}}

\def\starttextcolor[#1]%
  {\doifsomething{#1}
     {\definecolor[\@@themaintextcolor][#1]%
      \let\maintextcolor\@@themaintextcolor
      \doactivatecolor\maintextcolor
      \registermaintextcolor}}

\let\stoptextcolor\relax

\def\initializemaintextcolor
  {\doifelsenothing\@@cltextcolor
     {\definecolor[\@@themaintextcolor][\defaulttextcolor]}
     {\definecolor[\@@themaintextcolor][\@@cltextcolor]}%
   \let\maintextcolor\@@themaintextcolor
   \doactivatecolor\maintextcolor
   \registermaintextcolor}

\appendtoks \initializemaintextcolor \to \everyjob

\def\dodefinepaletcolor#1#2#3%
  {\doifassignmentelse{#3}% \definepalet[test][xx={y=.4}]
     {\definecolor[\??pa#1:#2][#3]%
      \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{(cs:#1:#2)}{\csname(cs:\??pa#1:#2)\endcsname}%
      \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{(ca:#1:#2)}{\csname(ca:\??pa#1:#2)\endcsname}}
     {\ifcsname(cs:#3)\endcsname % \definepalet[test][xx=green]
        \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{(cs:#1:#2)}{\csname(cs:#3)\endcsname}%
        \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{(ca:#1:#2)}{\csname(ca:#3)\endcsname}%
      \else
        % not entered when making format
        \localundefine{(cs:#1:#2)}% \letvalue{(cs:#1:#2)}\undefined
        \localundefine{(ca:#1:#2)}% \letvalue{(ca:#1:#2)}\undefined
      \fi}}

\setvalue{(cs:)}{} \setvalue{(ca:)}{0}
\setvalue{(ts:)}{} \setvalue{(ta:)}{0}

\def\doinheritca#1{\csname(ca:\ifcsname(ca:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ca:#1)\endcsname#1\fi\fi)\endcsname}
\def\doinheritcs#1{\csname(cs:\ifcsname(cs:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(cs:#1)\endcsname#1\fi\fi)\endcsname}
\def\doinheritta#1{\csname(ta:\ifcsname(ta:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ta:#1)\endcsname#1\fi\fi)\endcsname}
\def\doinheritts#1{\csname(ts:\ifcsname(ts:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ts:#1)\endcsname#1\fi\fi)\endcsname}

%D \macros
%D   {colorvalue, grayvalue}
%D
%D We can typeset the color components using \type{\colorvalue} and
%D \type{\grayvalue}. The commands:
%D
%D \startbuffer
%D color value of SomeKindOfRed: \colorvalue{SomeKindOfRed} \crlf
%D gray value of SomeKindOfRed: \grayvalue{SomeKindOfRed}
%D \stopbuffer
%D
%D \typebuffer
%D
%D show us:
%D
%D \startvoorbeeld
%D \getbuffer
%D \stopvoorbeeld

\def\colorformatseparator{ }

\def\MPcolor#1{\ctxlua{tex.sprint(colors.mp(\number\currentcolormodel,\number\doinheritca{#1},\number\doinheritta{#1}))}}

\let\currentcolorname\s!black % todo
\let\outercolorname  \s!black % todo

\def\thecolorattribute       #1{\number\csname(ca:\ifcsname(ca:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ca:#1)\endcsname#1\fi\fi)\endcsname}
\def\thetransparencyattribute#1{\number\csname(ta:\ifcsname(ta:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ta:#1)\endcsname#1\fi\fi)\endcsname}

\def\internalspotcolorname  #1{\ctxlua{tex.sprint(colors.spotcolorname  (\thecolorattribute{#1}))}}
\def\internalspotcolorparent#1{\ctxlua{tex.sprint(colors.spotcolorparent(\thecolorattribute{#1}))}}
\def\internalspotcolorsize  #1{\ctxlua{tex.sprint(colors.spotcolorvalue (\thecolorattribute{#1}))}}

\def\colorcomponents       #1{\ctxlua{tex.sprint(colors.colorcomponents       (\thecolorattribute       {#1}))}}
\def\transparencycomponents#1{\ctxlua{tex.sprint(colors.transparencycomponents(\thetransparencyattribute{#1}))}}

\def\colorvalue#1{\ctxlua{tex.sprint(colors.formatcolor(\thecolorattribute{#1},"\colorformatseparator"))}}
\def\grayvalue #1{\ctxlua{tex.sprint(colors.formatgray (\thecolorattribute{#1},"\colorformatseparator"))}}

\def\doifblackelse       #1{\ctxlua{commands.doifelse(colors.isblack(\thecolorattribute{#1}))}}
\def\doifdrawingblackelse  {\ctxlua{commands.doifelse(colors.isblack(tex.attribute[attributes.numbers['color']]))}}

%D \macros
%D   {forcecolorhack}
%D
%D We can out this in front of (for instance) a special and so force color
%D to be applied (only glyphs, rules and leaders are handled).
%D
%D \startbuffer
%D \framed
%D   [background=color,backgroundcolor=yellow,framecolor=red,corner=round]
%D   {test}
%D \stopbuffer
%D
%D \typebuffer \getbuffer

% ignores in attribute handler
%
% \def\forcecolorhack{\vrule\!!width\zeropoint\!!height\zeropoint\!!depth\zeropoint}

% \normal added else fails in metafun manual (leaders do a hard scan)

\unexpanded\def\forcecolorhack{\leaders\hrule\normalhskip\zeropoint}

%D We default to the colors defined in \module{colo-rgb} and
%D support both \cap{RGB} and \cap{CMYK} output. As you can
%D see, color support is turned off by default. Reduction of
%D gray colors to gray scales is turned on.

\definecolor[black][s=0]
\definecolor[white][s=1]

\definetransparency [none]        [0]
\definetransparency [normal]      [1]
\definetransparency [multiply]    [2]
\definetransparency [screen]      [3]
\definetransparency [overlay]     [4]
\definetransparency [softlight]   [5]
\definetransparency [hardlight]   [6]
\definetransparency [colordodge]  [7]
\definetransparency [colorburn]   [8]
\definetransparency [darken]      [9]
\definetransparency [lighten]    [10]
\definetransparency [difference] [11]
\definetransparency [exclusion]  [12]

\setupcolors
  [\c!state=\v!stop,         % will be enabled later on
   \c!conversion=\v!yes,
   \c!reduction=\v!no,
   \c!rgb=\v!yes,
   \c!cmyk=\v!yes,
   \c!spot=\v!yes,
   \c!mp\c!cmyk=\@@clcmyk,
   \c!mp\c!spot=\@@clspot,
   \c!expansion=\v!no,
   \c!textcolor=,
   \c!split=\v!no,           % obsolete
   \c!factor=\v!yes,
   \c!criterium=\v!all]      % obsolete

\appendtoks
    \setupcolors[\c!state=\v!start]% later direct
\to \everyjob

\appendtoks
    \let\showcolormessage\showmessage
\to \everyjob

\setupcolor
  [\v!rgb]

\protect \endinput
