colo-new.mkiv / last modification: 2008-05-27 13:08
%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.

\unprotect

\chardef\colorversion=2

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

% check: registerusedspotcolors
% check: registerusedcolorchannels
% check: \currentcolorname
% check: \outercolorname
% check: \chardef\currentcolorchannel=0
% check: \startcolormode
% check: \newif\iffilterspotcolor \filterspotcolorfalse
% check: \newif\ifdoingspotcolor  \doingspotcolorfalse
% check: \registercolorchannel

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

\registerctxluafile{colo-new}{1.000}

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

\def\setcolormodel#1%
  {\currentcolormodel\ctxlua{tex.print(colors.setmodel('colormodel','#1'))}%
   \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}

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

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

% \def\doactivatecolor#1% : in currentpalet, maybe not, ugly
%   {\csname(cs:\ifcsname(cs:\currentpalet#1)\endcsname\currentpalet\fi#1)\endcsname}
%    \csname(ts:\ifcsname(ts:\currentpalet#1)\endcsname\currentpalet\fi#1)\endcsname}
%
% more robust test, else we get \relaxed non-colors which may confuse e.g. mpcolor

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

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

\def\doactivatecolor#1% : in currentpalet, maybe not, ugly
  {\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
  {\doresetattribute\s!color
   \doresetattribute\s!transparency}

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

\def\dodefinecolor[#1][#2]%
  {\addtocommalist{#1}\colorlist
   \ctxlua{ctx.defineprocesscolor("#1","#2",false,\iffreezecolors true\else false\fi)}%
   \dodefinecolorcommand\setvalue{#1}}

\def\dodefineglobalcolor[#1][#2]%
  {\doglobal\addtocommalist{#1}\colorlist
   \ctxlua{ctx.defineprocesscolor("#1","#2",true,\iffreezecolors true\else false\fi)}%
   \dodefinecolorcommand\setgvalue{#1}}

\def\dodefinenamedcolor[#1][#2]%
  {\doglobal\addtocommalist{#1}\colorlist
   \ctxlua{ctx.defineprocesscolor("#1","#2",false,\iffreezecolors true\else false\fi)}%
   \dodefinecolorcommand\setvalue{#1}}

\def\dodefinespotcolor[#1][#2][#3]%
  {\doglobal\addtocommalist{#1}\colorlist % optional
   \doglobal\addtocommalist{#2}\allspotcolors
   \ctxlua{ctx.definespotcolor("#1","#2","#3",true)}%
   \dodefinecolorcommand\setxvalue{#1}}

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

\def\dodefinetransparency[#1][#2]%
  {\ctxlua{ctx.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(ctx.definesimplegray("_raster_",\@@rastervalue))}}}

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

% currentcolor, then we can push pop in register

           \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}}{}}
           \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\localstartraster   [#1]{\dosetrastercolor{#1}}
           \def\localstopraster        {}
           \def\startraster        [#1]{\dosetrastercolor{#1}}
           \def\stopraster             {}
           \def\raster             [#1]{\groupedcommand{\dosetrastercolor{#1}}{}}
           \def\faststartcolor     [#1]{\doactivatecolor{#1}}
           \def\faststopcolor          {}

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

\let\resynccolor  \relax % ?
\let\pushcolor    \relax
\let\popcolor     \relax
\let\popsplitcolor\relax

\def\restorecolormode
  {\ifincolor
     \deactivatecolor
     \ifx\maintextcolor\empty \else
       \doactivatecolor\maintextcolor
     \fi
   \fi}

% \def\pushpostponedpagecolor
%   {\edef\savedtopofpagecolor{\topofpagecolor}%
%    \doifsomething\savedtopofpagecolor\restorecolormode}
%
% \def\poppostponedpagecolor
%    {\doifsomething\savedtopofpagecolor\doactivatecolor\savedtopofpagecolor}
%
% no \topofpagecolor

\let\pushpostponedpagecolor\relax
\let\poppostponedpagecolor \relax

% \def\pushcolor
%   {\edef\popcolor
%      {\dosetattribute\s!color       {\dogetattribute\s!color       }%
%       \dosetattribute\s!transparency{\dogetattribute\s!transparency}}%
%    \let\popsplitcolor\popcolor
%    \deactivatecolor}

\appendtoks\deactivatecolor\to\everybeforeoutput % maybe we don't need push pop now

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

\let\grey            \graycolor
\let\localstartcolor \startcolor
\let\localstopcolor  \stopcolor
\let\globalstartcolor\startcolor
\let\globalstopcolor \stopcolor

\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\localstarttextcolor{\expanded{\startcolor[\ifx\maintextcolor\empty\defaulttextcolor\else\maintextcolor\fi]}}
\let\localstoptextcolor  \stopcolor
\let\restoretextcolor    \firstofoneargument

\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}}
     {\doifdefinedelse{(cs:#3)}% \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}}
        {\letvalue{(cs:#1:#2)}\undefined
         \letvalue{(ca:#1:#2)}\undefined}}}

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

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

\def\currentcolorname{\s!black} % todo
\def\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\PDFcolor     #1{\ctxlua{tex.sprint(ctx.pdfcolor     (\number\currentcolormodel, \thecolorattribute{#1}))}}
\def\PDFcolorvalue#1{\ctxlua{tex.sprint(ctx.pdfcolorvalue(\number\currentcolormodel, \thecolorattribute{#1}))}}
\def\FDFcolor     #1{\ctxlua{tex.sprint(ctx.fdfcolor     (\number\currentcolormodel, \thecolorattribute{#1}))}}

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

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

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

% hack, till we have adapted backend: (move it there)

\def\presetPDFtransparencybynumber#1#2#3%
  {\initializetransparency
   \ifcase#1\else
     \global\PDFcurrenttransparency\numexpr#1+\minusone\relax
     \presetPDFtransparency{#2}{#3}%
   \fi}

\protect \endinput