1
2
3\startcomponent colorsbasics
4
5\environment colorsenvironment
6
7\startchapter[title=Metafun][color=darkyellow]
8
9\startsection[title=Defining and using]
10
11In \METAPOST\ itself colors are defined as numbers or sets:
12
13\starttyping
14color red ; red := (1,0,0) ;
15cmykcolor cyan ; cyan := (1,0,0,0) ;
16numeric gray ; gray := 0.5 ;
17\stoptyping
18
19You dont need much fantasy to see that this fits well in the data model of
20\METAPOST. In fact, transparency could be represented as a \type {pair}. The
21disadvantage of having no generic color type is that you cannot mix them. In case
22you need to manipulate them, you can check the type:
23
24\starttyping
25if cmykcolor cyan : ... fi ;
26\stoptyping
27
28because \METAFUN\ is tightly integrated in \CONTEXT\ you can refer to colors
29known at the \TEX\ end by string. So,
30
31\starttyping
32string mycolor ; mycolor := "red" ;
33\stoptyping
34
35and then:
36
37\starttyping
38fill fullcircle scaled 4cm withcolor mycolor ;
39\stoptyping
40
41is quite okay. For completeness we also have \type {namedcolor} but its not
42really needed:
43
44\starttyping
45fill fullcircle scaled 4cm withcolor namedcolor("red");
46\stoptyping
47
48You can define spot colors too but normally you will refer to colors
49defined at the \TEX\ end.
50
51\startbuffer[spot]
52\startMPcode
53 fill fullcircle scaled 3cm withcolor
54 .5 spotcolor("whatever",(.3,.4,.5)) ;
55 fill fullcircle scaled 2cm withcolor
56 spotcolor("whatever",(.3,.4,.5)) ;
57 fill fullcircle scaled 1cm withcolor
58 spotcolor("whatever",(.3,.4,.5)2) ;
59\stopMPcode
60\stopbuffer
61
62\startbuffer[multi]
63\startMPcode
64 fill fullcircle scaled 3cm withcolor
65 .5 multitonecolor("whatever",(.3,.4,.5),(.5,.3,.4)) ;
66 fill fullcircle scaled 2cm withcolor
67 multitonecolor("whatever",(.3,.4,.5),(.5,.3,.4)) ;
68 fill fullcircle scaled 1cm withcolor
69 multitonecolor("whatever",(.3,.4,.5)2,(.5,.3,.4)2) ;
70\stopMPcode
71\stopbuffer
72
73\typebuffer[spot]
74
75Multitones are defined as:
76
77\typebuffer[multi]
78
79Some \PDF\ renderers have problems with fractions of such colors and even display
80the wrong colors. So, in these examples the third alternative in the sets of
81three might be more robust than the first. The result is shown in \in {figure}
82[fig:mpspot].
83
84\startplacefigure[reference=fig:mpspot,title={Spot and multitones directly defined in \METAFUN.}]
85 \startcombination[2*1]
86 {\getbuffer[spot]} {}
87 {\getbuffer[multi]} {}
88 \stopcombination
89\stopplacefigure
90
91\stopsection
92
93\startsection[title=Passing colors]
94
95Originally \TEX\ and \METAPOST\ were separated processes and even in \LUATEX\
96they still are. There can be many independent \METAPOST\ instances present, but
97always there is \LUA\ as glue between them. In the early days of \LUATEX\ this
98was a one way channel: the \METAPOST\ output is available at the \TEX\ end in
99\LUA\ as a table and properties are used to communicate extensions. In todays
100\LUATEX\ the \METAPOST\ library has access to \LUA\ itself so that gives us a
101channel to \TEX, although with some limitations.
102
103Say that we have a color defined as follows:
104
105\startbuffer
106\definecolor[MyColor][r=.25,g=.50,b=.75]
107\stopbuffer
108
109\typebuffer \getbuffer
110
111We can apply this to a rule:
112
113\startbuffer
114\blackrule[color=MyColor,width=3cm,height=1cm,depth=0cm]
115\stopbuffer
116
117\typebuffer
118
119From this we get:
120
121\startlinecorrection
122\getbuffer
123\stoplinecorrection
124
125In \TEX\ (code) we can do this:
126
127\startbuffer
128\startMPcode
129 fill unitsquare xyscaled (3cm,1cm) withcolor \MPcolor {MyColor} ;
130\stopMPcode
131\stopbuffer
132
133\typebuffer
134
135When the code is pushed to \METAPOST\ the color gets expanded, in this case to
136\typ {(0.25, 0.50, 0.75)} because we specified an \RGB\ color but the other
137colorspaces are supported too.
138
139\startlinecorrection
140\getbuffer
141\stoplinecorrection
142
143Equally valid code is:
144
145\starttyping
146\startMPcode
147 fill unitsquare xyscaled (3cm,1cm) withcolor "MyColor" ;
148\stopMPcode
149\stoptyping
150
151This is very un\METAPOST\ as naturally it can only deal with numerics for gray
152scales, triplets for \RGB\ colors, and quadruplets for \CMYK\ colors. In
153\METAFUN\ (as present in \CONTEXT\ MKIV) the \type {withcolor} operator also
154accepts a string, which is resolved to a color specification.
155
156For the record we note that when you use transparent colors, a more complex
157specification gets passed with \type {\MPcolor} or resolved (via the string). The
158same is true for spot and multitone colors. It will be clear that when you want
159to assign a color to a variable you have to make sure the type matches. A rather
160safe way to define colors is:
161
162\starttyping
163def MyColor =
164 \MPcolor{MyColor}
165enddef ;
166\stoptyping
167
168and because we can use strings, string variables are also an option.
169
170\stopsection
171
172\startsection[title=Grouping]
173
174The reason for discussing these details is that there is a rather fundamental
175concept of grouping in \TEX\ which can lead to unexpected side effects. The
176reason is that there is no grouping at the \LUA\ end, unless one uses a kind of
177stack, and that in \METAPOST\ grouping is an explicit feature.
178
179\starttyping
180\scratchcounter=123
181\bgroup
182 \scratchcounter=456
183\egroup
184\stoptyping
185
186After this \TEX\ code is expanded the counter has value 123. In \METAPOST\ you
187can do the following:
188
189\starttyping
190scratchcounter := 123 ;
191\begingroup
192 scratchcounter := 456 ;
193\endgroup
194\stoptyping
195
196but here the counter is 456 afterwards! You explicitly need to save a value:
197
198\starttyping
199scratchcounter := 123 ;
200\begingroup
201 save scratchcounter ;
202 numeric scratchcounter ;
203 scratchcounter := 456 ;
204\endgroup
205\stoptyping
206
207The difference perfectly makes sense if you think about the kind of applications
208\TEX\ and \METAPOST\ are used for. In \LUA\ you can do this:
209
210
211\starttyping
212scratchcounter = 123
213do
214 local scratchcounter = 456
215end
216\stoptyping
217
218and in fact, a \type {then}, \type {else}, \type {while}, \type {repeat}, \type
219{do} and function body also behave this way.
220
221So, what is the impact on colors? Imagine that you do this:
222
223\startbuffer
224\bgroup
225 \definecolor[MyColor][s=.5]
226 \startMPcode
227 pickup pencircle scaled 4mm ;
228 draw fullcircle scaled 30mm withcolor \MPcolor{MyColor} ;
229 draw fullcircle scaled 15mm withcolor "MyColor" ;
230 \stopMPcode
231\egroup
232\quad
233\startMPcode
234 pickup pencircle scaled 4mm ;
235 draw fullcircle scaled 30mm withcolor \MPcolor{MyColor} ;
236 draw fullcircle scaled 15mm withcolor "MyColor" ;
237\stopMPcode
238\stopbuffer
239
240\typebuffer
241
242We get the following colors:
243
244\startlinecorrection
245\hbox{\getbuffer}
246\stoplinecorrection
247
248Because \type {\MPcolor} is a \TEX\ macro, its value gets expanded when the
249graphic is calculated. After the group (first graphic) the color is restored.
250But, in order to access the colors defined at the \TEX\ end in \METAPOST\ by name
251(using \LUA) we need to make sure that a defined color is registered at that end.
252Before we could use the string accessor in \METAPOST\ colors, this was never a
253real issue. We kept the values in a (global) \LUA\ table which was good enough
254for the cases where we wanted to access color specifications, for instance for
255tracing. Such colors never changed in a document. But with the more dynamic
256\METAPOST\ graphics we cannot do that: there is no way that \METAPOST\ (or \LUA)
257later on can know that the color was defined inside a group as clone. For daily
258usage its enough to know that we have found a way around it in \CONTEXT\ at
259neglectable overhead. In the rare case this mechanism fails, you can always
260revert to the \type {\MPcolor} method.
261
262\startbuffer
263\definecolor[DemoOne][red]
264\definecolor[DemoTwo][s=.8,t=0.5,a=1]
265
266
267\definepalet[DemoPalet][NumberColor=red,red=cyan]
268\definepalet[DemoPalet][NumberColor=red]
269
270\setuppalet[DemoPalet]
271
272\bgroup
273 \definecolor[red] [b=.8]
274 \definecolor[DemoOne][yellow]
275 \startMPcode
276 fill fullcircle scaled 10 withcolor "NumberColor" ;
277 fill fullcircle scaled 7 withcolor "red" ;
278 fill fullcircle scaled 6 withcolor .5\MPcolor{red} ;
279 fill fullcircle scaled 4 shifted (-4,0) withcolor \MPcolor{DemoTwo} ;
280 fill fullcircle scaled 4 shifted ( 4,0) withcolor "DemoTwo" ;
281 fill fullcircle scaled 2 withcolor "DemoOne" ;
282 fill fullcircle scaled 1 withcolor \MPcolor{NumberColor} ;
283 currentpicture := currentpicture xysized(5cm,3cm) ;
284 \stopMPcode
285\egroup
286\hskip1cm
287\startMPcode
288 fill fullcircle scaled 10 withcolor "NumberColor" ;
289 fill fullcircle scaled 7 withcolor "red" ;
290 fill fullcircle scaled 6 withcolor .5\MPcolor{red} ;
291 fill fullcircle scaled 4 shifted (-4,0) withcolor \MPcolor{DemoTwo} ;
292 fill fullcircle scaled 4 shifted ( 4,0) withcolor "DemoTwo" ;
293 fill fullcircle scaled 2 withcolor "DemoOne" ;
294 fill fullcircle scaled 1 withcolor \MPcolor{NumberColor} ;
295 currentpicture := currentpicture xysized(5cm,3cm) ;
296\stopMPcode
297\stopbuffer
298
299The following example was used when developing the string based color resolver.
300The complication was in getting the color palets resolved right without too much
301overhead. Again we demonstrate this because border cases might occur that are not
302catched (yet).
303
304\startlinecorrection
305 \hbox {\getbuffer}
306\stoplinecorrection
307
308\stopsection
309
310\startsection[title=Transparency]
311
312Transparency is supported at the \TEX\ end: either or not bound to colors. We
313already saw how to use colors, heres how to apply transparency:
314
315\startbuffer
316\startMPcode
317 fill fullsquare xyscaled (4cm,2cm) randomized 5mm
318 withcolor "darkred" ;
319 fill fullsquare xyscaled (2cm,4cm) randomized 5mm
320 withcolor "darkblue" withtransparency ("normal",0.5) ;
321
322 fill fullsquare xyscaled (4cm,2cm) randomized 5mm shifted (45mm,0)
323 withcolor "darkred" withtransparency ("normal",0.5) ;
324 fill fullsquare xyscaled (2cm,4cm) randomized 5mm shifted (45mm,0)
325 withcolor "darkblue" withtransparency ("normal",0.5) ;
326
327 fill fullsquare xyscaled (4cm,2cm) randomized 5mm shifted (90mm,0)
328 withcolor "darkred" withtransparency ("normal",0.5) ;
329 fill fullsquare xyscaled (2cm,4cm) randomized 5mm shifted (90mm,0)
330 withcolor "darkblue" ;
331\stopMPcode
332\stopbuffer
333
334\typebuffer
335
336We get a mixture of normal and transparent colors. Instead of \type {normal}
337you can also pass a number (with \type {1} being \type {normal}).
338
339\startlinecorrection
340 \getbuffer
341\stoplinecorrection
342
343\stopsection
344
345\startsection[title=Shading]
346
347Shading is available too. This mechanism is a bit more complex deep down because
348it needs resources as well as shading vectors that adapt themselves to the current
349scale. We will not go into detail about the shading properties here.
350
351\startbuffer
352\startMPcode
353 comment("two shades with mp colors");
354 fill fullcircle scaled 5cm
355 withshademethod "circular"
356 withshadevector (2cm,1cm)
357 withshadecenter (.1,.5)
358 withshadedomain (.2,.6)
359 withshadefactor 1.2
360 withshadecolors (red,white)
361 ;
362 fill fullcircle scaled 5cm shifted (6cm,0)
363 withshademethod "circular"
364 withcolor "red" shadedinto "blue"
365 ;
366\stopMPcode
367\stopbuffer
368
369\typebuffer
370
371You can use normal \METAPOST\ colors as well as named colors.
372
373\startlinecorrection
374 \getbuffer
375\stoplinecorrection
376
377\startbuffer
378\startMPcode
379 comment("two shades with named colors");
380 fill fullcircle scaled 5cm
381 withshademethod "circular"
382 withshadecolors ((1,0,0),(0,0,1,0))
383 ;
384 fill fullcircle scaled 5cm shifted (6cm,0)
385 withshademethod "circular"
386 withcolor (1,0,0,0) shadedinto "blue"
387 ;
388\stopMPcode
389\stopbuffer
390
391The color space of the first color determines if the second one needs
392to be converted, so this is valid:
393
394\typebuffer
395
396The first circle is in \RGB\ colors and the second in \CMYK.
397
398\startlinecorrection
399 \getbuffer
400\stoplinecorrection
401
402You cannot use spot colors but you can use transparency, so with:
403
404\startbuffer
405\startMPcode
406 comment("three transparent shades");
407 fill fullcircle scaled 5cm
408 withshademethod "circular"
409 withshadecolors ("red","green")
410 withtransparency ("normal",0.5)
411 ;
412 fill fullcircle scaled 5cm shifted (30mm,0)
413 withshademethod "circular"
414 withshadecolors ("green","blue")
415 withtransparency ("normal",0.5)
416 ;
417 fill fullcircle scaled 5cm shifted (60mm,0)
418 withshademethod "circular"
419 withshadecolors ("blue","yellow")
420 withtransparency ("normal",0.5)
421 ;
422\stopMPcode
423\stopbuffer
424
425\typebuffer
426
427we get:
428
429\startlinecorrection
430 \getbuffer
431\stoplinecorrection
432
433You can define a shade and use it later on, for example:
434
435\startbuffer
436\startMPcode
437 defineshade myshade
438 withshademethod "circular"
439 withshadefactor 1
440 withshadedomain (0,1)
441 withshadecolors (black,white)
442 withtransparency (1,.5)
443 ;
444
445 fill fullcircle xyscaled(.75TextWidth,4cm)
446 shaded myshade ;
447 fill fullcircle xyscaled(.75TextWidth,4cm) shifted (.125TextWidth,0)
448 shaded myshade ;
449 fill fullcircle xyscaled(.75TextWidth,4cm) shifted (.25TextWidth,0)
450 shaded myshade ;
451\stopMPcode
452\stopbuffer
453
454\typebuffer
455
456This gives three transparent shaded shapes:
457
458\startlinecorrection
459 \getbuffer
460\stoplinecorrection
461
462A very special shade is the following:
463
464\startbuffer
465\startMPcode
466 fill fullsquare yscaled 5ExHeight xscaled TextWidth
467 withshademethod "linear"
468 withshadevector (0,1)
469 withshadestep (
470 withshadefraction .3
471 withshadecolors (red,green)
472 )
473 withshadestep (
474 withshadefraction .5
475 withshadecolors (green,blue)
476 )
477 withshadestep (
478 withshadefraction .7
479 withshadecolors (blue,red)
480 )
481 withshadestep (
482 withshadefraction 1
483 withshadecolors (red,yellow)
484 )
485 ;
486\stopMPcode
487\stopbuffer
488
489\typebuffer
490
491The result is a colorful band:
492
493\startlinecorrection
494 \getbuffer
495\stoplinecorrection
496
497\stopsection
498
499\startsection[title=Text]
500
501The text typeset with \type {textext} is processed in \TEX\ using the
502current settings. A text can of course have color directives embedded.
503
504\startbuffer
505\startMPcode
506numeric u ; u := 8mm ;
507draw thetextext("RED", (0,0u)) withcolor darkred ;
508draw thetextext("\darkgreen GREEN", (0,1u)) ;
509draw thetextext("\darkblue BLUE", (0,2u)) withcolor darkred ;
510draw thetextext("BLACK {\darkgreen GREEN}",(0,3u)) ;
511draw thetextext("RED {\darkblue BLUE}",(0,4u)) withcolor darkred ;
512\stopMPcode
513\stopbuffer
514
515\typebuffer
516
517In this example we demonstrate that you can also apply a color to the
518resulting picture.
519
520\startlinecorrection
521\tttfd \getbuffer
522\stoplinecorrection
523
524\stopsection
525
526\startsection[title=Helpers]
527
528\stopsection
529
530There are several color related macros in \METAFUN\ and these are discussed
531in the \METAFUN\ manual, so we only mention a few here.
532
533\startbuffer
534\startMPcode
535 fill fullsquare xyscaled(TextWidth,4cm)
536 withcolor darkred ;
537 fill fullsquare xyscaled(TextWidth,3cm)
538 withcolor complementary darkred ;
539 fill fullsquare xyscaled(TextWidth,2cm)
540 withcolor complemented darkred ;
541 fill fullsquare xyscaled(TextWidth,1cm)
542 withcolor grayed darkred ;
543\stopMPcode
544\stopbuffer
545
546\typebuffer
547
548This example code is shown in \in {figure} [fig:complemen1]. The \type
549{complementary} operator subtracts the given color from white, the \type
550{complemented} operator calculates its values from opposites (so a zero becomes a
551one). In \in {figure} [fig:complemen2] a more extensive example is shown.
552
553\startplacefigure
554 [reference=fig:complemen1,
555 title={The \type {complementary}, \type {complemented} and \type
556 {grayed} methodscompared.}]
557 \getbuffer
558\stopplacefigure
559
560\startMPdefinitions
561
562
563 def MyCompare (text method) =
564
565 picture p ; p := textext("\quad \bf
566 I don't understand about complementary colors\quad
567 And what they say\quad
568 Side by side they both get bright\quad
569 Together they both get gray\quad"
570 ) ;
571
572 numeric w ; w := bbwidth p ;
573 numeric h ; h := bbheight p ;
574
575 for i = 1 upto 10 :
576 fill fullsquare
577 xscaled (w10)
578 yscaled 5h
579 shifted (w2w20iw10,-3h2)
580 withcolor (ired10)
581 withtransparency(1,.5) ;
582 fill fullsquare
583 xscaled (w10)
584 yscaled 5h
585 shifted (w2w20iw10,3h2)
586 withcolor method (ired10)
587 withtransparency(1,.5) ;
588 endfor ;
589 addbackground withcolor .75white ;
590
591 draw p withcolor white ;
592
593 currentpicture := currentpicture xsized TextWidth ;
594 enddef ;
595\stopMPdefinitions
596
597\startplacefigure[reference=fig:complemen2,title={Two methods to complement colors compared (text: Fiona Apple).}]
598 \startcombination[1*2]
599 {\startMPcode MyCompare(complemented) ; \stopMPcode} {complemented}
600 {\startMPcode MyCompare(complementary) ; \stopMPcode} {complementary}
601 \stopcombination
602\stopplacefigure
603
604As we discussed before, the different color models in \METAPOST\ cannot be mixed
605in expressions. We therefore have two macros that expand into white or black
606in the right colorspace.
607
608\typebuffer
609
610\startbuffer
611\startMPcode
612 fill fullsquare xyscaled(TextWidth,4cm)
613 withcolor .5[(.5,0,0), whitecolor (.5,0,0)] ;
614 fill fullsquare xyscaled(TextWidth,3cm)
615 withcolor .5[(.5,0,0), blackcolor (.5,0,0)] ;
616 fill fullsquare xyscaled(TextWidth,2cm)
617 withcolor .5[(.5,0,0,0), whitecolor (.5,0,0,0)] ;
618 fill fullsquare xyscaled(TextWidth,1cm)
619 withcolor .5[(.5,0,0,0), blackcolor (.5,0,0,0)] ;
620\stopMPcode
621\stopbuffer
622
623\typebuffer
624
625\startlinecorrection
626\getbuffer
627\stoplinecorrection
628
629There are two macros that can be used to resolve string to colors: \type
630{resolvedcolor} and \type {namedcolor}. A resolved color is expanded via \LUA\
631while a named color is handled in the backend, when the result is converted to
632\PDF. The resolved approach is more recent and is the same as a string color
633specification.
634
635\startbuffer
636\startMPcode
637 fill fullcircle scaled 4cm withcolor .5 resolvedcolor "darkred" ;
638 fill fullcircle scaled 3cm withcolor .5 resolvedcolor "gray" ;
639 fill fullcircle scaled 2cm withcolor .5 namedcolor "darkblue" ;
640 fill fullcircle scaled 1cm withcolor .5 namedcolor "gray" ;
641\stopMPcode
642\stopbuffer
643
644\typebuffer
645
646\startlinecorrection
647\getbuffer
648\stoplinecorrection
649
650There is a \type {drawoptions} macro that can be used to define properties in one go.
651
652\startbuffer
653\startMPcode
654 drawoptions(withcolor "darkgreen");
655 fill fullcircle scaled 4cm ;
656 fill fullcircle scaled 3cm withcolor white ;
657 fill fullcircle scaled 2cm ;
658\stopMPcode
659\stopbuffer
660
661\typebuffer
662
663We get:
664
665\startlinecorrection
666\getbuffer
667\stoplinecorrection
668
669The drawback of this approach is that, because we use so called pre and
670postscripts for achieving special effects (like spotcolors and shading)
671successive \type {withcolor} calls can interfere in a way that unexpected results
672turn up. A way out is to use properties:
673
674\startbuffer
675\startMPcode
676 property p[] ;
677 p1 = properties(withcolor "darkred") ;
678 p2 = properties(withcolor "white") ;
679 fill fullcircle scaled 4cm withproperties p1 ;
680 fill fullcircle scaled 3cm withproperties p2 ;
681 fill fullcircle scaled 2cm withproperties p1 ;
682\stopMPcode
683\stopbuffer
684
685\typebuffer
686
687This results in:
688
689\startlinecorrection
690\getbuffer
691\stoplinecorrection
692
693\stopchapter
694
695\stopcomponent
696 |