%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\ifconvertGRAY \convertGRAYtrue \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 \unexpanded\def\definecolor {\dodoubleargument\dodefinecolor} \unexpanded\def\defineglobalcolor {\dodoubleargument\dodefineglobalcolor} \unexpanded\def\definenamedcolor {\dodoubleargument\dodefinenamedcolor} \unexpanded\def\definespotcolor {\dotripleargument\dodefinespotcolor} \unexpanded\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{\dosetcolormodel{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]{}}}} \unexpanded\def\startcolorpage {\startcolor[\ifx\maintextcolor\empty\defaulttextcolor\else\maintextcolor\fi]} \unexpanded\def\stopcolorpage {\stopcolor} \unexpanded\def\startraster [#1]{\dosetrastercolor{#1}} \unexpanded\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 Stacking: % \colormodelattribute \colorattribute \transparencyattribute \newcount\currentcolornesting \unexpanded\def\pushcolor[#1]% {\global\advance\currentcolornesting\plusone \expandafter\edef\csname\??cl:s:\number\currentcolornesting\endcsname {\attribute\colormodelattribute \the\attribute\colormodelattribute \attribute\colorattribute \the\attribute\colorattribute \attribute\transparencyattribute\the\attribute\transparencyattribute \space}% stack \doactivatecolor{#1}} \unexpanded\def\popcolor {\csname\??cl:s:\number\currentcolornesting\endcsname \global\advance\currentcolornesting\minusone} %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 \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 \unexpanded\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: \unexpanded\def\definetransparency {\dodoubleargument\dodefinetransparency} \unexpanded\def\setupcolors {\dosingleargument\dosetupcolors} \let\showcolormessage\gobblethreearguments \newtoks\everysetupcolors \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 \convertGRAYtrue \processaction [\@@clconversion] [ \v!yes=>\preferGRAYtrue, \v!no=>\convertGRAYfalse, \v!never=>\convertGRAYfalse, \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 \the\everysetupcolors} %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. \unexpanded\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 \unexpanded\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. \unexpanded\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}% % \dosetcolormodel{#1}} \def\dosetcolormodel#1% no message {\currentcolormodel\ctxlua{tex.print(colors.setmodel('#1',\ifweightGRAY true\else false\fi))}% \attribute\colormodelattribute\currentcolormodel} \dosetcolormodel{all} \def\dosetupcolormodel {\ifincolor \ifRGBsupported \ifCMYKsupported \dosetcolormodel{all}% \else \dosetcolormodel{rgb}% \fi \else \ifCMYKsupported \dosetcolormodel{cmyk}% \else \ifconvertGRAY \dosetcolormodel{gray}% \else \dosetcolormodel{none}% \fi \fi \fi \else \ifconvertGRAY \dosetcolormodel{gray}% \else \dosetcolormodel{none}% \fi \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. \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.enable() transparencies.enable()}% 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 \attribute\colorattribute\ctxlua{tex.sprint(colors.definesimplegray("_raster_",\@@rastervalue))}\relax} \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 \ifx\maintextcolor\empty\else\doactivatecolor\maintextcolor\fi \to \everybeforeoutput \def\registermaintextcolor{\ctxlua{colors.main = \thecolorattribute\maintextcolor}} \unexpanded\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 \appendtoks \initializemaintextcolor \to \everysetupcolors \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 Low level defs: \def\colordefalc#1#2{\setevalue{(ca:#1)}{#2}\setvalue {(cs:#1)}{\attribute\colorattribute #2 }} \def\colordefagc#1#2{\setxvalue{(ca:#1)}{#2}\setvalue {(cs:#1)}{\attribute\colorattribute #2 }} \def\colordefalt#1#2{\setevalue{(ta:#1)}{#2}\setvalue {(ts:#1)}{\attribute\transparencyattribute#2 }} \def\colordefagt#1#2{\setxvalue{(ta:#1)}{#2}\setgvalue{(ts:#1)}{\attribute\transparencyattribute#2 }} \def\colordefflc#1#2{\setvalue {(ca:#1)}{\doinheritca{#2}}\setvalue {(cs:#1)}{\doinheritcs{#2}}} \def\colordeffgc#1#2{\setgvalue{(ca:#1)}{\doinheritca{#2}}\setvalue {(cs:#1)}{\doinheritcs{#2}}} \def\colordefflt#1#2{\setvalue {(ta:#1)}{\doinheritta{#2}}\setvalue {(ts:#1)}{\doinheritts{#2}}} \def\colordeffgt#1#2{\setgvalue{(ta:#1)}{\doinheritta{#2}}\setgvalue{(ts:#1)}{\doinheritts{#2}}} \def\colordefrlc #1{\localundefine {(ca:#1)}\localundefine {(cs:#1)}} \def\colordefrgc #1{\globalundefine{(ca:#1)}\globalundefine{(cs:#1)}} \def\colordefrlt #1{\localundefine {(ta:#1)}\localundefine {(ts:#1)}} \def\colordefrgt #1{\globalundefine{(ta:#1)}\globalundefine{(ts:#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 \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