%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 ADE \& \CONTEXT\ Development Team}]
%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 have to 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{colo-icc}{1.000}

\unprotect

%D In \MKIV\ we have independent color, colorspace and transparency
%D but I'm still not sure if I keep it that way as it's probably more
%D efficient to combine them (less attributes and finalizing). If
%D it becomes a bottleneck we can set up a more complex system
%D with one shared attribute for colorspace, color and transparency.
%D
%D When typesetting for paper, we prefer using the \CMYK\ color space,
%D but for on||screen viewing we prefer \RGB\ (the previous
%D implementation supported only this scheme). Independant of such
%D specifications, we support some automatic conversions:
%D
%D \startitemize[packed]
%D \item  convert all colors to \RGB
%D \item  convert all colors to \CMYK
%D \item  convert all colors to gray scales
%D \stopitemize
%D
%D These options are communicated by means of:

\newconditional\c_colo_rgb_supported
\newconditional\c_colo_cmyk_supported
\newconditional\c_colo_spot_supported   % backend driven
\newconditional\c_colo_weight_gray      \settrue\c_colo_weight_gray
\newconditional\c_colo_convert_gray     \settrue\c_colo_convert_gray
\newconditional\c_colo_enabled
\newconditional\c_colo_expanded

\let\currentcolormodel \empty
\let\currentcolorname  \empty
\let\currentcolorpalet \empty
\let\currentcolorprefix\empty % \currentcolorpalet:

\installcorenamespace{color}
\installcorenamespace{colorattribute}
\installcorenamespace{transparencyattribute}
\installcorenamespace{colorsetter}
\installcorenamespace{transparencysetter}
\installcorenamespace{colorpaletspecification}
\installcorenamespace{colorpalet}
\installcorenamespace{colorstack}
\installcorenamespace{colorconversions}

%D \macros
%D   {definecolor,defineglobalcolor,definenamedcolor,definespotcolor,definemultitonecolor,
%D    definetransparency}
%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

\unexpanded\def\definecolor         {\dodoubleargument\colo_basics_define}
\unexpanded\def\defineglobalcolor   {\dodoubleargument\colo_basics_define_global}
\unexpanded\def\definenamedcolor    {\dodoubleargument\colo_basics_define_named}
\unexpanded\def\definespotcolor     {\dotripleargument\colo_basics_define_spot}
\unexpanded\def\definemultitonecolor{\doquadrupleempty\colo_basics_define_multitone}
\unexpanded\def\definetransparency  {\dodoubleargument\colo_basics_define_transpancy}

%D \macros
%D   {startcolor,stopcolor,color,graycolor}
%D
%D The local and global commands are here just for compatibility
%D with \MKII.
%D
%D \showsetup{startcolor}
%D
%D The simple color commands are:
%D
%D \showsetup{color}
%D \showsetup{graycolor}

%D We expect sane behaviour in \MKIV\ so we don't used grouped command any
%D longer.

% \testfeatureonce{100000}{\color[red]{}} % 1.046 => 0.541

\unexpanded\def\switchtocolor[#1]{\csname#1\endcsname}

\unexpanded\def\color        [#1]{\bgroup
                                  \def\g_color{\colo_helpers_activate{#1}}%
                                  \afterassignment\g_color
                                  \let\nexttoken}

\unexpanded\def\graycolor    [#1]{\bgroup
                                  \def\g_color{\colo_helpers_set_model\s!gray\colo_helpers_activate{#1}}%
                                  \afterassignment\g_color
                                  \let\nexttoken}

\unexpanded\def\startcolor   [#1]{\begingroup
                                  \colo_helpers_activate{#1}}

\unexpanded\def\stopcolor        {\endgroup}

\unexpanded\def\colored      [#1]{\bgroup
                                  \def\g_color{\colo_basics_defined_and_activated{#1}}%
                                  \afterassignment\g_color
                                  \let\nexttoken}

\unexpanded\def\fastcolored[#1]#2{\begingroup % is this command still needed?
                                  \colo_basics_defined_and_activated{#1}%
                                  #2%
                                  \endgroup}

\unexpanded\def\directcolored[#1]{\colo_basics_defined_and_activated{#1}}

\unexpanded\def\fastcolor  [#1]#2{\begingroup % is this command still needed?
                                  \colo_helpers_activate{#1}%
                                  #2%
                                  \endgroup}

\unexpanded\def\directcolor  [#1]{\colo_helpers_activate{#1}}


%D The following command is obsolete:

\unexpanded\def\startcolorpage   {\startcolor[\ifx\maintextcolor\empty\defaulttextcolor\else\maintextcolor\fi]}
\unexpanded\def\stopcolorpage    {\stopcolor}

\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ...
  {\begingroup
   \colo_helpers_activate{#1}%
   \normalexpanded{\endgroup\edef\noexpand#2%
     {\ifnum\attribute\colorattribute=\attributeunsetvalue\else\number\attribute\colorattribute\fi}}}

\let\grey\graycolor % these macros are only used in tracing

%D \macros
%D   {startcurrentcolor,stopcurrentcolor}

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

%D \macros
%D   {setupcolor}
%D
%D Color definitions can be grouped in files with the name:
%D
%D \starttyping
%D colo-imp-tag.tex
%D \stoptyping
%D
%D Loading such a file is done by:
%D
%D \showsetup{usecolors}
%D
%D Some default colors are specified in \type {colo-imp-rgb},
%D which is loaded into the format by default.
%D
%D Some demo palets and groups are defined in \type {colo-imp-dem}
%D which can be loaded with:
%D
%D \starttyping
%D \usecolors[dem]
%D \stoptyping

\unexpanded\def\startcolorset[#1]{\ctxcommand{startcolorset("#1")}}
\unexpanded\def\stopcolorset     {\ctxcommand{stopcolorset()}}
\unexpanded\def\usecolors    [#1]{\ctxcommand{usecolors("#1")}}

\let\setupcolor\usecolors

\installsetuponlycommandhandler \??color {colors}

\let\colo_helpers_show_message\gobblethreearguments

% \newtoks\everysetupcolors

\let\v_colo_freeze_state\s!false
\let\v_colo_weight_state\s!false

\setvalue{\??colorconversions\v!yes}%
  {\settrue \c_colo_convert_gray}

\setvalue{\??colorconversions\v!always}%
  {\settrue \c_colo_convert_gray
   \setfalse\c_colo_rgb_supported
   \setfalse\c_colo_cmyk_supported}

\appendtoks
   %
   \doifelse{\directcolorsparameter\c!spot     }\v!yes  \settrue \setfalse\c_colo_spot_supported
   \doifelse{\directcolorsparameter\c!expansion}\v!yes  \settrue \setfalse\c_colo_expanded
   \doifelse{\directcolorsparameter\c!factor   }\v!no   \setfalse\settrue \c_colo_weight_gray
   \doifelse{\directcolorsparameter\c!rgb      }\v!yes  \settrue \setfalse\c_colo_rgb_supported
   \doifelse{\directcolorsparameter\c!cmyk     }\v!yes  \settrue \setfalse\c_colo_cmyk_supported
   \doifelse{\directcolorsparameter\c!state    }\v!start\settrue \setfalse\c_colo_enabled
   %
   \ifconditional\c_colo_weight_gray
     \let\v_colo_weight_state\s!true
   \else
     \let\v_colo_weight_state\s!false
   \fi
   %
   \ifconditional\c_colo_expanded
     \let\v_colo_freeze_state\s!true
   \else
     \let\v_colo_freeze_state\s!false
   \fi
   %
   \setfalse\c_colo_convert_gray
   \getvalue{\??colorconversions\directcolorsparameter\c!conversion}% could be a nice \ifcsname
   % too often:
   \ifconditional\c_colo_rgb_supported \colo_helpers_show_message\m!colors{10}\v!rgb \fi
   \ifconditional\c_colo_cmyk_supported\colo_helpers_show_message\m!colors{10}\v!cmyk\fi
   \colo_helpers_set_current_model
   \ifproductionrun
     \edef\p_pagecolormodel{\directcolorsparameter\c!pagecolormodel}%
     \ctxcommand{synchronizecolormodel("\ifx\p_pagecolormodel\v!auto \currentcolormodel \else \p_pagecolormodel \fi")}%
   \fi
\to \everysetupcolors

\appendtoks
    \setupcolors[\c!state=\v!start]%
    \ctxcommand{enablecolor()}%           % this can as well happen when
    \ctxcommand{enabletransparency()}%    % the handler is defined in lua
    \let\colo_helpers_show_message\showmessage
\to \everyjob

%D We provide stacking independent of grouping.

\newcount\c_colo_nesting

\unexpanded\def\pushcolor[#1]%
  {\global\advance\c_colo_nesting\plusone
   \expandafter\edef\csname\??colorstack\number\c_colo_nesting\endcsname
     {\attribute\colormodelattribute  \the\attribute\colormodelattribute
      \attribute\colorattribute       \the\attribute\colorattribute
      \attribute\transparencyattribute\the\attribute\transparencyattribute
      \relax}% stack
   \colo_helpers_activate{#1}}

\unexpanded\def\popcolor
  {\csname\??colorstack\number\c_colo_nesting\endcsname
   \global\advance\c_colo_nesting\minusone}

% a simple one: assumes grouping

\newcount\c_colo_saved_attribute_color
\newcount\c_colo_saved_attribute_transparency

\unexpanded\def\savecolor
  {\c_colo_saved_attribute_color       \attribute\colorattribute
   \c_colo_saved_attribute_transparency\attribute\transparencyattribute}

\unexpanded\def\restorecolor
  {\attribute\colorattribute       \c_colo_saved_attribute_color
   \attribute\transparencyattribute\c_colo_saved_attribute_transparency}

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

\let\m_colo_palets_tmp\empty

\unexpanded\def\definepalet
  {\dodoubleargument\colo_palets_define}

\unexpanded\def\colo_palets_define[#1][#2]% todo
  {\doifassignmentelse{#2}
     {%\colo_helpers_show_message\m!colors6{#1}%
      \let\m_colo_palets_tmp\empty
      \setevalue{\??colorpaletspecification#1}{#2}%
      \processcommalist[#2]{\colo_palets_define_one{#1}}%
      \letvalue{\??colorpalet#1}\m_colo_palets_tmp
      \let\m_colo_palets_tmp\empty}
     {\ifcsname\??colorpaletspecification#2\endcsname
        \normalexpanded{\colo_palets_define[#1][\csname\??colorpaletspecification#2\endcsname]}%
      \fi}}

% \def\colo_palets_define_one#1#2% get rid of { } in #2
%   {\colo_palets_define_two{#1}[#2]}%

\def\colo_palets_define_one#1#2% get rid of { }
  {\doifassignmentelse{#2} % catch empty entries
     {\colo_palets_define_two{#1}[#2]}
     {\colo_palets_define_three{#1}{#2}}}

\def\colo_palets_define_two#1[#2=#3]%
  {\edef\m_colo_palets_tmp{\ifx\m_colo_palets_tmp\empty\else\m_colo_palets_tmp,\fi#2}%
   \colo_palets_define_set{#1}{#2}{#3}}%

\def\colo_palets_define_three#1#2%
  {\ifcsname\??colorpaletspecification#2\endcsname
     \processcommacommand[\csname\??colorpaletspecification#2\endcsname]{\colo_palets_define_one{#1}}%
   \fi}

\let\paletsize\!!zerocount

\unexpanded\def\getpaletsize[#1]% only works for valid k=v definitions
  {\getcommacommandsize[\csname\??colorpaletspecification#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}

\newtoks\everysetuppalet

\unexpanded\def\setuppalet
  {\dosingleempty\colo_palets_setup}

\def\colo_palets_setup[#1]%
  {\edef\currentcolorpalet{#1}%
   \ifx\currentcolorpalet\empty
     % seems to be a reset
     \let\currentcolorprefix\empty
   \else\ifcsname\??colorpalet\currentcolorpalet\endcsname
     \edef\currentcolorprefix{#1:}%
   \else
     \colo_helpers_show_message\m!colors7\currentcolorpalet
     \let\currentcolorpalet\empty
     \let\currentcolorprefix\empty
   \fi\fi
   \the\everysetuppalet
   \colo_helpers_initialize_maintextcolor}

%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   {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   {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   {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 \METAPOST\ code that represents the
%D color.
%D
%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 In \MKIV\ we don't support color separation as we might now
%D assume that printing houses have the right programs to do
%D it themselves. If it's ever needed in \MKIV\ It is relatively
%D easy to support it in the backend code.

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

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

\unexpanded\def\setcolormodel[#1]% % beware, \setupcolors will overload this, so this one is
  {\colo_helpers_set_model{#1}}  % only for local usage

\def\colo_helpers_set_model#1% direct
  {\edef\currentcolormodel{#1}%
   \ctxcommand{setcolormodel('\currentcolormodel',\v_colo_weight_state)}} % sets attribute at lua end

\colo_helpers_set_model\s!all

\def\colo_helpers_set_current_model
  {\ifconditional\c_colo_enabled
     \ifconditional\c_colo_rgb_supported
       \ifconditional\c_colo_cmyk_supported
         \colo_helpers_set_model\s!all
       \else
         \colo_helpers_set_model\s!rgb
       \fi
     \else
       \ifconditional\c_colo_cmyk_supported
         \colo_helpers_set_model\s!cmyk
       \else
         \ifconditional\c_colo_convert_gray
           \colo_helpers_set_model\s!gray
         \else
           \colo_helpers_set_model\s!none
         \fi
       \fi
     \fi
   \else
     \ifconditional\c_colo_convert_gray
       \colo_helpers_set_model\s!gray
     \else
       \colo_helpers_set_model\s!none
     \fi
   \fi}

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

\def\v_colo_dummy_name{d_u_m_m_y}

\letvalue{\??colorsetter-}\empty % used?
\letvalue{\??transparencysetter-}\empty % used?

% new: expandable (see tbl)

\def\colo_helpers_fast_activate
  {\ifx\currentcolorprefix\empty
     \expandafter\colo_helpers_fast_activate_nop
   \else
     \expandafter\colo_helpers_fast_activate_yes
   \fi}

\def\colo_helpers_fast_activate_yes#1%
  {\ifcsname\??colorsetter\currentcolorprefix#1\endcsname
     \csname\??colorsetter\currentcolorprefix#1\endcsname
     \csname\??transparencysetter\currentcolorprefix#1\endcsname
   \else\ifcsname\??colorsetter#1\endcsname
     \csname\??colorsetter#1\endcsname
     \csname\??transparencysetter#1\endcsname
   \fi\fi}

\def\colo_helpers_fast_activate_nop#1%
  {\ifcsname\??colorsetter#1\endcsname
     \csname\??colorsetter#1\endcsname
     \csname\??transparencysetter#1\endcsname
   \fi}

\let\dofastcoloractivation\colo_helpers_fast_activate

% so far

\def\colo_helpers_activate % two-step is not that much faster but less tracing
  {\ifx\currentcolorprefix\empty
     \expandafter\colo_helpers_activate_nop
   \else
     \expandafter\colo_helpers_activate_yes
   \fi}

\def\colo_helpers_activate_yes#1%
  {\edef\currentcolorname{#1}%
   \ifcsname\??colorsetter\currentcolorprefix\currentcolorname\endcsname
     \csname\??colorsetter\currentcolorprefix\currentcolorname\endcsname
     \csname\??transparencysetter\currentcolorprefix\currentcolorname\endcsname
   \else\ifcsname\??colorsetter\currentcolorname\endcsname
     \csname\??colorsetter\currentcolorname\endcsname
     \csname\??transparencysetter\currentcolorname\endcsname
   \fi\fi}

\def\colo_helpers_activate_nop#1%
  {\edef\currentcolorname{#1}%
   \ifcsname\??colorsetter\currentcolorname\endcsname
     \csname\??colorsetter\currentcolorname\endcsname
     \csname\??transparencysetter\currentcolorname\endcsname
   \fi}

\def\colo_helpers_activate_dummy
  {\csname\??colorsetter       \v_colo_dummy_name\endcsname
   \csname\??transparencysetter\v_colo_dummy_name\endcsname}

\let\dousecolorparameter\colo_helpers_activate

\unexpanded\def\dousecolorhashparameter#1#2%
  {\ifcsname#1#2\endcsname
     \expandafter\dousecolorparameter\csname#1#2\endcsname
   \fi}

\unexpanded\def\dousecurrentcolorparameter
  {\let\currentcolorname\currentcolorparameter % maybe only when success
   \ifcsname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname
     \csname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname
     \csname\??transparencysetter\currentcolorprefix\currentcolorparameter\endcsname
   \else\ifcsname\??colorsetter\currentcolorparameter\endcsname
     \csname\??colorsetter\currentcolorparameter\endcsname
     \csname\??transparencysetter\currentcolorparameter\endcsname
   \fi\fi}

\let\dosetcolorattribute\dousecolorhashparameter % for a while

\unexpanded\def\deactivatecolor % sort of public but a bad name
  {\let\currentcolorname\s!black
   \attribute\colorattribute\attributeunsetvalue
   \attribute\transparencyattribute\attributeunsetvalue}

\def\colo_basics_define[#1][#2]%
  {\ctxcommand{defineprocesscolor("#1","#2",false,\v_colo_freeze_state)}%
   \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}

\def\colo_basics_define_global[#1][#2]%
  {\ctxcommand{defineprocesscolor("#1","#2",true,\v_colo_freeze_state)}%
   \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}}

\def\colo_basics_define_named[#1][#2]%
  {\ctxcommand{defineprocesscolor("#1","#2",false,\v_colo_freeze_state)}%
   \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}

\def\dodefinefastcolor[#1][#2]% still not fast but ok (might change)
  {\ctxcommand{defineprocesscolor("#1","#2",false,\v_colo_freeze_state)}%
   \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}

\def\colo_basics_defined_and_activated#1%
  {\ctxcommand{defineprocesscolor("\v_colo_dummy_name","#1",false,false)}%
   \colo_helpers_activate_dummy}

% Spotcolors used setxvalue but that messes up currentcolor
% and probably no global is needed either but they are global
% at the lua end (true argument) so we keep that if only because
% spot colors often are a document wide property

\def\colo_basics_define_spot[#1][#2][#3]%
  {\ctxcommand{definespotcolor("#1","#2","#3",true)}%
   \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}}

\def\colo_basics_define_multitone[#1][#2][#3][#4]%
  {\ctxcommand{definemultitonecolor("#1","#2","#3","#4",true)}%
   \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}}

%D Transparencies (only):

\def\colo_basics_define_transpancy[#1][#2]%
  {\ctxcommand{definetransparency("#1",#2)}}

% A goodie that replaces the startMPcolor hackery

% \definecolor[red-t]  [r=1,t=0.5,a=1]
% \definecolor[green-t][g=1,t=0.5,a=1]
%
% \defineintermediatecolor[mycolora][0.5,red,green]
% \defineintermediatecolor[mycolorb][0.5,red-t,green-t]
%
% \definecolor[mycolorc][.5(blue,red)]
% \definecolor[mycolord][.5(blue)]
%
% \enabledirectives[colors.pgf]
% \definecolor[mycolorx][magenta!50!yellow]
%
% \starttext
%     test {\mycolora OEPS} test
%     test {\mycolorb OEPS} test
%     test {\mycolorc OEPS} test
%     test {\mycolord OEPS} test
%     test {\mycolorx OEPS} test
% \stoptext
%
% Beware: if we say:
%
% \definecolor[one][two]
%
% only color one is actually defined and two is not seen at the
% \LUA\ end. This means that this doesn't work:
%
% \definecolor[ColorA][red]
% \definecolor[ColorB][.5(ColorA)]
% \definecolor[ColorC][.5(ColorB,white)]
%
% But this does work:
%
% \definecolor[ColorA][1.0(red)]
% \definecolor[ColorB][0.5(ColorA)]
% \definecolor[ColorC][0.5(ColorB,white)]
%
% because the fractional definition results in a new definition.

\unexpanded\def\defineintermediatecolor
  {\dotripleempty\colo_basics_define_intermediate}

\def\colo_basics_define_intermediate[#1][#2][#3]% \dotripleempty adds {} inside []
  {\colo_basics_define_intermediate_indeed[#1][#2][#3]}

\def\colo_basics_define_intermediate_indeed[#1][#2,#3,#4][#5]%
  {\ctxcommand{defineintermediatecolor("#1","#2",
     \thecolorattribute{#3},\thecolorattribute{#4},
     \thetransparencyattribute{#3},\thetransparencyattribute{#4},
     "#5",false,\v_colo_freeze_state)}% not global
   \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}

%D Here is a more efficient helper for pgf:
%D
%D \starttying
%D \startluacode
%D     function commands.pgfxcolorspec(ca) -- {}{}{colorspace}{list}
%D         local cv = attributes.colors.values[ca]
%D         if cv then
%D             local model = cv[1]
%D             if model == 2 then
%D                 context("{}{}{gray}{%1.3f}",cv[2])
%D             elseif model == 3 then
%D                 context("{}{}{rgb}{%1.3f,%1.3f,%1.3f}",cv[3],cv[4],cv[5])
%D             elseif model == 4 then
%D                 context("{}{}{cmyk}{%1.3f,%1.3f,%1.3f,%1.3f}",cv[6],cv[7],cv[8],cv[9])
%D             else
%D                 context("{}{}{gray}{%1.3f}",cv[2])
%D             end
%D         else
%D             context("{}{}{gray}{0}")
%D         end
%D     end
%D \stopluacode
%D
%D \def\pgfutil@registercolor#1%
%D   {\setevalue{\string\color@#1}{\noexpand\xcolor@\ctxcommand{pgfxcolorspec(\thecolorattribute{#1})}}}
%D
%D \definecolor [darkblue] [r=0,g=0,b=0.5]
%D
%D \starttikzpicture
%D     \fill [blue] (0,0) circle(1);
%D     \fill [darkblue] (0,0) circle(1);
%D \stoptikzpicture
%D \stoptyping
%D
%D \stopmode

\def\pgf@context@registercolor#1% bonus macro
  {\setevalue{\string\color@#1}{\noexpand\xcolor@{}{}\ctxcommand{pgfxcolorspec(\thecolorattribute{#1})}}}

%D \starttyping
%D \ifdefined\pgf@context@registercolor
%D     \let\pgfutil@registercolor\pgf@context@registercolor
%D \fi
%D \stoptyping

%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\??colorattribute\currentcolorprefix#1\endcsname
     \expandafter\firstoftwoarguments
   \else\ifcsname\??colorattribute#1\endcsname
     \doubleexpandafter\firstoftwoarguments
   \else
     \doubleexpandafter\secondoftwoarguments
   \fi\fi}

\def\doifcolor#1%
  {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
     \expandafter\firstofoneargument
   \else\ifcsname\??colorattribute#1\endcsname
     \doubleexpandafter\firstofoneargument
   \else
     \doubleexpandafter\gobbleoneargument
   \fi\fi}

%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

\let\maintextcolor     \empty
\def\defaulttextcolor  {black}
\def\s!themaintextcolor{themaintextcolor}

\unexpanded\def\inheritmaintextcolor
  {\ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi}

\unexpanded\def\onlyinheritmaintextcolor
  {\ifx\maintextcolor\empty
     \deactivatecolor
   \else
     \colo_helpers_activate\maintextcolor
   \fi}

\appendtoks
    \deactivatecolor % public?
    \inheritmaintextcolor
\to \everybeforeoutput

\def\colo_helpers_switch_to_maintextcolor#1%
  {\let\maintextcolor\s!themaintextcolor
   \definecolor[\maintextcolor][#1]% can be fast one
   \colo_helpers_activate\maintextcolor
   \ctxcommand{registermaintextcolor(\thecolorattribute\maintextcolor)}}

\unexpanded\def\starttextcolor[#1]%
  {\doifsomething{#1}
     {\colo_helpers_switch_to_maintextcolor{#1}}}

\let\stoptextcolor\relax

\let\p_colo_textcolor\empty

\def\colo_helpers_initialize_maintextcolor
  {\edef\p_colo_textcolor{\directcolorsparameter\c!textcolor}%
   \ifx\p_colo_textcolor\empty
     \colo_helpers_switch_to_maintextcolor\defaulttextcolor
   \else
     \colo_helpers_switch_to_maintextcolor\p_colo_textcolor
   \fi}

\appendtoks \colo_helpers_initialize_maintextcolor \to \everyjob
\appendtoks \colo_helpers_initialize_maintextcolor \to \everysetupcolors

\def\colo_helpers_inherited_direct_cs#1{\csname\??colorsetter          \ifcsname\??colorsetter          #1\endcsname#1\fi\endcsname}
\def\colo_helpers_inherited_direct_ca#1{\csname\??colorattribute       \ifcsname\??colorattribute       #1\endcsname#1\fi\endcsname}
\def\colo_helpers_inherited_direct_ts#1{\csname\??transparencysetter   \ifcsname\??transparencysetter   #1\endcsname#1\fi\endcsname}
\def\colo_helpers_inherited_direct_ta#1{\csname\??transparencyattribute\ifcsname\??transparencyattribute#1\endcsname#1\fi\endcsname}

\def\colo_helpers_inherited_palet_ca#1#2{\csname\??colorattribute       \ifcsname\??colorattribute       \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
\def\colo_helpers_inherited_palet_cs#1#2{\csname\??colorsetter          \ifcsname\??colorsetter          \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
\def\colo_helpers_inherited_palet_ta#1#2{\csname\??transparencyattribute\ifcsname\??transparencyattribute\??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
\def\colo_helpers_inherited_palet_ts#1#2{\csname\??transparencysetter   \ifcsname\??transparencysetter   \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}

\let\colo_helpers_set_value\setvalue

\appendtoks
   \ifconditional\c_colo_expanded
     \let\colo_helpers_set_value\setevalue
   \else
     \let\colo_helpers_set_value\setvalue
   \fi
\to \everysetupcolors

\def\colo_palets_define_set#1#2#3%
  {\doifassignmentelse{#3}% \definepalet[test][xx={y=.4}]
     {\definecolor[\??colorpalet#1:#2][#3]%
      \colo_helpers_set_value{\??colorsetter          #1:#2}{\colo_helpers_inherited_palet_ca{#1}{#2}}%
      \colo_helpers_set_value{\??colorattribute       #1:#2}{\colo_helpers_inherited_palet_cs{#1}{#2}}%
      \colo_helpers_set_value{\??transparencysetter   #1:#2}{\colo_helpers_inherited_palet_ta{#1}{#2}}%
      \colo_helpers_set_value{\??transparencyattribute#1:#2}{\colo_helpers_inherited_palet_ts{#1}{#2}}}
     {\ifcsname\??colorsetter#3\endcsname % \definepalet[test][xx=green]
        \colo_helpers_set_value{\??colorsetter          #1:#2}{\colo_helpers_inherited_direct_cs{#3}}%
        \colo_helpers_set_value{\??colorattribute       #1:#2}{\colo_helpers_inherited_direct_ca{#3}}%
        \colo_helpers_set_value{\??transparencysetter   #1:#2}{\colo_helpers_inherited_direct_ts{#3}}%
        \colo_helpers_set_value{\??transparencyattribute#1:#2}{\colo_helpers_inherited_direct_ta{#3}}%
      \else
        % not entered when making format
        \localundefine{\??colorsetter          #1:#2}%
        \localundefine{\??colorattribute       #1:#2}%
        \localundefine{\??transparencysetter   #1:#2}%
        \localundefine{\??transparencyattribute#1:#2}%
      \fi}}

\letvalue{\??colorsetter       }\empty \letvalue{\??colorattribute       }\!!zerocount
\letvalue{\??transparencysetter}\empty \letvalue{\??transparencyattribute}\!!zerocount

\setvalue{\??colorattribute        currentcolor}{\the\attribute\colorattribute}        % for mpcolor
\setvalue{\??transparencyattribute currentcolor}{\the\attribute\transparencyattribute} % for mpcolor

\def\colo_helpers_inherited_current_ca#1{\csname\??colorattribute       \ifcsname\??colorattribute       \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute       #1\endcsname#1\fi\fi\endcsname}
\def\colo_helpers_inherited_current_cs#1{\csname\??colorsetter          \ifcsname\??colorsetter          \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorsetter          #1\endcsname#1\fi\fi\endcsname}
\def\colo_helpers_inherited_current_ta#1{\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
\def\colo_helpers_inherited_current_ts#1{\csname\??transparencysetter   \ifcsname\??transparencysetter   \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencysetter   #1\endcsname#1\fi\fi\endcsname}

%D Low level defs:

\unexpanded\def\colordefalc#1#2{\setevalue{\??colorattribute       #1}{#2}\setvalue {\??colorsetter       #1}{\attribute\colorattribute       #2 }}
\unexpanded\def\colordefagc#1#2{\setxvalue{\??colorattribute       #1}{#2}\setgvalue{\??colorsetter       #1}{\attribute\colorattribute       #2 }} % was not g
\unexpanded\def\colordefalt#1#2{\setevalue{\??transparencyattribute#1}{#2}\setvalue {\??transparencysetter#1}{\attribute\transparencyattribute#2 }}
\unexpanded\def\colordefagt#1#2{\setxvalue{\??transparencyattribute#1}{#2}\setgvalue{\??transparencysetter#1}{\attribute\transparencyattribute#2 }}

\unexpanded\def\colordefflc#1#2{\setvalue {\??colorattribute       #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter       #1}{\colo_helpers_inherited_current_cs{#2}}}
\unexpanded\def\colordeffgc#1#2{\setgvalue{\??colorattribute       #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter       #1}{\colo_helpers_inherited_current_cs{#2}}}
\unexpanded\def\colordefflt#1#2{\setvalue {\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setvalue {\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}}
\unexpanded\def\colordeffgt#1#2{\setgvalue{\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setgvalue{\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}}

\unexpanded\def\colordefrlc  #1{\localundefine {\??colorattribute       #1}\localundefine {\??colorsetter       #1}}
\unexpanded\def\colordefrgc  #1{\globalundefine{\??colorattribute       #1}\globalundefine{\??colorsetter       #1}}
\unexpanded\def\colordefrlt  #1{\localundefine {\??transparencyattribute#1}\localundefine {\??transparencysetter#1}}
\unexpanded\def\colordefrgt  #1{\globalundefine{\??transparencyattribute#1}\globalundefine{\??transparencysetter#1}}

%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 \startexample
%D \getbuffer
%D \stopexample

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

\let\colorformatseparator\space

\def\MPcolor                 #1{\ctxcommand{mpcolor(\number\attribute\colormodelattribute,\number\colo_helpers_inherited_current_ca{#1},\number\colo_helpers_inherited_current_ta{#1})}}
\def\MPoptions               #1{\ctxcommand{mpoptions(\number\attribute\colormodelattribute,\number\colo_helpers_inherited_current_ca{#1},\number\colo_helpers_inherited_current_ta{#1})}}

\def\thecolorattribute       #1{\number\csname\??colorattribute       \ifcsname\??colorattribute       \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute       #1\endcsname#1\fi\fi\endcsname}
\def\thetransparencyattribute#1{\number\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}

\def\thecolormodelattribute    {\the\attribute\colormodelattribute}

\def\internalspotcolorname   #1{\ctxcommand{spotcolorname(\thecolorattribute{#1})}}
\def\internalspotcolorparent #1{\ctxcommand{spotcolorparent(\thecolorattribute{#1})}}
\def\internalspotcolorsize   #1{\ctxcommand{spotcolorvalue(\thecolorattribute{#1})}}

\def\colorcomponents         #1{\ctxcommand{colorcomponents(\thecolorattribute{#1})}}
\def\transparencycomponents  #1{\ctxcommand{transparencycomponents(\thetransparencyattribute{#1})}}

\def\colorvalue              #1{\ctxcommand{formatcolor(\thecolorattribute{#1},"\colorformatseparator")}}
\def\grayvalue               #1{\ctxcommand{formatgray (\thecolorattribute{#1},"\colorformatseparator")}}

\def\doifblackelse           #1{\ctxcommand{doifblackelse(\thecolorattribute{#1})}}
\def\doifdrawingblackelse      {\ctxcommand{doifdrawingblackelse()}}

%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\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint}

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

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

%D We default to the colors defined in \type {colo-imp-rgb} and
%D support both \RGB\ and \CMYK\ output. Transparencies are defined
%D here:

\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]
\definetransparency [hue]        [13]
\definetransparency [saturation] [14]
\definetransparency [color]      [15]
\definetransparency [luminosity] [16]

\setupcolors
  [\c!state=\v!stop, % color will be enabled later on
   \c!conversion=\v!yes,
   \c!rgb=\v!yes,
   \c!cmyk=\v!yes,
   \c!spot=\v!yes,
   \c!pagecolormodel=\v!none,
   \c!expansion=\v!no,
   \c!textcolor=,
   \c!factor=\v!yes]

\setupcolor
  [\v!rgb]

\protect \endinput
