% language=us runpath=texruns:manuals/luametafun \environment luametafun-style \startcomponent luametafun-color \startchapter[title={Color}] \startsection[title=Lab colors] There are by now plenty of examples made by users that use color and \METAFUN\ provides all kind of helpers. So do we need more? When I play around with things or when users come with questions that then result in a nice looking graphic, the result might en dup as example of coding. The following is an example of showing of colors. We have a helper that goes from a so called lab specification to rgb and it does that via xyz transformations. It makes no real sense to interface this beyond this converter. We use this opportunity to demonstrate how to make an interface. \startbuffer \startMPdefinitions vardef cielabmatrix(expr l, mina, maxa, minb, maxb, stp) = image ( for a = mina step stp until maxa : for b = minb step stp until maxb : draw (a,b) withcolor labtorgb(l,a,b) ; endfor ; endfor ; ) enddef ; \stopMPdefinitions \stopbuffer \typebuffer[option=TEX] \getbuffer Here we define a macro that makes a color matrix. It can be used as follows \startbuffer \startcombination[nx=4,ny=1] {\startMPcode draw cielabmatrix(20, -100, 100, -100, 100, 5) ysized 35mm withpen pencircle scaled 2.5 ; \stopMPcode} {\type {l = 20}} {\startMPcode draw cielabmatrix(40, -100, 100, -100, 100, 5) ysized 35mm withpen pencircle scaled 2.5 ; \stopMPcode} {\type {l = 40}} {\startMPcode draw cielabmatrix(60, -100, 100, -100, 100, 5) ysized 35mm withpen pencircle scaled 2.5 ; \stopMPcode} {\type {l = 60}} {\startMPcode draw cielabmatrix(80, -100, 100, -100, 100, 5) ysized 35mm withpen pencircle scaled 2.5 ; \stopMPcode} {\type {l = 80}} \stopcombination \stopbuffer \typebuffer[option=TEX] \startlinecorrection \getbuffer \stoplinecorrection One can of course mess around a bit: \startbuffer \startcombination[nx=4,ny=1] {\startMPcode draw cielabmatrix(20, -100, 100, -100, 100, 10) ysized 35mm randomized 1 withpen pensquare scaled 4 ; \stopMPcode} {\type {l = 20}} {\startMPcode draw cielabmatrix(40, -100, 100, -100, 100, 10) ysized 35mm randomized 1 withpen pensquare scaled 4 ; \stopMPcode} {\type {l = 40}} {\startMPcode draw cielabmatrix(60, -100, 100, -100, 100, 10) ysized 35mm randomized 1 withpen pensquare scaled 4 ; \stopMPcode} {\type {l = 60}} {\startMPcode draw cielabmatrix(80, -100, 100, -100, 100, 10) ysized 35mm randomized 1 withpen pensquare scaled 4 ; \stopMPcode} {\type {l = 80}} \stopcombination \stopbuffer \typebuffer[option=TEX] \startlinecorrection \getbuffer \stoplinecorrection Normally, when you don't go beyond this kind of usage, a simple macro like the above will do. But when you want to make something that is upward compatible (which is one of the principles behind the \CONTEXT\ user interface(s), you can do this: \startbuffer \startcombination[nx=4,ny=1] {\startMPcode draw lmt_labtorgb [ l = 20, step = 20 ] ysized 35mm withpen pencircle scaled 8 ; \stopMPcode} {\type {l=20}} {\startMPcode draw lmt_labtorgb [ l = 40, step = 20 ] ysized 35mm withpen pencircle scaled 8 ; \stopMPcode} {\type {l=40}} {\startMPcode draw lmt_labtorgb [ l = 60, step = 20 ] ysized 35mm withpen pencircle scaled 8 ; \stopMPcode} {\type {l=60}} {\startMPcode draw lmt_labtorgb [ l = 80, step = 20 ] ysized 35mm withpen pencircle scaled 8 ; \stopMPcode} {\type {l=80}} \stopcombination \stopbuffer \typebuffer[option=TEX] \startlinecorrection \getbuffer \stoplinecorrection This is a predefined macro in the reserved \type {lmt_} namespace (don't use that one yourself, create your own). First we preset the possible parameters: \starttyping[option=MP] presetparameters "labtorgb" [ mina = -100, maxa = 100, minb = -100, maxb = 100, step = 5, l = 50, ] ; \stoptyping Next we define the main interface macro: \starttyping[option=MP] def lmt_labtorgb = applyparameters "labtorgb" "lmt_do_labtorgb" enddef ; \stoptyping Last we do the actual implementation, which looks a lot like the one we started with: \starttyping[option=MP] vardef lmt_do_labtorgb = image ( pushparameters "labtorgb" ; save l ; l := getparameter "l" ; for a = getparameter "mina" step getparameter "step" until getparameter "maxa" : for b = getparameter "minb" step getparameter "step" until getparameter "maxb" : draw (a,b) withcolor labtorgb(l,a,b) ; endfor ; endfor ; popparameters ; ) enddef ; \stoptyping Of course we can now add all kind of extra features but this is what we currently have. Maybe this doesn't belong in the \METAFUN\ core but it's not that much code and a nice demo. After all, there is much in there that is seldom used. A perceptive color space that uses the lab model is lhc. Here is an example of how that can be used: \startbuffer \startMPdefinitions vardef lchcolorcircle(expr l, c, n) = image ( save p, h ; path p ; numeric h ; p := arcpointlist n of fullcircle ; for i within p : h := i*360/n ; draw pathpoint scaled 50 withpen pencircle scaled (120/n) withcolor lchtorgb(l,c,h) ; draw textext ("\tt\bf" & decimal h) scaled .4 shifted (pathpoint scaled 50) withcolor white ; endfor ; ) enddef ; \stopMPdefinitions \stopbuffer \typebuffer[option=TEX] \getbuffer Of course you can come up with another representation than this but here is how it looks: \startbuffer \startMPcode draw image ( draw lchcolorcircle(75,100,24) ; draw lchcolorcircle(50,100,24) scaled .75 ; draw lchcolorcircle(25,100,24) scaled .50 ; ) ysized 4cm ; \stopMPcode \stopbuffer \typebuffer[option=TEX] \startbuffer \startcombination[nx=6,ny=1,distance=.02tw] {\startMPcode draw lmt_lchcircle [ l = 75, c = 100, steps = 12 ] xsized .15TextWidth ; \stopMPcode} {\type {l=75,c=100}} {\startMPcode draw lmt_lchcircle [ l = 50, c = 100, steps = 12 ] xsized .15TextWidth ; \stopMPcode} {\type {l=50,c=100}} {\startMPcode draw lmt_lchcircle [ l = 25, c = 100, steps = 12 ] xsized .15TextWidth ; \stopMPcode} {\type {l=25,c=100}} {\startMPcode draw lmt_lchcircle [ l = 75, c = 25, steps = 12 ] xsized .15TextWidth ; \stopMPcode} {\type {l=75,c=25}} {\startMPcode draw lmt_lchcircle [ l = 50, c = 25, steps = 12 ] xsized .15TextWidth ; \stopMPcode} {\type {l=50,c=25}} {\startMPcode draw lmt_lchcircle [ l = 25, c = 25, steps = 12 ] xsized .15TextWidth ; \stopMPcode} {\type {l=25,c=25}} \stopcombination \stopbuffer You can get rather nice color pallets by manipulating the axis without really knowing what color you get. The \type {h} value is in angles and shown inside the circles. \startlinecorrection \getbuffer \stoplinecorrection Of course we can again wrap this into a parameter driven macro, this time \typ {lmt_lchcircle} which accepts \type {l}, \type {c}, \type {steps} and a \type {labels} boolean. \stopsection \startsection[title=Transparency] Although transparency is independent from color we discuss one aspect here. Where color is sort of native to \METAPOST, especially when we talk \RGB\ and \CMYK, other color spaces are implemented using so called prescripts, think \quotation {information bound to paths and related wrappers}. When you do this: \startbuffer \startMPcode path c ; c := fullcircle scaled 1cm ; picture p ; p := image ( fill c shifted ( 0mm,0) withcolor "darkred" ; fill c shifted ( 5mm,0) withcolor "darkgreen" ; fill c shifted (10mm,0) withcolor "darkblue" ; ) ; draw p ; draw p shifted (3cm,0) withcolor "middlegray" ; \stopMPcode \stopbuffer \typebuffer[option=TEX] You will notice that the picture gets recolored so the color properties set on the picture are applied to separate elements that make it. A picture itself is actually just a list of objects and it has no properties of its own. A way around this is to wrap it in a group, bound or clip which basically means something: begin, list of objects, end. By putting properties on the wrapper we can support features that apply to what gets wrapped without adapting the properties directly. \startlinecorrection \getbuffer \stoplinecorrection Because transparency is also implemented with prescripts we have a problem: should it apply to the wrapper or to everything? In the \LUATEX\ version of the \METAPOST\ library the scripts get assigned to the first element that supports them and because there only paths can have these properties, you cannot simply change the transparency without looping over the picture and redraw it. \startbuffer \startMPcode picture q ; q := image ( fill c shifted ( 0mm,0) withcolor "darkcyan" withtransparency (1,.5); fill c shifted ( 5mm,0) withcolor "darkmagenta" withtransparency (1,.5); fill c shifted (10mm,0) withcolor "darkyellow" withtransparency (1,.5); ) ; draw q ; draw q shifted (3cm,0) withtransparency (1,.25) ; \stopMPcode \stopbuffer \typebuffer[option=TEX] In \LUAMETATEX\ we have a way to assign the properties to the elements so we get three less transparent circles: \startlinecorrection \getbuffer \stoplinecorrection In \MKIV\ only the first circle becomes lighter. \startbuffer \startMPcode picture r ; r := image ( draw p ; draw q shifted (7cm,0cm) ; ) ; draw r ; draw r shifted (3cm,0) withtransparency (1,.75) ; \stopMPcode \stopbuffer \typebuffer[option=TEX] This example shows that when we draw \type {p} and \type {q} we get the elements at the same level (flattened) so we can indeed apply the transparency to all of them. \startlinecorrection \getbuffer \stoplinecorrection So, keep in mind that this only works in \MKXL\ and not in \MKVI\ (unless we also upgrade \LUATEX\ to support this). \stopsection \startsection[title=Surrounding color] Here is an example that shows how to make a graphic listen to the current color: \startbuffer \startcolor[blue] blue before \startMPcode setbackendoption "noplugins" ; fill fullcircle xscaled 3EmWidth yscaled 1.5ExHeight ; \stopMPcode\space blue after \stopcolor \stopbuffer \typebuffer[option=tex] This backend option disables {\em all} additional features so it will only work for for relative simple graphics. There might be more detailed control in the future. \startlinecorrection \getbuffer \stoplinecorrection \stopsection \stopchapter \stopcomponent % \startMPpage[offset=1ts] % draw image ( % fill (unitsquare xscaled 10cm yscaled 4cm) % withcolor svgcolor(0.5,0,0) % ; % registerluminositygroup ("test") ( % fill (unitsquare scaled 2cm) shifted (1cm,1cm) % withshademethod "circular" % withshadecolors (.6,.1) % ) ; % applyluminositygroup ("test") ( % fill (unitsquare scaled 2cm) shifted (1cm,1cm) % withshademethod "circular" % ) ; % draw luminositygroup ( % fill (unitsquare scaled 2cm) shifted (4cm,1cm) % withshademethod "circular" % withshadecolors (.6,.1) % ) ( % fill (unitsquare scaled 2cm) shifted (4cm,1cm) % withshademethod "circular" % ) ; % draw luminosityshade ( % (unitsquare scaled 2cm) shifted (7cm,1cm) % ) ( % withshademethod "circular" % withshadecolors (.6,.1) % ) ( % withshademethod "circular" % ) ; % ) ; % \stopMPpage % \startMPpage[offset=1ts] % draw image ( % fill (unitsquare xscaled 10cm yscaled 4cm) % withcolor "darkblue" % ; % registerluminositygroup ("test") ( % fill (unitsquare scaled 2cm) shifted (1cm,1cm) % withcolor "darkgreen" % ) ; % applyluminositygroup ("test") ( % fill (unitsquare scaled 2cm) shifted (1cm,1cm) % withcolor "darkred" % ) ; % draw luminositygroup ( % fill (unitsquare scaled 2cm) shifted (4cm,1cm) % withcolor "darkgreen" % ) ( % fill (unitsquare scaled 2cm) shifted (4cm,1cm) % withcolor "darkred" % ) ; % draw luminosityshade ( % (unitsquare scaled 2cm) shifted (7cm,1cm) % ) ( % withcolor "darkgreen" % ) ( % withcolor "darkred" % ) ; % ) ; % \stopMPpage