%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 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. \unprotect \chardef\colorversion=1 % temp, needed for tracing purposes, mkiv transition %D We use a couple of local registers. That way we don't have %D to group when converting colors. By the way, this is not %D really faster. We can sqeeze half a second runtime for 50K %D switches on a 1G machine, but the macros will become rather %D ugly then. To mention one such improvement: no colon %D after the key character (.25 sec). \newdimen\colordimen \newcount\colorcount %D 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 \newif\iflocalcolor \let\colorlist \empty \let\currentspotcolor \empty \let\allspotcolors \empty \let\usedspotcolors \empty \let\usedcolorchannels\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} % check: registerusedspotcolors % check: registerusedcolorchannels %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. \ifx\doifcolorelse\undefined \let\doifcolorelse\secondoftwoarguments \let\doifcolor \gobbleoneargument \fi %D \macros %D {localstartcolor,localstopcolor} %D %D Simple color support, that is without nesting, is provided %D by: \ifx\localstartcolor\undefined \let\localstartcolor\undefined \let\localstopcolor \undefined \fi %D \macros %D {faststartcolor,faststopcolor} %D %D No checking for arguments and such: \ifx\faststartcolor\undefined \def\faststartcolor[#1]{} \def\faststopcolor {} \fi %D These local ones may go away in future versions. %D \macros %D {startcolor,stopcolor} %D %D The more save method, the one that saves the current color %D state and returns to this state afterward, is activated by: %D %D \showsetup{startcolor} \ifx\startcolor\undefined \let\startcolor\undefined \let\stopcolor \undefined \fi %D \macros %D {startcurrentcolor,stopcurrentcolor} \def\startcurrentcolor{\startcolor[\outercolorname]} \def\stopcurrentcolor {\stopcolor} %D \macros %D {color,graycolor} %D %D This leaves the simple color command: %D %D \showsetup{color} %D \showsetup{graycolor} \ifx\color\undefined \def\color [#1]{} \def\graycolor[#1]{} \def\gray {\graycolor} \fi %D \macros %D {localstartraster,localstopraster, %D startraster,stopraster,raster} %D %D The previous conversions are not linear and treat each color %D component according to human perception curves. Pure gray %D (we call them rasters) has equal color components. In %D \CONTEXT\ rasters are only used as backgrounds and these %D don't cross page boundaries in the way color does. Therefore %D we don't need stacks and marks. Just to be compatible with %D color support we offer both 'global' and 'local' commands. \ifx\startraster\undefined \def\startraster [#1]{} \def\stopraster {} \def\raster [#1]{} \def\localstartraster[#1]{} \def\localstopraster {} \fi %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{ } \ifx\colorvalue\undefined \let\colorvalue\gobbleoneargument \let\grayvalue \gobbleoneargument \fi % check: \currentcolorname % check: \outercolorname %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.\mksuffix} {\showmessage\m!colors4\colorstyle} {\readsysfile{\shortfilename.tex} {\showmessage\m!colors4\colorstyle} {\showmessage\m!colors5\colorstyle}}% \stopreadingfile} \let\usecolors\setupcolor % check: \chardef\currentcolorchannel=0 % check: \startcolormode % check: \newif\iffilterspotcolor \filterspotcolorfalse % check: \newif\ifdoingspotcolor \doingspotcolorfalse % check: \registercolorchannel %D \macros %D {definetransparency} %D %D This command numbers to names: \def\definetransparency {\dodoubleargument\dodefinetransparency} \def\setupcolors {\dosingleargument\dosetupcolors} \def\resetcolorsplitting {\chardef\currentcolorchannel\zerocount \let\currentspotcolor\empty \filterspotcolorfalse} \def\colorsplitsuffix{\ifcase\currentcolorchannel\else-\@@clsplit\fi} \def\colorsplitprefix{\ifcase\currentcolorchannel\else\@@clsplit-\fi} \def\setcolorsplitting {\resetsystemmode{\v!color\colorsplitsuffix}% \resetcolorsplitting \processaction [\@@clsplit] [ c=>\chardef\currentcolorchannel1,% m=>\chardef\currentcolorchannel2,% y=>\chardef\currentcolorchannel3,% k=>\chardef\currentcolorchannel4,% r=>\chardef\currentcolorchannel5,% g=>\chardef\currentcolorchannel6,% b=>\chardef\currentcolorchannel7,% s=>\chardef\currentcolorchannel8,% \v!no=>,% \currentcolorchannel0,% all colors \s!default=>,% \currentcolorchannel0,% all colors \s!unknown=>\filterspotcolortrue \edef\currentspotcolor{\commalistelement}]% \setsystemmode{\v!color\colorsplitsuffix}% \iffilterspotcolor \let\@@clrgb\v!no \fi} \ifx\dosetupcolormodel\undefined \let\dosetupcolormodel\relax \fi \def\dosetupcolors[#1]% some no longer make sense in MkIV {\getparameters[\??cl][#1]% \doifelse\@@clspot\v!yes \SPOTsupportedtrue \SPOTsupportedfalse \doifelsenothing\@@clsplit \resetcolorsplitting \setcolorsplitting \doifelse\@@clreduction\v!yes \reduceCMYKtrue \reduceCMYKfalse \doifelse\@@clexpansion\v!yes \freezecolorstrue \freezecolorsfalse \doifelse\@@clcriterium\v!all \hidesplitcolortrue \hidesplitcolorfalse \doifelse\@@clrgb\v!no {\ifRGBsupported \ifproductionrun\showmessage\m!colors {9}\v!rgb \fi\RGBsupportedfalse \fi} {\ifRGBsupported \else\ifproductionrun\showmessage\m!colors{10}\v!rgb \fi\RGBsupportedtrue \fi}% \doifelse\@@clcmyk\v!no {\ifCMYKsupported \ifproductionrun\showmessage\m!colors {9}\v!cmyk \fi\CMYKsupportedfalse\fi} {\ifCMYKsupported\else\ifproductionrun\showmessage\m!colors{10}\v!cmyk \fi\CMYKsupportedtrue \fi}% \doifelse\@@clmpcmyk\v!no {\ifMPcmykcolors \ifproductionrun\showmessage\m!colors {9}{\v!mp\v!cmyk}\fi\MPcmykcolorsfalse \fi} {\ifMPcmykcolors \else\ifproductionrun\showmessage\m!colors{10}{\v!mp\v!cmyk}\fi\MPcmykcolorstrue \fi}% \doifelse\@@clmpspot\v!no {\ifMPspotcolors \ifproductionrun\showmessage\m!colors {9}{\v!mp\v!spot}\fi\MPspotcolorsfalse \fi} {\ifMPspotcolors \else\ifproductionrun\showmessage\m!colors{10}{\v!mp\v!spot}\fi\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\showmessage\m!colors{11}\empty\fi \converttoGRAYtrue \forcegrayMPcolorstrue \convertMPcolorsfalse \reduceMPcolorsfalse \fi\fi \processaction [\@@clstate] [ \v!global=>\ifincolor\else\showmessage\m!colors1\colorstyle\fi \incolortrue\localcolorfalse, \v!local=>\ifincolor\else\showmessage\m!colors2\colorstyle\fi \incolortrue\localcolortrue, \v!start=>\ifincolor\else\showmessage\m!colors1\colorstyle\fi \incolortrue\localcolorfalse \let\@@clstate\v!global, \v!stop=>\incolorfalse\localcolorfalse \forcegrayMPcolorstrue]% \dosetupcolormodel \initializemaintextcolor} %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. \ifx\startregistercolor\undefined \def\startregistercolor[#1]{} \def\stopregistercolor {} \fi %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 \def\maintextcolor {} \def\defaulttextcolor {black} \def\@@themaintextcolor{themaintextcolor} \ifx\initializemaintextcolor\undefined \def\starttextcolor [#1]{} \def\stoptextcolor {} \def\initializemaintextcolor {} \fi \ifx\restoretextcolor\undefined % to be redone \let\restoretextcolor \firstofoneargument \let\localstarttextcolor\relax \let\localstoptextcolor \relax \fi %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} {%\showmessage\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]}}}} \ifx\dodefinepaletcolor\undefined \let\dodefinepaletcolor\gobblethreearguments \fi \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 \showmessage\m!colors7\currentpalet \let\currentpalet\empty \fi\fi} %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 {\doifdefinedelse{\??cr#2:\recurselevel} {\setevalue{\??cr#1:\recurselevel}{\csname\??cr#2:\recurselevel\endcsname}} {\exitloop}}}% \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 \macros %D {PDFcolor,FDFcolor} %D %D Similar alternatives are avaliable for \PDF: %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 %D So, from now on, colors are not frozen any more! \chardef\currentcolorchannel=0 \newif\iffilterspotcolor \filterspotcolorfalse \newif\ifdoingspotcolor \doingspotcolorfalse \def\registercolorchannel#1% {\ifdoingspotcolor \else \global\expandafter\chardef\csname\??cs#1\endcsname\zerocount \fi} \newif\ifhidesplitcolor \hidesplitcolortrue %D The next macro is for instance used in figure splitting: \def\doifseparatingcolorselse {\iffilterspotcolor \@EA\firstoftwoarguments \else\ifcase\currentcolorchannel \@EAEAEA\secondoftwoarguments \else \@EAEAEA\firstoftwoarguments \fi\fi} \def\doifcolorchannelelse#1% {\doifseparatingcolorselse {\doifelsenothing{#1} \secondoftwoarguments {\doifelse{#1}\@@clsplit \firstoftwoarguments \secondoftwoarguments}} \secondoftwoarguments} \def\resetcolorseparation {\filterspotcolorfalse \chardef\currentcolorchannel\zerocount} %D These can be used in selecting specific files (like %D figuredatabases). % we already have: % % \def\colorsplitsuffix{\ifcase\currentcolorchannel\else-\@@clsplitsen\fi} % \def\colorsplitprefix{\ifcase\currentcolorchannel\else\@@clsplitsen-\fi} \def\colorchannelprefix{\doifseparatingcolorselse\@@clsplit\empty-} \def\colorchannelsuffix{-\doifseparatingcolorselse\@@clsplit\empty} %D We now define the low level macros: \chardef\colorversion=1 %D Color support is not present in \TEX. Colorful output can %D however be accomplished by using specials. This also means %D that this support depends on the \DVI\ driver used. At the %D moment this module was written, still no decent standard on %D color specials has been agreed upon. We therefore decided to %D implement a mechanism that is as independant as possible of %D drivers. %D %D Color support shares with fonts that is must be implemented %D in a way that permits processing of individual \DVI\ pages. %D Furthermore it should honour grouping. The first condition %D forces us to use a scheme that keeps track of colors at %D page boundaries. This can be done by means of \TEX's %D marking mechanism (\type{\mark}). %D %D When building pages, \TEX\ periodically looks at the %D accumulated typeset contents and breaks the page when %D suitable. At that moment, control is transfered to the %D output routine. This routine takes care of building the %D pagebody and for instance adds headers and footers. The page %D can be broken in the middle of some colored text, but %D headers and footers are often in black upon white or %D background. If colors are applied there, they definitely %D are used local, which means that they don't cross page %D borders. %D %D Boxes are handled as a whole, which means that when we %D apply colors inside a box, those colors don't cross page %D boundaries, unless of course boxes are split or unboxed. %D Especially in interactive texts, colors are often used in %D such a local way: in boxes (buttons and navigational tools) %D or in the pagebody (backgrounds). %D %D So we can distinguish local colors, that don't cross %D pages from global colors, of which we can end many pages %D later. The color macros will treat both types in a different %D way, thus gaining some speed. %D %D This module also deals with gray scales. Because similar %D colors can end up in the same gray scale when printed in %D black and white, we also implement a palet system that deals %D with these matters. Because of fundamental differences %D between color and gray scale printing, in \CONTEXT\ we also %D differ between these. For historic reasons |<|we first %D implemented gray scales using patterns of tiny periods|>| %D and therefore called them {\em rasters}. So don't be %D surprised if this term shows up. %D \macros %D {definecolor} %D %D We will enable users to specify colors in \cap{RGB} and %D \cap{CMYK} color spaces or gray scales using %D %D \showsetup{definecolor} %D %D For example: %D %D \starttyping %D \definecolor [SomeKindOfRed] [r=.8,g=.05,b=.05] %D \stoptyping %D %D Such color specifications are saved in a macro in the %D following way: %D %D \starttyping %D \setvalue{\??cr name}{R:r:g:b} %D \setvalue{\??cr name}{C:c:m:y:k} %D \setvalue{\??cr name}{S:s} %D \stoptyping %D %D Gray scales are specified with the \type{s} parameter, %D where the \type {s} is derived from {\em screen}. %D %D Starting with \PDF\ 1.4 (2001) \CONTEXT\ supports %D transparent colors. The transparency factor is represented %D by a \type {t} and the transparency method by an \type {a} %D (alternative). Later we will implement more control %D (probably by symbolic methods. So, currently the data is %D stored as follows: %D %D \starttyping %D \setvalue{\??cr name}{R:r:g:b:a:t} %D \setvalue{\??cr name}{C:c:m:y:k:a:t} %D \setvalue{\??cr name}{S:s:a:t} %D \stoptyping % r g b : rbg % c m y k : cmyk % s : gray % p n d f : spot % h : hexadecimal % t a : transparency % e : equivalent (spotcolors) \def\@@cl@@z{0} \def\@@cl@@o{1} \def\@@resetcolorparameters {\let\@@cl@@r\@@cl@@z \let\@@cl@@g\@@cl@@z \let\@@cl@@b\@@cl@@z \let\@@cl@@c\@@cl@@z \let\@@cl@@m\@@cl@@z \let\@@cl@@y\@@cl@@z \let\@@cl@@k\@@cl@@z \let\@@cl@@s\@@cl@@z \let\@@cl@@p\@@cl@@o \let\@@cl@@n\empty \let\@@cl@@d\empty \let\@@cl@@f\@@cl@@o \let\@@cl@@h\empty \let\@@cl@@e\empty \let\@@cl@@t\@@cl@@z \let\@@cl@@a\@@cl@@z} \@@resetcolorparameters \def\@@cl@@A{\@@cl@@a} % a hook for symbolic conversion, see below %D Handling a few nested \type{\cs}'s is no problem (\type %D {\@EA\@EAEAEA\@EA}) but we need a full expansion, so I %D tried one of the fully expandable primitives using a sort %D of delimited thing. I tried \type {\number} first, but this %D does not work, but \type {\romannumeral} does. Actually, %D \type{\romannumeral0} returns nothing, so it's a perfect %D candidate for this kind of hackery. This reminds me that I %D have to look into David Kastrup's Euro\TeX\ 2002 article %D because he is using \type {\romannumeral} for loops %D (repetitive \quote {m} stuff). % \def\x{\y}\def\y{\z}\def\z{0:1:1:1} % % \def\bla #1:#2:#3\end{} % % \@EA\bla\romannumeral\x\end \def\colorXpattern{0S:\@@cl@@z:\@@cl@@z:\@@cl@@z} \def\colorZpattern{0S:\@@cl@@z:\@@cl@@A:\@@cl@@t} \def\colorSpattern{0S:\@@cl@@s:\@@cl@@A:\@@cl@@t} \def\colorCpattern{0C:\@@cl@@c:\@@cl@@m:\@@cl@@y:\@@cl@@k:\@@cl@@A:\@@cl@@t} \def\colorRpattern{0R:\@@cl@@r:\@@cl@@g:\@@cl@@b:\@@cl@@A:\@@cl@@t} %def\colorPpattern{0P:\@@cl@@n:\@@cl@@p:\@@cl@@A:\@@cl@@t} \def\colorPpattern{0P:\@@cl@@n:\@@cl@@f:\@@cl@@d:\@@cl@@p:\@@cl@@A:\@@cl@@t} %D The extra 0 catches empty colors specs (needed for the %D \type {\MPcolor} and \type {\PDFcolor} conversion (\type %D {\@@cr} equals \type {\relax}!). \def\handlecolorwith#1{\@EA#1\romannumeral0} %D Next comes the main definition macro. \def\dodefinecolor {\dododefinecolor\relax \setvalue \setevalue1} \def\dodefineglobalcolor{\dododefinecolor\doglobal\setgvalue\setxvalue1} \def\dodefinenamedcolor {\dododefinecolor\doglobal\setvalue \setevalue0} \let\colorlist\empty % not really used, only for colo-run \setfalse\collectcolorsinlist \def\collectcolorinlist#1{\doglobal\addtocommalist{#1}\colorlist} \def\dododefinecolor#1#2#3#4[#5][#6]% #2==set(g)value #3==set[e|x]value {\ifconditional\collectcolorsinlist\collectcolorinlist{#5}\fi \doifassignmentelse{#6} {\@@resetcolorparameters \getparameters[\??cl @@][#6]% \ifx\@@cl@@h\empty \doifelse{\@@cl@@r\@@cl@@g\@@cl@@b}{\@@cl@@z\@@cl@@z\@@cl@@z} {\doifelse{\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k}{\@@cl@@z\@@cl@@z\@@cl@@z\@@cl@@z} {\doifelse\@@cl@@s\@@cl@@z {\showmessage\m!colors8{{[#6]},#5}% #3{\??cr#5}{\colorZpattern}} {#3{\??cr#5}{\colorSpattern}}} {#3{\??cr#5}{\colorCpattern}}} {#3{\??cr#5}{\colorRpattern}}% \else \setxvalue{\??cr#5}{\colorHpattern}% \fi % new: e=external spot color name \ifx\@@cl@@e\empty \else \doregisterspotcolorname{#5}\@@cl@@e \fi} {\doifelsenothing\currentpalet \donefalse {\doifdefinedelse{\??cr\currentpalet#6}\donetrue\donefalse}% \ifdone \doifnot{#5}{#6} {#2{\??cr#5}{\paletcolorspec{#6}}}% \else \doifdefinedelse{\??cr#6} {\doifelse{#5}{#6} {% this way we can freeze \definecolor[somecolor][somecolor] % and still prevent cyclic definitions \iffreezecolors#3{\??cr#5}{\csname\??cr#6\endcsname}\fi} {\iffreezecolors\@EA#3\else\@EA#2\fi{\??cr#5}{\csname\??cr#6\endcsname}}} {\showmessage\m!colors3{#5 (def)}}% \fi}% \ifcase#4\or \unexpanded#2{#5}{\switchtocolor[#5]}% \unexpanded toegevoegd \fi} \def\paletcolorspec#1% {\csname\??cr\currentpalet#1\endcsname} %D Hex color support is not enabled by default. You need to say \type %D {\setupcolor [hex]} to get this working. \ifx\colorHpattern\undefined \let\colorHpattern\colorZpattern \fi %D New and experimental. \def\dodefinespotcolor[#1][#2][#3]% todo: always global {\doifnot{#1}{#2} {\@@resetcolorparameters \ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi \edef\@@cl@@n{#2}% \getparameters[\??cl @@][#3]% \doifnothing\@@cl@@p{\let\@@cl@@p\!!plusone}% \ifx\@@cl@@e\empty \else \doregisterspotcolorname{#2}\@@cl@@e \fi \doglobal\addtocommalist{#2}\allspotcolors \setxvalue{\??cr#1}{\colorPpattern}% was \setevalue \setgvalue{#1}{\switchtocolor[#1]}}} % was \setvalue \def\registerusedspotcolors {\ifx\allspotcolors\empty \else \bgroup \let\usedspotcolors\empty \def\docommand##1% {\doifdefined{\??cs##1}{\addtocommalist{##1}\usedspotcolors}}% \processcommacommand[\allspotcolors]\docommand \savecurrentvalue\usedspotcolors\usedspotcolors \egroup \fi} \def\registerusedcolorchannels {\bgroup \doifdefinedelse{\??cs c} {\def\usedcolorchannels{c,m,y,k}}% {\let\usedcolorchannels\empty}% \doifdefined{\??cs r} {\addtocommalist{r,g,b}\usedcolorchannels}% \doifdefined{\??cs s} {\ExpandBothAfter\doifnotinset{k}\usedcolorchannels {\addtocommalist{s}\usedcolorchannels}}% \savecurrentvalue\usedcolorchannels\usedcolorchannels \egroup} \prependtoks \registerusedspotcolors \registerusedcolorchannels \to \everylastshipout \def\registerusedspotcolor#1% {\global\@EA\chardef\csname\??cs#1\endcsname\zerocount} %D On top of spotcolors, we define multitone colors. You'd better know %D what you're doing because invalid definitions will lead to invalid %D documents (i.e.\ resources). % \definecolor [darkblue] [c=.5,m=.5] % \definecolor [darkyellow] [y=.5] % % \definemultitonecolor [whatever] [darkblue=.5,darkyellow=.5] [c=.25,m=.25,y=.25] [a=1,t=.5] % \definemultitonecolor [another] [darkblue=.5,darkyellow=.5] [c=.25,m=.25,y=.25] \def\dodefinemultitonecolor[#1][#2][#3][#4]% {\let\@@cl@@cl@@D\empty % n's \let\@@cl@@cl@@P\empty % p's \let\@@cl@@cl@@N\empty % name \scratchcounter\zerocount \processcommacommand[#2]\dododefinemultitonecolor \bgroup \lccode`\.=`\_% \lccode`\,=`\_% \lccode`\:=`\_% \lccode`\;=`\_% \lccode`\+=`\_% \lccode`\-=`\_% \lccode`\*=`\_% \lccode`\/=`\_% % \lccode`\_=`\_% % not needed, other attribute in driver: % % \@@resetcolorparameters % \getparameters[#4]% % \ifx\@@cl@@t\@@cl@@z\else % \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\@@cl@@t_\@@cl@@a}% % \fi \lowercase\@EA{\@EA\xdef\@EA\@@cleancolor\@EA{\@@cl@@cl@@N}}% \egroup \setxvalue{\??cl\@@cleancolor\s!check}{\noexpand\docheckmultitonecolor{\@@cl@@cl@@D}}% \expanded{\defineglobalcolor[\@@cleancolor][#3,#4]}% \expanded{\definespotcolor[#1][\@@cleancolor][#4,f=\the\scratchcounter,p={\@@cl@@cl@@P},d={\@@cl@@cl@@D}]}} \def\docheckmultitonecolor#1% {\flushatshipout {\let\checkmultitonecolor\gobbleoneargument \def\docommand##1{\hbox{\definecolor[\s!dummy-100][##1][p=1]\color[\s!dummy-100]}}% \processcommalist[#1]\docommand}} \def\checkmultitonecolor#1% {\csname\??cl#1\s!check\endcsname\letgvalue{\??cl#1\s!check}\relax} \def\dodefinespotcolor[#1][#2][#3]% todo: always global (REDEFINED) {\doifnot{#1}{#2} {\@@resetcolorparameters \ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi \edef\@@cl@@n{#2}% \getparameters[\??cl @@][#3]% \doifnothing \@@cl@@p{\let\@@cl@@p\!!plusone}% \doifsomething\@@cl@@e{\doregisterspotcolorname{#2}\@@cl@@e}% \doglobal\addtocommalist{#2}\allspotcolors \setxvalue{\??cr#1}{\colorPpattern}% was \setevalue \setgvalue{#1}{\switchtocolor[#1]}}}% was \setvalue \def\dododefinemultitonecolor#1% {\advance\scratchcounter\plusone \splitstring#1\at=\to\!!stringa\and\!!stringb \ifx\@@cl@@cl@@D\empty \let\@@cl@@cl@@D\!!stringa \let\@@cl@@cl@@P\!!stringb \normalizecolor\!!stringb \edef\@@cl@@cl@@N{\!!stringa_\!!stringb}% \else \edef\@@cl@@cl@@D{\@@cl@@cl@@D,\!!stringa}% \edef\@@cl@@cl@@P{\@@cl@@cl@@P,\!!stringb}% \normalizecolor\!!stringb \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\!!stringa_\!!stringb}% \fi} % \def\dododefinemultitonecolor#1% a/b safe % {\advance\scratchcounter\plusone % \splitstring#1\at=\to\@@cl@@one\and\@@cl@@two % \ifx\@@cl@@cl@@D\empty % \let\@@cl@@cl@@D\@@cl@@one % \let\@@cl@@cl@@P\@@cl@@two % \normalizecolor\@@cl@@two % \edef\@@cl@@cl@@N{\@@cl@@one_\@@cl@@two}% % \else % \edef\@@cl@@cl@@D{\@@cl@@cl@@D,\@@cl@@one}% % \edef\@@cl@@cl@@P{\@@cl@@cl@@P,\@@cl@@two}% % \normalizecolor\@@cl@@two % \edef\@@cl@@cl@@N{\@@cl@@cl@@N_\@@cl@@one_\@@cl@@two}% % \fi} %D The names of colors are stored in a comma separated list %D only for the purpose of showing them with \type {\showcolor}. %D %D \startbuffer %D \definecolor [SomeKindOfRed] [r=.8,g=.05,b=.05] %D \stopbuffer %D %D \typebuffer %D \getbuffer %D %D This color shows up as \color [SomeKindOfRed] {some kind %D of red}. %D %D \starttyping %D \setupcolors[state=start] %D %D \definecolor[mygreen][green] %D \definecolor[green][g=.5] %D %D \startcolor[mygreen]test\stopcolor %D %D \setupcolors[expansion=no] %D %D \definecolor[mygreen][green] %D \definecolor[green][g=.5] %D %D \startcolor[mygreen]test\stopcolor %D \stoptyping %D \macros %D {startcolormode,stopcolormode,permitcolormode} %D %D We use \type{\stopcolormode} to reset the color in %D whatever color space and do so by calling the corresponding %D special. Both commands can be used for fast color %D switching, like in colored verbatim, \newif\ifpermitcolormode \permitcolormodetrue \def\dowithcolor#1#2% #1=\action #2=color {\ifincolor\ifpermitcolormode \ifcsname\??cr\currentpalet#2\endcsname \handlecolorwith#1\csname\??cr\currentpalet#2\endcsname\od \else\ifcsname\??cr#2\endcsname \handlecolorwith#1\csname\??cr#2\endcsname\od \fi\fi \fi\fi} \def\startcolormode % includes \ifincolor\ifpermitcolormode {%\dostoptransparency % needed for: {test \trans test \notrans test} \conditionalstoptransparency \dowithcolor\execcolorRCSP} \def\stopcolormode {\ifincolor\ifpermitcolormode \supportedstoptransparency \dostopcolormode \fi\fi} \def\restorecolormode {\ifincolor\ifpermitcolormode \supportedstoptransparency \dostopcolormode \ifx\maintextcolor\empty \else \startcolormode\maintextcolor \fi \fi\fi} %D Color modes are entered using the next set of commands. %D The \type{\stop} alternatives are implemented in a way %D that permits non||grouped use. %D %D The, for this module redundant, check if we are in color %D mode is needed when we use these macros in other modules. \def\execcolorRCSP#1:% {\csname execcolor#1\endcsname} \def\execcolorR {\iffilterspotcolor \@EA\noexeccolorR \else \@EA\doexeccolorR \fi} \def\execcolorC {\iffilterspotcolor \@EA\noexeccolorC \else \@EA\doexeccolorC \fi} \def\execcolorS {\iffilterspotcolor \@EA\noexeccolorS \else \@EA\doexeccolorS \fi} \def\execcolorP {\iffilterspotcolor \@EA\doexeccolorPP \else\ifcase\currentcolorchannel \@EAEAEA\doexeccolorP \else \@EAEAEA\noexeccolorP \fi\fi} \def\doexeccolorR#1:#2:#3:% {\edef\@@cl@@r{#1}\edef\@@cl@@g{#2}\edef\@@cl@@b{#3}% \ifpreferGRAY\ifx\@@cl@@r\@@cr@@g\ifx\@@cl@@r\@@cl@@b \GRAYpreferedtrue \fi\fi\fi \ifincolor\else\RGBsupportedfalse\CMYKsupportedfalse\fi \ifGRAYprefered \registercolorchannel\c!s \let\@@cl@@s\@@cl@@r \normalizeGRAY \doexeccolorgray \else\ifRGBsupported \registercolorchannel\c!r \normalizeRGB \doexeccolorrgb \else\ifCMYKsupported \registercolorchannel\c!c \convertRGBtoCMYK\@@cl@@r\@@cl@@g\@@cl@@b \normalizeCMYK \doexeccolorcmyk \else \registercolorchannel\c!s \convertRGBtoGRAY\@@cl@@r\@@cl@@g\@@cl@@b \normalizeGRAY \doexeccolorgray \fi\fi\fi \exectransparency} \def\doexeccolorC#1:#2:#3:#4:% {\edef\@@cl@@c{#1}\edef\@@cl@@m{#2}\edef\@@cl@@y{#3}\edef\@@cl@@k{#4}% \ifpreferGRAY\ifx\@@cl@@k\@@cl@@z\ifx\@@cl@@c\@@cr@@m\ifx\@@cl@@c\@@cl@@y \GRAYpreferedtrue \fi\fi\fi\fi \ifincolor\else\RGBsupportedfalse\CMYKsupportedfalse\fi \ifGRAYprefered \registercolorchannel\c!s \let\@@cl@@s\@@cl@@c \normalizeGRAY \doexeccolorgray \else\ifCMYKsupported \registercolorchannel\c!c \ifreduceCMYK \convertCMYKtoCMY\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k \fi \normalizeCMYK \doexeccolorcmyk \else\ifRGBsupported \registercolorchannel\c!r \convertCMYKtoRGB\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k \normalizeRGB \doexeccolorrgb \else \registercolorchannel\c!s \convertCMYKtoGRAY\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k \normalizeGRAY \doexeccolorgray \fi\fi\fi \exectransparency} \def\doexeccolorS#1:% {\edef\@@cl@@s{#1}% \registercolorchannel\c!s \normalizeGRAY \doexeccolorgray \exectransparency} % \def\doexeccolorP#1:#2:% % {\edef\@@cl@@n{#1}% % \edef\@@cl@@p{#2}% % \registerusedspotcolor\@@cl@@n % \ifSPOTsupported % \dowithcolor\registerspotcolor\@@cl@@n % \dostartspotcolormode\@@cl@@n\@@cl@@p % \else % \doingspotcolortrue % \let\spotcolorfactor\@@cl@@p % \factorizecolortrue % using counter and array % \dowithcolor\execcolorRCSP\@@cl@@n % \factorizecolorfalse % \let\spotcolorfactor\@@cl@@o % \doingspotcolorfalse % \fi % \exectransparency} \def\doexeccolorP#1:#2:#3:#4:% {\edef\@@cl@@n{#1}% name \edef\@@cl@@f{#2}% fractions \edef\@@cl@@d{#3}% definitions \edef\@@cl@@p{#4}% \ifx\@@cl@@d\empty \let\@@cl@@d\@@cl@@n \fi \registerusedspotcolor\@@cl@@n \ifSPOTsupported \checkmultitonecolor\@@cl@@n \dowithcolor\registerspotcolor\@@cl@@n \dostartspotcolormode\@@cl@@n\@@cl@@p \else \doingspotcolortrue \normalizespotcolor\@@cl@@p \let\spotcolorfactor\@@cl@@p \factorizecolortrue % using counter and array \dowithcolor\execcolorRCSP\@@cl@@n \factorizecolorfalse \let\spotcolorfactor\@@cl@@o \doingspotcolorfalse \fi \exectransparency} \def\doexeccolorPindex#1:#2:#3:#4:% {\edef\@@cl@@n{#1}% \edef\@@cl@@f{#2}% \edef\@@cl@@d{#3}% \edef\@@cl@@p{#4}% \ifx\@@cl@@d\empty \let\@@cl@@d\@@cl@@n \fi \ifSPOTsupported \checkmultitonecolor\@@cl@@n \dowithcolor\registerindexcolor\@@cl@@n \fi \noexectransparency} \def\doexeccolorPP#1:#2:% {\edef\@@cl@@n{#1}% \edef\@@cl@@p{#2}% \registerusedspotcolor\@@cl@@n \ifx\@@cl@@n\currentspotcolor \normalizeSPOT \dostartgraycolormode\@@cl@@p % was spotcolormode \else \dovidecolor\@@cl@@p\@@cl@@o \fi \exectransparency} \def\doexeccolorrgb {\ifcase\currentcolorchannel \dostartrgbcolormode\@@cl@@r\@@cl@@g\@@cl@@b \or \or \or \or \or \dostartgraycolormode\@@cl@@r \or \dostartgraycolormode\@@cl@@g \or \dostartgraycolormode\@@cl@@b \fi} \def\doexeccolorcmyk {\ifcase\currentcolorchannel \dostartcmykcolormode\@@cl@@c\@@cl@@m\@@cl@@y\@@cl@@k \or \negatecolorcomponent\@@cl@@c\dostartgraycolormode\@@cl@@c \or \negatecolorcomponent\@@cl@@m\dostartgraycolormode\@@cl@@m \or \negatecolorcomponent\@@cl@@y\dostartgraycolormode\@@cl@@y \or \negatecolorcomponent\@@cl@@k\dostartgraycolormode\@@cl@@k \fi} \def\doexeccolorgray {\ifcase\currentcolorchannel \dostartgraycolormode\@@cl@@s \or \or \or \or \dostartgraycolormode\@@cl@@s \or \or \or \or \dostartgraycolormode\@@cl@@s \fi} %D When filtering colors, we need to either erase %D the background, or ignore the foreground. % \newif\ifhidesplitcolor \hidesplitcolortrue % % \def\noexeccolor#1\od % {\dostartgraycolormode\@@cl@@o} % % \let\noexeccolorS\noexeccolor % \let\noexeccolorP\noexeccolor %D Well, here comes some real trickery. When we have the 100\% %D spot color or black color, we don't want to erase the %D background. So, instead we hide the content by giving it %D zero transparency. % todo : #1#2#3 met #2 > of < and #3 een threshold \def\dohidecolor#1#2% {\ifhidesplitcolor \ifx#1#2% \dostartgraycolormode\@@cl@@o \else \doregisternonecolor \dostartnonecolormode \fi \else \dostartgraycolormode\@@cl@@o \fi} \def\dovidecolor#1#2% {\ifhidesplitcolor \ifx#1#2% \doregisternonecolor \dostartnonecolormode \else \dostartgraycolormode\@@cl@@o \fi \else \dostartgraycolormode\@@cl@@o \fi} % \def\fullytransparentcolor % fails on floats % {\dostartgraycolormode\@@cl@@o % better than z % %\global\@EA\chardef\csname\@@currenttransparent\endcsname\plusone % %\global\intransparenttrue % \dostarttransparency10} \def\noexeccolorR#1:#2:#3:#4\od {\edef\@@cl@@r{#1}\edef\@@cl@@g{#2}\edef\@@cl@@b{#3}% \dohidecolor\@@cl@@s\@@cl@@o} \def\noexeccolorC#1:#2:#3:#4:#5\od {\edef\@@cl@@c{#1}\edef\@@cl@@m{#2}\edef\@@cl@@y{#3}\edef\@@cl@@k{#4}% \dohidecolor\@@cl@@s\@@cl@@o} \def\noexeccolorS#1:#2\od {\edef\@@cl@@s{#1}% \dohidecolor\@@cl@@s\@@cl@@o} \def\noexeccolorP#1:#2:#3:#4:#5\od {\edef\@@cl@@p{#4}% \dohidecolor\@@cl@@p\@@cl@@z} %D For the sake of postprocessing (i.e.\ color separation) %D we can normalize colors, which comes down to giving equal %D values an equal accuracy and format. This feature is %D turned off by default due to a speed penalty. This macro %D also handles spot color percentages. \newif\iffactorizecolor \newif\ifnormalizecolor \def\spotcolorfactor{1} % \def\normalizecolor#1% % {\colordimen#1\thousandpoint % \colordimen\spotcolorfactor\colordimen % \colorcount\colordimen % \advance\colorcount \medcard % \divide\colorcount \maxcard % \edef#1{\realcolorvalue\colorcount}} \def\normalizecolor#1% {\colorcount\numexpr(\dimexpr\spotcolorfactor\dimexpr#1\thousandpoint\relax\relax+\medcard)/\maxcard\relax \edef#1{\realcolorvalue\colorcount}} % \def\normalizespotcolor#1% % {\colordimen-#1\thousandpoint % \advance\colordimen\thousandpoint % \colorcount\colordimen % \advance\colorcount \medcard % \divide\colorcount \maxcard % \edef#1{\realcolorvalue\colorcount}} \def\normalizespotcolor#1% {\colorcount\numexpr(\dimexpr\thousandpoint-#1\thousandpoint\relax+\medcard)/\maxcard\relax \edef#1{\realcolorvalue\colorcount}} \def\donormalizeRGB {\normalizecolor\@@cl@@r \normalizecolor\@@cl@@g \normalizecolor\@@cl@@b} \def\normalizeRGB {\ifnormalizecolor \donormalizeRGB \else\iffactorizecolor \donormalizeRGB \fi\fi} \def\donormalizeCMYK {\normalizecolor\@@cl@@c \normalizecolor\@@cl@@m \normalizecolor\@@cl@@y \normalizecolor\@@cl@@k} \def\normalizeCMYK {\ifnormalizecolor \donormalizeCMYK \else\iffactorizecolor \donormalizeCMYK \fi\fi} \def\donormalizeGRAY {\normalizecolor\@@cl@@s} \def\normalizeGRAY {\ifnormalizecolor \donormalizeGRAY \else\iffactorizecolor \donormalizeGRAY \fi\fi} \def\normalizeSPOT {\normalizespotcolor\@@cl@@p} %D We need to register spot colors (i.e.\ resources need to %D be created. \def\registerspotcolor#1:% {\ifcsname\??cl:\c!p:\@@cl@@n\endcsname \@EA\dontregisterspotcolor \else \letgvalue{\??cl:\c!p:\@@cl@@n}\empty %\@EA\@EA\csname registerspotcolor#1\endcsname \csname registerspotcolor#1\@EA\endcsname \fi} % todo: convert to rgb if needed, will will do this in mkiv \def\dontregisterspotcolor #1\od{} \def\registerspotcolorR #1:#2:#3:#4\od{\doregisterrgbspotcolor \@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}} \def\registerspotcolorC#1:#2:#3:#4:#5\od{\doregistercmykspotcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}{#4}} \def\registerspotcolorS #1:#2\od{\doregistergrayspotcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}} \def\registerspotcolorP #1:#2:#3\od{\doregistergrayspotcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#2}} %D Experimental feature: % \definecolor [darkblue] [c=1,m=.38,y=0,k=.64] % pantone pms 2965 uncoated m % \definecolor [darkyellow] [c=0,m=.28,y=1,k=.06] % pantone pms 124 uncoated m % % \definecolor [darkblue-50] [darkblue] [p=.5] % \definecolor [darkyellow-50] [darkyellow] [p=.5] % \definecolor [darkblue-80] [darkblue] [p=.8] % \definecolor [darkyellow-80] [darkyellow] [p=.8] % % \definecolor [darkblue,darkyellow] [r=.8] % \definecolor [darkdull-5030] [darkblue,darkyellow] [p={.5,.3}] % % \setupcolors[state=start] % % \blackrule[width=4cm,height=3cm,color=darkblue-50] % \blackrule[width=4cm,height=3cm,color=darkblue-80] % \blackrule[width=4cm,height=3cm,color=darkyellow-50] % \blackrule[width=4cm,height=3cm,color=darkyellow-80] % \blackrule[width=4cm,height=3cm,color=darkdull-5030] %D Experimental too (special purpose code). \def\registerindexcolor#1:% {\ifcsname\??cl:i:\@@cl@@n\endcsname \@EA\dontregisterindexcolor \else \letgvalue{\??cl:i:\@@cl@@n}\empty % signal \showmessage\m!colors{12}\@@cl@@n \@EA\@EA\csname registerindexcolor#1\endcsname \fi} \let\dontregisterindexcolor\dontregisterspotcolor \def\registerindexcolorR #1:#2:#3:#4\od{\doregisterrgbindexcolor \@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}} \def\registerindexcolorC#1:#2:#3:#4:#5\od{\doregistercmykindexcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}{#2}{#3}{#4}} \def\registerindexcolorS #1:#2\od{\doregistergrayindexcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#1}} \def\registerindexcolorP #1:#2:#3\od{\doregistergrayindexcolor\@@cl@@n\@@cl@@f\@@cl@@d\@@cl@@p{#2}} \def\predefinecolor[#1]% {\bgroup \flushatshipout{\hbox{\localcolortrue\color[#1]{}}}% real ones \egroup} \def\predefineindexcolor[#1]% {\bgroup \flushatshipout{\hbox{\localcolortrue\color[#1]{}}}% real ones \let\doexeccolorP\doexeccolorPindex \flushatshipout{\hbox{\localcolortrue\color[#1]{}}}% index one \egroup} % \def\checkpredefinedcolor[#1]% % {\ifcase\internalspotcolorsize{#1}\relax % \@EA\predefinecolor\or\@EA\predefinecolor\else\@EA\predefineindexcolor % \fi[#1]} \let\checkpredefinedcolor\predefineindexcolor % we need an index in order to negate bitmaps %D Transparency is handled similar for all three color modes. We %D can turn transparency off with the following switch: \newif\iftransparencysupported \transparencysupportedtrue % only mkii \def\exectransparency {\iftransparencysupported \expandafter\doexectransparency \else \expandafter\noexectransparency \fi} \def\doexectransparency#1:#2\od {\ifcase#1\space \global\intransparentfalse \else \global\intransparentfalse %\dostarttransparency{#1}{#2}% \supportedstarttransparency{#1}{#2}% \global\intransparenttrue \fi} \def\noexectransparency#1\od {} %D Experimental: minimize transparency resets. \newif\ifintransparent \newif\ifoptimizetransparency \optimizetransparencytrue % under test \let\supportedstoptransparency\relax \def\conditionalstoptransparency {\ifoptimizetransparency \ifintransparent \global\intransparentfalse \supportedstoptransparency \fi \else \supportedstoptransparency \fi} \def\supportedstarttransparency {\iftransparencysupported \globallet\supportedstoptransparency\dostoptransparency \expandafter\dostarttransparency \else \expandafter\gobbletwoarguments \fi} %D We now use the \type {\@@cl@@A} hook to implement %D symbolic names. These are converted into numbers %D at definition time (which saves runtime). \def\dodefinetransparency[#1][#2]% {\@EA\chardef\csname\??cl-#1\endcsname#2\relax} \def\transparencynumber#1% {\number\executeifdefined{\??cl-#1}{#1}} %D Now we hook 'm into the patterns: \def\@@cl@@A{\transparencynumber\@@cl@@a} %D The next macro can be used to return to the (normal) %D page color. This macro is used in the same way as %D \type {\color}. \def\startregistercolor[#1]% {\permitcolormodefalse\startcolor[#1]\permitcolormodetrue} \def\stopregistercolor {\permitcolormodefalse\stopcolor\permitcolormodetrue} \def\starttextcolor[#1]% {\doifsomething{#1} {\bgroup \def\stoptextcolor % also goes ok with \page after {\let\maintextcolor\empty % this one because the top of \stopregistercolor % page sets the color right (side \egroup}% % effect) \def\starttextcolor[##1]% {\bgroup % \@@themaintextcolor==##1 is catched in \definecolor \definecolor[\@@themaintextcolor][##1]% \let\stoptextcolor\egroup}% \startregistercolor[\@@themaintextcolor]% \definecolor[\@@themaintextcolor][#1]% \let\maintextcolor\@@themaintextcolor}} \let\stoptextcolor\relax %D The following hook permits proper support at the text %D level. This definition actually belongs in another %D module. (May need a different \MKIV\ implementation.) % \ifx\initializemaintextcolor\undefined \let\@@clprevcolor\empty \def\initializemaintextcolor {% saveguard for setting text color to empty after % it has been set \doifnothing\@@cltextcolor {\ifx\@@clprevcolor\empty\else \let\@@cltextcolor\defaulttextcolor \fi}% \doifelsenothing\@@cltextcolor {\let\maintextcolor\empty} {\edef\@@clprevcolor{\@@cltextcolor}% \let\maintextcolor\@@themaintextcolor \doifelsenothing\@@cltextcolor % another saveguard {\definecolor[\@@themaintextcolor][\defaulttextcolor]}% {\definecolor[\@@themaintextcolor][\@@cltextcolor]}% \doinitializemaintextcolor}} \def\doinitializemaintextcolor {\appendtoks\starttextcolor[\@@themaintextcolor]\to\everystarttext \appendtoks\stoptextcolor \to\everystoptext \let\doinitializemaintextcolor\relax} % \fi \def\localstarttextcolor {\ifx\maintextcolor\empty \startcolormode\defaulttextcolor \else \startcolormode\maintextcolor \fi} % \def\localstoptextcolor % {\stopcolormode} % % better: \def\localstoptextcolor {\restorecolormode} \def\restoretextcolor {\ifx\maintextcolor\empty \expandafter\dorestoretextcolor \else % obey main text color \fi} \def\dorestoretextcolor {\color[\defaulttextcolor]} %D We use some reserved names for local color components. %D Consistent use of these scratch variables saves us %D unneccessary hash entries. %D %D \starttyping %D \@@cl@@r \@@cl@@g \@@cl@@b %D \@@cl@@c \@@cl@@m \@@cl@@y \@@cl@@k %D \@@cl@@s %D \stoptyping %D %D We implement several conversion routines. %D %D \starttyping %D \convertRGBtoCMYK {r} {g} {b} %D \convertRGBtoGRAY {r} {g} {b} %D \convertCMYKtoRGB {c} {m} {y} {k} %D \convertCMYKtoGRAY {c} {m} {y} {k} %D \convertCMYKtoCMY {c} {m} {y} {k} %D \stoptyping %D %D The relation between \cap{Gray}, \cap{RGB} and \cap{CMYK} %D is: %D %D \placeformula[-] %D \startformula %D G = .30r + .59g + .11b %D = 1.0 - \min(1.0,\ .30c + .59m + .11y + k) %D \stopformula %D %D When converting from \cap{CMYK} to \cap{RGB} we use the %D formula: %D %D \placeformula[-] %D \startformula %D \eqalign %D {r &= 1.0 - \min(1.0,\ c+k) \cr %D g &= 1.0 - \min(1.0,\ m+k) \cr %D b &= 1.0 - \min(1.0,\ y+k)} %D \stopformula %D %D In the conversion routine the color components are calculated %D in three digits precision. \def\realcolorvalue#1% {\ifnum#1>\zerocount % important, first encountered in --modu supp-mpe \ifnum#1<\plusten 0.00\the#1\else \ifnum#1<\plushundred 0.0\the#1\else \ifnum#1<\plusthousand 0.\the#1\else 1\fi\fi\fi \else 0\fi} % \def\doconvertCMYKtoRGB#1\k#2\to#3% % {\ifdim#2\points>#1\points% >= problem, repaired 2/12/2002 % \let#3\@@cl@@z % k >= color % \else % \colordimen\onepoint % \advance\colordimen -#1\points % \advance\colordimen -#2\points % \multiply\colordimen \plusthousand % \colorcount\colordimen % \advance\colorcount \medcard % \divide\colorcount \maxcard % \edef#3{\realcolorvalue\colorcount}% % \fi} \def\doconvertCMYKtoRGB#1\k#2\to#3% {\colorcount\numexpr(\dimexpr\plusthousand\dimexpr\onepoint-#1\points-#2\points\relax\relax+\medcard)/\maxcard\relax \ifnum\colorcount>\zeropoint \edef#3{\realcolorvalue\colorcount}% \else \let#3\@@cl@@z \fi} \def\convertCMYKtoRGB#1#2#3#4% {\doconvertCMYKtoRGB#1\k#4\to\@@cl@@r \doconvertCMYKtoRGB#2\k#4\to\@@cl@@g \doconvertCMYKtoRGB#3\k#4\to\@@cl@@b} % \def\doconvertRGBtoCMYK#1\to#2% % {\colordimen#1\points % \multiply\colordimen \plusthousand % \colorcount\colordimen % \advance\colorcount \medcard % \divide\colorcount \maxcard % \colorcount-\colorcount % \advance\colorcount \plusthousand % \edef#2{\realcolorvalue\colorcount}} \def\doconvertRGBtoCMYK#1\to#2% {\colorcount\numexpr\plusthousand-(\dimexpr\plusthousand\dimexpr#1\points\relax\relax+\medcard)/\maxcard\relax \edef#2{\realcolorvalue\colorcount}} \def\convertRGBtoCMYK#1#2#3% {\doconvertRGBtoCMYK#1\to\@@cl@@c \doconvertRGBtoCMYK#2\to\@@cl@@m \doconvertRGBtoCMYK#3\to\@@cl@@y \let\@@cl@@k\@@cl@@z} %D The following switch is mainly meant for (hidden) %D documentation purposes. \def\nGRAYfactor{333.333} \def\rGRAYfactor{\ifweightGRAY300\else\nGRAYfactor\fi} \def\gGRAYfactor{\ifweightGRAY590\else\nGRAYfactor\fi} \def\bGRAYfactor{\ifweightGRAY110\else\nGRAYfactor\fi} % \def\convertRGBtoGRAY#1#2#3% % {\colordimen#1\points % \colordimen\rGRAYfactor\colordimen % \colorcount\colordimen % \colordimen#2\points % \colordimen\gGRAYfactor\colordimen % \advance\colorcount \colordimen % \colordimen#3\points % \colordimen\bGRAYfactor\colordimen % \advance\colorcount \colordimen % \advance\colorcount \medcard % \divide\colorcount \maxcard % \edef\@@cl@@s{\realcolorvalue\colorcount}} \def\convertRGBtoGRAY#1#2#3% {\colorcount\numexpr (\dimexpr\rGRAYfactor\dimexpr#1\points\relax\relax+ \dimexpr\gGRAYfactor\dimexpr#2\points\relax\relax+ \dimexpr\bGRAYfactor\dimexpr#3\points\relax\relax+ \medcard)/\maxcard \relax \edef\@@cl@@s{\realcolorvalue\colorcount}} \def\convertCMYKtoGRAY#1#2#3#4% {\convertCMYKtoRGB{#1}{#2}{#3}{#4}% \convertRGBtoGRAY\@@cl@@r\@@cl@@g\@@cl@@b} % \def\doconvertCMYKtoCMY#1\k#2\to#3% % {\colordimen#1\points % \advance\colordimen #2\points\relax % \ifdim\colordimen>\onepoint % \colordimen\onepoint % %\else % % \colordimen\colordimen % \fi % \multiply\colordimen \plusthousand % \colorcount\colordimen % \advance\colorcount \medcard % \divide\colorcount \maxcard % \edef#3{\realcolorvalue\colorcount}} \def\doconvertCMYKtoCMY#1\k#2\to#3% {\colorcount\numexpr(\dimexpr\plusthousand\dimexpr#1\points+#2\points\relax\relax+\medcard)/\maxcard\relax \ifnum\colorcount>\plusthousand \let#3\@@cl@@o \else \edef#3{\realcolorvalue\colorcount}% \fi} \def\convertCMYKtoCMY#1#2#3#4% {\doconvertCMYKtoCMY#1\k#4\to\@@cl@@c \doconvertCMYKtoCMY#2\k#4\to\@@cl@@m \doconvertCMYKtoCMY#3\k#4\to\@@cl@@y \let\@@cl@@k\@@cl@@z} %D Before we present the color macros, we first define the %D setup command. This command takes care of setting up the %D booleans that control local and global behavior (more on %D that later) and conversion to other color spaces. \let\currentspotcolor \empty \let\previousspotcolor\empty %D The tests depend on the use of constants. If we use the \MKIV\ %D method we can share more. \def\doifcolorelse#1% {\ifcsname\??cr\ifcsname\??cr\currentpalet#1\endcsname\currentpalet\fi#1\endcsname \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} \def\doifcolor#1% {\ifcsname\??cr\ifcsname\??cr\currentpalet#1\endcsname\currentpalet\fi#1\endcsname \expandafter\firstofoneargument \else \expandafter\gobbleoneargument \fi} %D There are a couple of different color switching macros, %D the local ones can be used to speed up things (only in \MKII). \def\localstartcolor {\ifincolor \localcolortrue \expandafter\doglobalstartcolor \else \expandafter\noglobalstartcolor \fi} \def\localstopcolor {\ifincolor \doglobalstopcolor \else \noglobalstopcolor \fi} \unexpanded\def\startcolor {\ifincolor \expandafter\doglobalstartcolor \else \expandafter\noglobalstartcolor \fi} \unexpanded\def\stopcolor {\ifincolor \doglobalstopcolor \else \noglobalstopcolor \fi} %D This macros call the global color switching ones. Starting %D a global, i.e. a possible page boundary crossing, color %D mode also sets a \type{\mark} in \TEX's internal list. \newcount\colorlevel \letvalue{\??cl0C}\empty % saved color \letvalue{\??cl0S}\empty % stop command %D We keep a positive color stack for foreground colors, and %D a negative one for backgrounds. Not that brilliant a %D solution, but it suits. The signs are swapped when the %D page ornaments are typeset. \let\@@colorplus \plusone \let\@@colorminus\minusone \def\@@currentcolorname {\??cl\the\colorlevel C} \def\@@currentcolorstop {\??cl\the\colorlevel S} %def\@@currenttransparent{\??cl\the\colorlevel T} \letvalue{\??cl*\s!black}\s!black \def\currentcolorname {\csname \ifcsname\@@currentcolorname\endcsname \expandafter\ifx\csname\@@currentcolorname\endcsname\empty \??cl*\s!black \else \@@currentcolorname \fi \else \??cl*\s!black \fi \endcsname} \def\outercolorname {\ifcsname\@@currentcolorname\endcsname \expandafter\ifx\csname\@@currentcolorname\endcsname\empty \s!black \else currentcolor% \fi \else \s!black \fi} % not the following, because we need a different tag in order to trick the stack % % \def\outercolorname{\executeifdefined\@@currentcolorname\s!black} % % \def\startcurrentcolor{\expanded{\startcolor[\s!black]\noexpand\startcolor[\outercolorname]}} % \def\stopcurrentcolor {\stopcolor\stopcolor} % % test case: % % \setupcolors[state=start,textcolor=red] % \starttext % red % \color[green]{green % \startMPcode % label(\sometxt{green\color[blue]{blue}green}, origin) withcolor red; % draw fullcircle scaled 1cm xscaled 2; % \stopMPcode % green} % red % \stoptext \def\dodoglobalstartcolor {\global\@EA\let\@EA\@@currentcolor\csname\@@currentcolorname\endcsname \global\advance\colorlevel \@@colorplus \global\@EA\let\csname\@@currentcolorname\endcsname\@@askedcolor %\debuggerinfo\m!colors % {start \@@askedcolor\space at level \the\colorlevel}% \ifx\@@askedcolor\empty \global\@EA\let\csname\@@currentcolorname\endcsname\@@currentcolor \global\@EA\let\csname\@@currentcolorstop\endcsname\donoglobalstopcolor \else\ifx\@@askedcolor\@@currentcolor \global\@EA\let\csname\@@currentcolorstop\endcsname\donoglobalstopcolor \else \doifcolorelse\@@askedcolor {%\docolormark\@@askedcolor \ifpermitcolormode\docolormark\@@askedcolor\fi \global\@EA\let\csname\@@currentcolorstop\endcsname\dodoglobalstopcolor \startcolormode\@@askedcolor} {\global\@EA\let\csname\@@currentcolorstop\endcsname\donoglobalstopcolor \showmessage\m!colors3\@@askedcolor\empty}% \fi\fi} \def\doglobalstartcolor[#1]% {\edef\@@askedcolor{#1}% \ifcase\colorlevel\relax \ifx\@@askedcolor\empty \global\@EA\let\csname\@@currentcolorstop\endcsname\empty \else \dodoglobalstartcolor \fi \else \dodoglobalstartcolor \fi \ignorespaces} \def\noglobalstartcolor[#1]% {} \def\dodoglobalstopcolor {\ifcase\colorlevel \else \donoglobalstopcolor \global\@EA\let\@EA\@@previouscolor\csname\@@currentcolorname\endcsname \ifcase\colorlevel\relax \ifpermitcolormode \docolormark\empty \conditionalstoptransparency \dostopcolormode \fi \else % let's do a bit redundant testing here \docolormark\@@previouscolor \ifx\@@previouscolor\empty \ifpermitcolormode \conditionalstoptransparency \dostopcolormode \fi \else \doifcolorelse\@@previouscolor {\ifx\@@currentcolor\@@previouscolor\else % alternatively we could let \startcolormode handle this \ifpermitcolormode \conditionalstoptransparency % really needed % more safe but less efficient: \dostopcolormode \fi \startcolormode\@@previouscolor \fi} {\ifpermitcolormode \conditionalstoptransparency \dostopcolormode \fi}% \fi \fi \fi} \def\donoglobalstopcolor {\ifcase\colorlevel \else \global\@EA\let\@EA\@@currentcolor\csname\@@currentcolorname\endcsname %\debuggerinfo{\m!colors} % {stop \@@currentcolor\normalspace at level \the\colorlevel}% \global\advance\colorlevel \@@colorminus \fi} \def\doglobalstopcolor {\csname\@@currentcolorstop\endcsname} \let\noglobalstopcolor\relax \let\faststartcolor\doglobalstartcolor \let\faststopcolor \doglobalstopcolor %D We don't use grouping and save each stop alternative. This %D permits be especially useful in for instance local color %D support in verbatim. Using \type{\bgroup}||\type{\egroup} %D pairs could interfere with calling commands %D This color mechanism takes care of nested colors, like in: %D %D \startbuffer %D \color[green]{groen \color[green]{groen \color[red]{rood}} groen} %D \color[green]{groen \color[]{groen \color[red]{rood}} groen} %D \color[green]{groen \color[red]{rood \color[red]{rood}} groen} %D \color[green]{groen \color[green]{groen \color[]{groen}} groen} %D \color[green]{groen \color[red]{rood} groen} %D \color[green]{groen \color[]{groen} groen} %D \color[]{zwart \color[red]{rood} zwart} %D \color[]{zwart} %D \stopbuffer %D %D \typebuffer %D %D or %D %D \startvoorbeeld %D \startlines %D \getbuffer %D \stoplines %D \stopvoorbeeld %D %D Crossing page boundaries is of course also handled. %D Undefined or empty color specifications are treated as %D efficient as possible. %D %D \startbuffer %D \startcolor[green] %D [green] \input tufte [green] \par %D \startcolor[] %D [green] \input knuth [green] \par %D \startcolor[red] %D [red] \input tufte [red] \par %D \startcolor[yellow] %D [yellow] \input knuth [yellow] \par %D \stopcolor %D [red] \input tufte [red] \par %D \stopcolor %D [green] \input knuth [green] \par %D \stopcolor %D [green] \input tufte [green] \par %D \stopcolor %D \stopbuffer %D %D \startpacked %D \getbuffer %D \stoppacked %D %D These quotes are typeset by saying: %D %D \typebuffer %D We already mentioned that colors interfere with building %D the pagebody. This means that when the page is composed, %D the colors temporary have to be reset. After the page is %D shipped out, we have to revive the current color. %D %D We use \type{\mark}s to keep track of colors across page %D boundaries. Unfortunately standard \TEX\ supports only one mark, %D and using this one for color support only would be a waste. %D We therefore use an adapted version of J.~Fox's multiple mark %D mechanism as (re|)|implemented in \module{supp-mrk}. \doifdefinedelse{rawnewmark} {\rawnewmark\colormark} {\let\colormark\gobbleoneargument} %D Using this mark mechanism with lots of colors has one %D major drawback: \TEX's memory tends to overflow when %D very colorful text is stored in a global box. Even worse is that %D the processing time grows considerably. We therefore support %D local as well as global color switching. %D %D Of the next macros, \type {\popcolor} is to be used after %D the actual \type {\shipout} and \type {\startcolorpage} and %D \type {\stopcolorpage} are called when entering and leaving %D the \type {\pagebody} builder. In case of emergencies %D \type {\pushcolor} can be used to undo the current color, %D for instance when insertions are appended to the page. %D %D Out of efficiency we only use marks when needed. The next %D macro tries to find out if indeed a mark should be set. %D This macro uses the boolean \type {\ifinpagebody}, which can %D be defined and set in the module that handles the pagebody. \def\docolormark#1% {\iflocalcolor \else \ifinpagebody \else \ifinframed \else \dodocolormark{#1}% \fi \fi \fi} \let\lastcolormark=\empty \def\dodocolormark#1% {\edef\newcolormark{#1}% \ifx\newcolormark\lastcolormark\else \global\let\lastcolormark\newcolormark \@EA\rawsetmark\@EA\colormark\@EA{\lastcolormark}% \fi} %D \macros %D {pushcolor, popcolor} %D %D Pushing the current state in the output routine simply comes %D to resetting the color to black, while popping restores the %D color state to that of before the break. \def\topofpagecolor{\rawgetbotmark\colormark} % see postponing \def\pushcolor {\stopcolormode} \def\popcolor {\doifsomething{\rawgetbotmark\colormark} {%\debuggerinfo\m!colors{popping \getbotmark\colormark}% \startcolormode{\rawgetbotmark\colormark}}} \def\popsplitcolor {\getsplitmarks\colormark % hier wel \doifsomething{\rawgetsplitbotmark\colormark} {%\debuggerinfo\m!colors{split popping \getsplitbotmark\colormark}% \startcolormode{\rawgetsplitbotmark\colormark}}} \appendtoks\pushcolor \to\everypushproperties \appendtoks\popcolor \to\everypopproperties \appendtoks\popsplitcolor\to\everypopsplitproperties % Private macro: only needed in test cases (like multiple % seperations in one file); no user command! \def\resynccolor {\ifcase\pagetotal % \ifdim\pagetotal=\zeropoint \popcolor \else\ifx\@@currentcolor\empty \ifx\maintextcolor\empty\else \startcolormode\maintextcolor \fi \else \startcolormode\@@currentcolor \fi\fi} % weird stuff \def\pushpostponedpagecolor {\edef\savedtopofpagecolor{\topofpagecolor}% \doifsomething\savedtopofpagecolor\restorecolormode} % \stopcolormode \def\poppostponedpagecolor {\doifsomething\savedtopofpagecolor\startcolormode\savedtopofpagecolor} %D \macros %D {startcolorpage, stopcolorpage} %D %D Local use can be forced with the next two macros. Nesting %D is still supported but colors are no longer marked. %D %D The next implementation makes (simple) color separation more %D easy. It also supports nested colors in page backgrounds %D and texts. \def\startcolorpage {\bgroup \let\@@colorplus \minusone \let\@@colorminus\plusone \let\docolormark\gobbleoneargument \edef\savedcolorlevel{\the\colorlevel}% \global\colorlevel\zerocount % before \localstartcolor of \ifx\maintextcolor\empty % course, ugly bug removed \localstartcolor[\defaulttextcolor]% \else \localstartcolor[\maintextcolor]% \fi} \def\stopcolorpage {\localstopcolor \global\colorlevel\savedcolorlevel \egroup} \appendtoks \startcolorpage\to\everystarttextproperties \prependtoks\stopcolorpage \to\everystoptextproperties %D We want color support to be similar to font support and %D therefore implement \type{\color} using grouping. %D %D When \type {\somecolor} is issued, we can savely assume %D grouping. Using \type {\groupedcommand} here (i.e.\ the %D definition of \type {\color}) is unsafe because in %D interferes with for instance switching attributes. \unexpanded\def\color[#1]% {\groupedcommand{\startcolor[#1]}\stopcolor} %D This implementation enables use of defined colors like: %D %D \starttyping %D Look at the {\brightgreen bright} side of life and get %D yourself no \red{red} head! %D \stoptyping %D Also wrong, test in combinations: \type{...{}{\red test}} %D %D \def\switchtocolor[#1]% %D {\startcolor[#1]\aftergroup\stopcolor} \def\switchtocolor[#1]% grouping is realy needed, else migration {\bgroup\startcolor[#1]\aftergroup\stopcolor\aftergroup\egroup} \unexpanded\def\color[#1]% {\groupedcommand{\startcolor[#1]}\stopcolor} \unexpanded\def\graycolor[#1]% not \gray because this is a color {\groupedcommand{\RGBsupportedfalse\CMYKsupportedfalse\SPOTsupportedfalse\startcolor[#1]}\stopcolor} \unexpanded\def\colored[#1]% {\groupedcommand{\definecolor[@colored@][#1]\startcolor[@colored@]}\stopcolor} %D We can speed the following macros a bit up, but this %D hardly pays off; they are only used in the manual. \def\realcolorformat#1% {\ifnum#1<\plusten 0.00\the#1\else \ifnum#1<\plushundred 0.0\the#1\else \ifnum#1<\plusthousand 0.\the#1\else 1.000\fi\fi\fi} \def\dodoformatcolor#1% {\colordimen#1\points\relax \ifdim\colordimen>\onepoint \colordimen\onepoint \fi \multiply\colordimen \plusthousand \colorcount\colordimen \advance\colorcount \medcard \divide\colorcount \maxcard \relax \realcolorformat\colorcount} \def\doformatcolorR#1:#2:#3:#4:#5\od {\dodoformatcolor{#1}\colorformatseparator \dodoformatcolor{#2}\colorformatseparator \dodoformatcolor{#3}} \def\doformatcolorC#1:#2:#3:#4:#5:#6\od {\dodoformatcolor{#1}\colorformatseparator \dodoformatcolor{#2}\colorformatseparator \dodoformatcolor{#3}\colorformatseparator \dodoformatcolor{#4}} \def\doformatcolorS#1:#2:#3\od {\dodoformatcolor{#1}} \def\doformatcolorP#1:#2:#3:#4:#5:#6\od {#1\colorformatseparator \dodoformatcolor{#2}\colorformatseparator \dodoformatcolor{#3}\colorformatseparator \dodoformatcolor{#4}\colorformatseparator} \def\doformatcolor#1:% {\csname doformatcolor#1\endcsname} \def\colorvalue {\dowithcolor\doformatcolor} \def\doformatgrayR#1:#2:#3:#4:#5\od {\convertRGBtoGRAY{#1}{#2}{#3}% \dodoformatcolor\@@cl@@s} \def\doformatgrayC#1:#2:#3:#4:#5:#6\od {\convertCMYKtoGRAY{#1}{#2}{#3}{#4}% \dodoformatcolor\@@cl@@s} \def\doformatgrayS#1:#2:#3\od {\dodoformatcolor{#1}} % \def\doformatgrayP#1:#2:#3:#4:#5:#6\od % {\convertSPOTtoGRAY{#1}{#2}{#3}{#4}% % \dodoformatcolor\@@cl@@s} \def\doformatgrayP#1:#2:#3:#4:#5:#6\od {todo} \def\doformatgray#1:% {\csname doformatgray#1\endcsname} \def\grayvalue {\dowithcolor\doformatgray} %D \macros %D {localstartraster,localstopraster, %D startraster,stopraster} %D %D The previous conversions are not linear and treat each color %D component according to human perception curves. Pure gray %D (we call them rasters) has equal color components. In %D \CONTEXT\ rasters are only used as backgrounds and these %D don't cross page boundaries in the way color does. Therefore %D we don't need stacks and marks. Just to be compatible with %D color support we offer both 'global' and 'local' commands. %D %D \starttyping %D \def\localstartraster[#1]% %D {\doifelsenothing{#1} %D {\dostartgraymode\@@rsscreen} %D {\dostartgraymode{#1}}} %D %D \def\localstopraster %D {\dostopgraymode} %D %D \let\startraster\localstartraster %D \let\stopraster \localstopraster %D \stoptyping %D %D The next alternative is slower, since it works on top of the %D color (stack) mechanism, but it does provide nesting. \def\dosetrastercolor#1% {\edef\@@cl@@s{#1}% \ifx\@@cl@@s\empty \let\@@cl@@s\@@rsscreen \fi \let\@@cl@@t\@@cl@@z % else we get rogue \let\@@cl@@a\@@cl@@z % transpancies \setevalue{\??cr\??rs}{\colorSpattern}} % beware, don't add extra grouping, else color in tables % fails \def\localstartraster[#1]% {\ifincolor\dosetrastercolor{#1}\localstartcolor[\??rs]\fi} \def\startraster[#1]% {\ifincolor\dosetrastercolor{#1}\startcolor[\??rs]\fi} \def\localstopraster{\ifincolor\localstopcolor\fi} \def\stopraster {\ifincolor\stopcolor\fi} \def\raster[#1]{\groupedcommand{\startraster[#1]}{\stopraster}} %D Palets use an auxiliary macro: \def\dodefinepaletcolor#1#2#3% {\doifassignmentelse{#3} {% == \definepalet[test][xx={y=.4}] \definecolor[\??pa#1:#2][#3]% \iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{\??cr#1:#2}{\csname\??cr\??pa#1:#2\endcsname}} {% == \definepalet[test][xx=green] \doifdefinedelse{\??cr#3} {\iffreezecolors\@EA\setevalue\else\@EA\setvalue\fi{\??cr#1:#2}{\csname\??cr#3\endcsname}} {\letvalue{\??cr#1:#2}\colorXpattern}}} %D \MP\ related conversions: \def\scaledMPcolor#1#2% {\ifMPgraphics \handlecolorwith\doMPcolor \csname\??cr \ifcsname\??cr\currentpalet#2\endcsname\currentpalet\fi #2\endcsname :::::::\end#1\end \else #2% \fi} \def\MPcolor{\scaledMPcolor1} %D Before we had transparency available, the following %D conversion macro was available: %D %D \starttyping %D \def\doMPcolor#1:#2:#3:#4:#5:#6:#7:#8\end %D {\if #1R(#2,#3,#4)% %D \else\if#1C\ifMPcmykcolors cmyk(#2,#3,#4,#5)\else(1-#2-#5,1-#3-#5,1-#4-#5)\fi %D \else\if#1S(#2,#2,#2)% %D \else (0,0,0)% %D \fi\fi\fi} %D \stoptyping %D %D In order to be useful, this macro is to be fully %D expandabele. \def\doMPcolor#1:% #1 can be \relax ! ! ! i.e. an empty color {\csname MPc\@EA\ifx\csname MPc\string#1\endcsname\relax B\else#1\fi\endcsname} \def\MPcR{\doMPrgb} \def\MPcC{\ifMPcmykcolors\@EA\doMPcmykY\else\@EA\doMPcmykN\fi} \def\MPcS{\doMPgray} \def\MPcP{\ifMPspotcolors\@EA\doMPspotY\else\@EA\doMPspotN\fi} \def\MPcB{\doMPblack} \def\transparentMP {transparent} \def\cmykMP {scaledcmyk} \def\cmykASrgbMP {scaledcmykasrgb} % not really needed any more \def\rgbMP {scaledrgb} \def\grayMP {scaledgray} \def\spotMP {spotcolor} \def\doMPtransparent#1#2:#3:#4\end {\ifcase#2\space(#1)\else\transparentMP(#2,#3,(#1))\fi} \def\doMPgray#1:#2\end#3\end {\doMPtransparent{\grayMP(#1,#3)}#2\end} \def\doMPrgb#1:#2:#3:#4\end#5\end {\doMPtransparent{\rgbMP(#1,#2,#3,#5)}#4\end} \def\doMPcmykY#1:#2:#3:#4:#5\end#6\end {\doMPtransparent{\cmykMP(#1,#2,#3,#4,#6)}#5\end} \def\doMPcmykN#1:#2:#3:#4:#5\end#6\end {\doMPtransparent{\cmykASrgbMP(#1,#2,#3,#4,#6)}#5\end} \def\doMPspotY#1:#2:#3:#4:#5\end#6\end % best make #3 same as #1 when empty {\doMPtransparent{multitonecolor("#1",#2,"#3","#4")}#5\end} \def\doMPspotN#1:#2:#3:#4:#5\end#6\end {\scaledMPcolor{#4}{#1}} \def\doMPblack#1\end#2\end {\unknownMPcolor} \def\unknownMPcolor {(0,0,0)} \let\processMP\spotMP % for some time, will become obsolete, brrr %D \PDF\ related conversions: \def\PDFcolor #1{\handlecolorwith\doPDFcolor \csname\??cr#1\endcsname:::::::\end} \def\PDFcolorvalue#1{\handlecolorwith\doPDFcolorvalue\csname\??cr#1\endcsname:::::::\end} \def\FDFcolor #1{\handlecolorwith\doFDFcolor \csname\??cr#1\endcsname:::::::\end} \def\doPDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end {\if #1R#2 #3 #4 rg% \else\if#1C#2 #3 #4 #5 k% \else\if#1S#2 g% \else\if#1P#5 g% \else 0 g% \fi\fi\fi\fi} \def\doPDFcolorvalue#1:#2:#3:#4:#5:#6:#7:#8\end {\if #1R#2 #3 #4% \else\if#1C#2 #3 #4 #5% \else\if#1S#2% \else\if#1P#5% \else 0% \fi\fi\fi\fi} \def\doFDFcolor#1:#2:#3:#4:#5:#6:#7:#8\end {[\if #1R#2 #3 #4% \else\if#1C#2 #3 #4 #5% \else\if#1S#2% \else\if#1P#5% \else 0% \fi\fi\fi\fi]} \def\internalspotcolorname#1{\handlecolorwith\dointernalspotcolorname\csname\??cr#1\endcsname:::::::\end} \def\internalspotcolorsize#1{\handlecolorwith\dointernalspotcolorsize\csname\??cr#1\endcsname:::::::\end} \def\dointernalspotcolorname#1:#2:#3:#4:#5:#6:#7:#8\end{\if#1P\ifcase0#3 #1\else#2\fi\else#1\fi} \def\dointernalspotcolorsize#1:#2:#3:#4:#5:#6:#7:#8\end{\if#1P\ifcase0#3 0\else#3\fi\else 0\fi} %D Because it's a persitent issue, we also provide \def\pgf@context@registercolor#1% {\handlecolorwith\pgf@context@registercolor@indeed\csname\??cr#1\endcsname:::::::>#1\end} \def\pgf@context@registercolor@indeed#1:#2:#3:#4:#5:#6>#7\end {\setevalue{\string\color@#7}{\noexpand\xcolor@{}{}% \if#1R{rgb}{#2,#3,#4}\else \if#1C{cmyk}{#2,#3,#4,#5}\else \if#1S{gray}{#2}\else {gray}{0}\fi\fi\fi}} %D Slow but ok \unknown \def\colorcomponents#1% might be broken {\startnointerference \localcolortrue \globallet\thecolorcomponents\empty \def\doexeccolorR ##1:##2:##3:##4:##5\od{\gdef\thecolorcomponents{r=\twodigitrounding{##1} g=\twodigitrounding{##2} b=\twodigitrounding{##3}}}% \def\doexeccolorC##1:##2:##3:##4:##5:##6\od{\gdef\thecolorcomponents{c=\twodigitrounding{##1} m=\twodigitrounding{##2} y=\twodigitrounding{##3} k=\twodigitrounding{##4}}}% \def\doexeccolorS ##1:##2:##3\od{\gdef\thecolorcomponents{s=\twodigitrounding{##1}}}% \def\doexeccolorP##1:##2:##3:##4:##5:##6\od{\gdef\thecolorcomponents{p=\twodigitrounding{##4} n=##1}}% \let\doexeccolorPindex\doexeccolorP \backgroundline[#1]{}% \stopnointerference \thecolorcomponents} \def\transparencycomponents#1% {\startnointerference \localcolortrue \globallet\thetransparencycomponents\empty \def\doexeccolorR ##1:##2:##3:##4:##5\od{\gdef\thetransparencycomponents{a=\twodigitrounding{##4} t=\twodigitrounding{##5}}}% \def\doexeccolorC##1:##2:##3:##4:##5:##6\od{\gdef\thetransparencycomponents{a=\twodigitrounding{##5} t=\twodigitrounding{##6}}}% \def\doexeccolorS ##1:##2:##3\od{\gdef\thetransparencycomponents{a=\twodigitrounding{##2} t=\twodigitrounding{##3}}}% \def\doexeccolorP##1:##2:##3:##4:##5:##6\od{\gdef\thetransparencycomponents{a=\twodigitrounding{##5} t=\twodigitrounding{##6}}}% \let\doexeccolorPindex\doexeccolorP \backgroundline[#1]{}% \stopnointerference \thetransparencycomponents} %D \macros %D {everyshapebox} %D %D A terrible hack, needed because we cannot have marks in %D shape boxes. \appendtoks \localcolortrue \to \everyshapebox %D \macros %D {forcecolorhack} %D %D Awful \unknown \let\forcecolorhack\relax %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] \definetransparency [hue] [13] \definetransparency [saturation] [14] \definetransparency [color] [15] \definetransparency [luminosity] [16] \setupcolors [\c!state=\v!stop, \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, \c!criterium=\v!all] \setupcolor [\v!rgb] \protect \endinput