% language=us runpath=texruns:manuals/metafun % graphic text takes 5 sec on 21 \startcomponent metafun-effects \environment metafun-environment \useMPlibrary[outlines] \startchapter[reference=sec:effects,title={Special effects}] \startintro Sometimes we want to go beyond \METAPOST's native features. Examples of such an extension are \CMYK\ colors, shading and transparency. Although features like this should be used with care, sometimes the documents look and feel can profit from it. If you don't want the whole graphic, but only a part of it, clipping comes into play. In addition to the standard clipping features, we can use \METAPOST\ to provide a decent clipping path. In this chapter we will uncover the details. We will also introduce ways to include externally defined graphics and outline fonts. We will demonstrate that within reasonable bounds you can manipulate such graphics. \stopintro \startsection[title={Spot colors}] You can define spot and multitone colors directly in \METAFUN, although normally you will do it at the \TEX\ end for consistency. At the \TEX\ end we define this: \startbuffer \definecolor [SpotBlue] [c=1,m=.38,y=0,k=.64] \definecolor [SpotYellow] [c=0,m=.28,y=1,k=.06] \definemultitonecolor [MultiColor] [SpotBlue=.5,SpotYellow=.25] \stopbuffer \typebuffer \getbuffer \startbuffer draw image ( fill unitsquare shifted (7,0) withcolor namedcolor("MultiColor") ; fill unitsquare shifted (6,0) withcolor .6 * spotcolor("temp1",red) ; fill unitsquare shifted (5,0) withcolor .4 * spotcolor("temp1",red) ; fill unitsquare shifted (4,0) withcolor .5 * spotcolor("temp2",.5green) ; fill unitsquare shifted (3,0) withcolor .5 * spotcolor("temp3",green) ; fill unitsquare shifted (2,0) withcolor multitonecolor("temp4",blue/2,yellow/2,green/2,magenta/3) ; ) xsized TextWidth ; \stopbuffer Next we process this graphic: \typebuffer and get: \startlinecorrection[blank] \processMPbuffer \stoplinecorrection \stopsection \startsection[title={Transparency}] \index{transparency} {\em In the screen version we use a light gray background color. As a result, some of the transparency methods demonstrated here give unexpected results. The A4 version of this document demonstrates the real effects.} Although transparent colors have been around for some time already, it was only around 2000 that they made it as a high level feature into document format languages like \PDF. Supporting such a feature at a higher abstraction level is not only more portable, but also less sensitive for misinterpretation. \startbuffer[mpdef] vardef ColorCircle (expr method, factor, ca, cb, cc) = save u, p ; path p ; p := fullcircle shifted (1/4,0) ; image ( fill p rotated 90 withcolor ca withtransparency (method,factor) ; fill p rotated 210 withcolor cb withtransparency (method,factor) ; fill p rotated 330 withcolor cc withtransparency (method,factor) ; ) enddef ; \stopbuffer \typebuffer[mpdef] \startbuffer[mp] draw ColorCircle ("normal", .5, red, green, blue) xsized 3cm ; currentpicture := currentpicture shifted (-4cm,0) ; draw ColorCircle ("exclusion", .5, red, green, blue) xsized 3cm ; currentpicture := currentpicture shifted (-4cm,0) ; draw ColorCircle ("exclusion", 1, red, green, blue) xsized 3cm ; \stopbuffer \typebuffer[mp] \startlinecorrection[blank] \processMPbuffer[mpdef,mp] \stoplinecorrection \startbuffer[mp] cmykcolor xcyan ; xcyan := (1,0,0,0) ; cmykcolor xmagenta ; xmagenta := (0,1,0,0) ; cmykcolor xyellow ; xyellow := (0,0,1,0) ; draw ColorCircle ("exclusion", .5, xcyan, xmagenta, xyellow) xsized 3cm ; \stopbuffer \typebuffer[mp] \startlinecorrection[blank] \processMPbuffer[mpdef,mp] \stoplinecorrection You can be tempted to use transparency as a convenient way to achieve soft colors. In that case you should be aware of the fact that rendering transparent colors takes more time than normal colors \footnote {When your printer does not support this feature natively, the intermediate (\POSTSCRIPT) file send to the printing engine is also larger.} Fortunatey, \METAPOST\ provides a similar mechanism. The last circle in the following row demonstrates how we can trigger colors proportionally to other colors. Normally \type {background} is white, but you can set predefined color variables to another value. \startbuffer[mp] path p ; p := fullcircle scaled 2cm ; fill p shifted (0cm,0) withcolor blue ; fill p shifted (3cm,0) withcolor .5blue ; fill p shifted (6cm,0) withcolor transparent (1,0.5,blue) ; fill p shifted (9cm,0) withcolor .5[blue,white] ; \stopbuffer \typebuffer[mp] \startlinecorrection[blank] \processMPbuffer[mp] \stoplinecorrection The next series demonstrates that we use the complementary factor \type {.7} in the \METAPOST\ soft color to achieve the same softness as the \type {.3} transparency. \startbuffer[mp] path p ; p := fullcircle scaled 2cm ; fill p shifted (0cm,0) withcolor red ; fill p shifted (3cm,0) withcolor .7red ; fill p shifted (6cm,0) withcolor transparent (1,0.3,red) ; fill p shifted (9cm,0) withcolor .7[red,white] ; \stopbuffer \typebuffer[mp] \startlinecorrection[blank] \processMPbuffer[mp] \stoplinecorrection \startbuffer[mp] vardef SampleText (expr t, c) = save p ; picture p ; p := image (draw t infont "\truefontname{Regular}") ; draw (p shifted (- xpart center p,0)) scaled 5 withcolor c; enddef ; SampleText ("Much Of This" , transparent(1, .5, red )) ; SampleText ("Functionality" , transparent(1, .5, green)) ; SampleText ("Was Written" , transparent(1, .5, blue )) ; SampleText ("While Listening", transparent(1, .5, cmyk(1,0,0,0))) ; SampleText ("To the CD's Of" , transparent(1, .5, cmyk(0,1,0,0))) ; SampleText ("Tori Amos" , transparent(1, .5, cmyk(0,0,1,0))) ; \stopbuffer So far we have applied transparent colors to shapes but text can also be the target. \typebuffer[mp] The source code of this example illustrates that the \CMYK\ color space is also supported. The \type {\truefontname} macro communicates the running font from \TEX\ to \METAPOST. Instead of such low level code one can of course also use the \type {textext} macro. \startbuffer[mp] vardef SampleText (expr t) = draw textext(t) scaled 5 ; enddef ; SampleText ("\colored[a=1,t=.5,r=1]{Much Of This}") ; SampleText ("\colored[a=1,t=.5,g=1]{Functionality}") ; SampleText ("\colored[a=1,t=.5,b=1]{Was Written}") ; SampleText ("\colored[a=1,t=.5,c=1]{While Listening}") ; SampleText ("\colored[a=1,t=.5,m=1]{To the CD's Of}") ; SampleText ("\colored[a=1,t=.5,y=1]{Tori Amos}") ; \stopbuffer However, as we do the typesetting in \TEX\ in \MKIV\ this is the way to go: \typebuffer[mp] As expected we get: \startlinecorrection[blank] \processMPbuffer[mp] \stoplinecorrection Currently the 12 in \PDF\ available transparency methods are supported. \footnote {In the future we may also support more control over the individual methods.} You can use both numbers and names. As you may expect, both \CONTEXT\ and \METAFUN\ support transparency in the same way. \in {Figure} [fig:transparencies] shows how the method affects the result. \startuseMPgraphic{test} numeric u ; u := if lua.mp.mode("screen") : 12mm else : 20mm fi ; path p ; p := fullcircle scaled u shifted (u/4,0); % cmykcolor xyellow ; xyellow := (0,0,1,0) ; % color xgreen ; xgreen := (0,1,0) ; % color xblue ; xblue := (0,0,1) ; % fill p rotated 90 withcolor transparent("\MPvar{a}",.5,xyellow) ; % fill p rotated 210 withcolor transparent("\MPvar{a}",.5,xgreen) ; % fill p rotated 330 withcolor transparent("\MPvar{a}",.5,xblue) ; % fill p rotated 90 withcolor (0,0,1,0) withtransparency("\MPvar{a}",.5) ; % fill p rotated 210 withcolor (0,1,0) withtransparency("\MPvar{a}",.5) ; % fill p rotated 330 withcolor (0,0,1) withtransparency("\MPvar{a}",.5) ; fill p rotated 90 withcolor (0,0,1,0) withtransparency(\MPvar{b},.5) ; fill p rotated 210 withcolor (0,1,0) withtransparency(\MPvar{b},.5) ; fill p rotated 330 withcolor (0,0,1) withtransparency(\MPvar{b},.5) ; \stopuseMPgraphic \startplacefigure[location=here,reference=fig:transparencies,title={The 12 transparency alternatives by name.}] \doifelsemode {screen} { \setupcombination[nx=8,ny=2] } { \setupcombination[nx=4,ny=4] } \startcombination {\useMPgraphic{test}{b=1,a=normal}} {\tttf normal} {\useMPgraphic{test}{b=2,a=multiply}} {\tttf multiply} % here the mu in multiply triggers lookahead in lmtx {\useMPgraphic{test}{b=3,a=screen}} {\tttf screen} {\useMPgraphic{test}{b=4,a=overlay}} {\tttf overlay} {\useMPgraphic{test}{b=5,a=softlight}} {\tttf softlight} {\useMPgraphic{test}{b=6,a=hardlight}} {\tttf hardlight} {\useMPgraphic{test}{b=7,a=colordodge}} {\tttf colordodge} {\useMPgraphic{test}{b=8,a=colorburn}} {\tttf colorburn} {\useMPgraphic{test}{b=9,a=darken}} {\tttf darken} {\useMPgraphic{test}{b=10,a=lighten}} {\tttf lighten} {\useMPgraphic{test}{b=11,a=difference}} {\tttf difference} {\useMPgraphic{test}{b=12,a=exclusion}} {\tttf exclusion} {\useMPgraphic{test}{b=13,a=hue}} {\tttf hue} {\useMPgraphic{test}{b=14,a=saturation}} {\tttf saturation} {\useMPgraphic{test}{b=15,a=color}} {\tttf color} {\useMPgraphic{test}{b=16,a=luminosity}} {\tttf luminosity} \stopcombination \stopplacefigure In \CONTEXT\ a transparent color is defined in a similar way as \quote {normal} colors. The transparency method is specified with the \type {a} key (either by number or by name) and the factor \type {t}. \startbuffer \definecolor [tred] [r=1,t=.5,a=exclusion] \definecolor [tgreen] [g=1,t=.5,a=exclusion] \definecolor [tblue] [b=1,t=.5,a=exclusion] \stopbuffer \typebuffer \getbuffer Both keys are needed. You can define your own symbolic names using: \starttyping \definetransparency [myowndefault] [1] \stoptyping The \type {\MPcolor} macro passes a color from \CONTEXT\ to \METAPOST, including the transparency specification. \startbuffer[mp] u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0); fill p rotated 90 withcolor \MPcolor{tred} ; fill p rotated 210 withcolor \MPcolor{tgreen} ; fill p rotated 330 withcolor \MPcolor{tblue} ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer[mp] \stoplinecorrection Of course this also works well for \CMYK\ colors. \startbuffer \definecolor[tred] [c=1,k=.2,t=.5,a=1] \definecolor[tgreen][m=1,k=.2,t=.5,a=1] \definecolor[tblue] [y=1,k=.2,t=.5,a=1] \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer[mp] \stoplinecorrection Gray scales work as well: \startbuffer \definecolor[tgraya][s=.9,t=.7,a=11] \definecolor[tgrayb][s=.7,t=.7,a=11] \definecolor[tgrayc][s=.5,t=.7,a=11] \stopbuffer \typebuffer \getbuffer We apply this to some text. By using an overlay we can conveniently explore the difference in fonts. % \startbuffer % def SampleText (expr s, f, c) = % draw s infont f scaled 5 withcolor c ; % enddef ; % SampleText("Hello", "\truefontname{Regular}" , \MPcolor{ta}) ; % SampleText("Hello", "\truefontname{RegularBold}" , \MPcolor{tb}) ; % SampleText("Hello", "\truefontname{RegularSlanted}", \MPcolor{tc}) ; % \stopbuffer \startbuffer draw textext("\color[tgraya]{\tf Hello}") scaled 5 ; draw textext("\color[tgrayb]{\bf Hello}") scaled 5 ; draw textext("\color[tgrayc]{\sl Hello}") scaled 5 ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection \stopsection \startsection[title={Shading}] \startsubsection[title=Introduction] \index{shading} In this section we introduce different kinds of shading. Since \METAPOST\ does not support this feature directly, we have to fall back on a few tricks. For the moment shading is only supported in \PDF. In the following examples, we will use the next three colors: \startbuffer \definecolor[mycolora][darkyellow] \definecolor[mycolorb][s=.8] \definecolor[mycolorc][darkred] \stopbuffer \typebuffer \getbuffer Shading support evolved in steps and alongside development of the backend code. Also, as it became more used a second interface came available. We discuss both here. \stopsubsection \startsubsection[title=The old method] First we discuss the old method which is still valid and also available in \MKII. It illustrates some of the principles. \startbuffer[a] \startuniqueMPgraphic{CircularShade} path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ; circular_shade(p,0,\MPcolor{mycolora},\MPcolor{mycolorb}) ; \stopuniqueMPgraphic \startuniqueMPgraphic{LinearShade} path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ; linear_shade(p,0,\MPcolor{mycolora},\MPcolor{mycolorb}); \stopuniqueMPgraphic \stopbuffer \startbuffer[b] \defineoverlay[circular shade][\uniqueMPgraphic{CircularShade}] \defineoverlay[linear shade] [\uniqueMPgraphic{LinearShade}] \stopbuffer \startbuffer[c] \framed [background=circular shade,frame=off] {\bf \white Hi there, I'm Circular!} \stopbuffer \startbuffer[d] \framed [background=linear shade,frame=off] {\bf \white Whow, this is Linear!} \stopbuffer A shade is a fill with a stepwise change in color. In \POSTSCRIPT\ (level 2), the way this color changes can be circular, linear, or according to a user defined function. Circular and linear shades look like this: \startlinecorrection[blank] \getbuffer[a,b,c] \stoplinecorrection \startlinecorrection[blank] \getbuffer[a,b,d] \stoplinecorrection As you can see, the shade lays behind the text, as a background overlay. These overlays are unique \METAPOST\ graphics, so they will adapt themselves to the dimensions of the foreground. \typebuffer[b] The two framed texts are defined as: \typebuffer[c] and: \typebuffer[d] We still have to define the graphics. Here we use a macro that takes four arguments: a path, a number identifying the center of shading, and the colors to start and end with. \typebuffer[a] The \METAPOST\ macros, \type {circular_shade} and \type {linear_shade}, add information to the \METAPOST\ output file, which is interpreted by the converter built in \CONTEXT. Shading comes down to interpolation between two or more points or user supplied ranges. A poor mans way of doing this, is to build the graphics piecewise with slightly changing colors. But, instead of \quote {manually} stepping through the color values, we can use the more efficient and generalized \POSTSCRIPT\ level~2 and \PDF\ level~1.3 shading feature. \def\SomeShade#1#2#3% waarom unique ? {\startuniqueMPgraphic{shade-#1} width := \overlaywidth ; height := \overlayheight ; path p ; p := unitsquare xscaled width yscaled height ; #2_shade(p,#3,\MPcolor{mycolora},\MPcolor{mycolorb}) ; \stopuniqueMPgraphic \defineoverlay[shade-#1][\uniqueMPgraphic{shade-#1}]% \framed[background=shade-#1,width=2cm,height=2cm,frame=off]{}} \startlinecorrection[blank] \startcombination[5*1] {\SomeShade{20}{circular}{0}} {circular 0} {\SomeShade{21}{circular}{1}} {circular 1} {\SomeShade{22}{circular}{2}} {circular 2} {\SomeShade{23}{circular}{3}} {circular 3} {\SomeShade{24}{circular}{4}} {circular 4} \stopcombination \stoplinecorrection \startlinecorrection[blank] \startcombination[4*2] {\SomeShade{32}{linear}{1}} {linear 1} {\SomeShade{32}{linear}{2}} {linear 2} {\SomeShade{33}{linear}{3}} {linear 3} {\SomeShade{34}{linear}{4}} {linear 4} {\SomeShade{35}{linear}{5}} {linear 5} {\SomeShade{36}{linear}{6}} {linear 6} {\SomeShade{37}{linear}{7}} {linear 7} {\SomeShade{38}{linear}{8}} {linear 8} \stopcombination \stoplinecorrection % % This limitation si no longer present in mpiv. % % Shading is not a \METAPOST\ feature, which means that it has to be implemented % using so called specials, directives that end up in the output file. % Unfortunately these are not coupled to the specific path, which means that we % have to do a significant amount of internal bookkeeping. Also, in \PDF\ we have % to make sure that the graphics and their resources (being the shading functions) % are packaged together. % % Because of this implementation, shading may behave somewhat unexpected at times. % A rather normal case is the next one, where we place 5~shaded circles in a row. % % \startbuffer % path p ; p := fullcircle scaled 1cm ; % for i=0 step 2cm until 8cm : % circular_shade(p shifted (i,0),0,\MPcolor{mycolora},\MPcolor{mycolorb}) ; % endfor ; % \stopbuffer % % \typebuffer % % \startlinecorrection[blank] % \processMPbuffer % \stoplinecorrection % % At first sight, in the next situation, we would expect something similar, because % we simply copy the same circle 5~times. However, due to the way we have % implemented shading in \CONTEXT, we do indeed copy the circles, but the shade % definition is frozen and the same one is used for all 5~circles. This means that % the center of the shading stays at the first circle. % % \startbuffer % circular_shade(fullcircle scaled 1cm,0,\MPcolor{mycolora},\MPcolor{mycolorb}) ; % picture s ; s := currentpicture ; currentpicture := nullpicture ; % for i=0 step 2cm until 8cm : % addto currentpicture also s shifted (i,0) ; % endfor ; % \stopbuffer % % \typebuffer % % \startlinecorrection[blank] % \processMPbuffer % \stoplinecorrection % % Unlike \TEX, \METAPOST\ does not keep its specials attached to the current path, % and flushes them before the graphic data. Since we use these specials to register % shading information, it is rather hard to tightly connect a specific shade with a % certain fill, especially if an already performed fill is not accessible, which is % the case when we copy a picture. % % This may seem a disadvantage, but fortunately it also has its positive side. In % the next example we don't copy, but reuse an already defined shade. By storing % the reference to this shade, and referring to it by using \type {withshade}, we % can use a shade that operates on multiple shapes. \startbuffer sh := define_circular_shade (origin,origin,0,8cm,\MPcolor{mycolora},\MPcolor{mycolorb}) ; for i=0 step 2cm until 8cm : fill fullcircle scaled 1cm shifted (i,0) withshade sh ; endfor ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection The low level macro \type {define_circular_shade} is fed with two pairs (points), two radius, and two colors. The shade is distributed between the colors according to the radius. Shading can hardly be called an easy issue. The macros that we provide here are in fact simplifications, which means that at a lower level, one can do more advanced things. Here we limit ourselves to the more common cases. In the previous examples, we used an arrow to indicate the direction and magnitude of the shade. The next macro demonstrates the principles in a different way. \startbuffer[a] def test_shade (expr a, b, ra, rb) = pickup pencircle scaled 1mm ; color ca ; ca := \MPcolor{mycolora} ; color cb ; cb := \MPcolor{mycolorb} ; color cc ; cc := \MPcolor{mycolorc} ; path pa ; pa := fullcircle scaled 2ra shifted a ; path pb ; pb := fullcircle scaled 2rb shifted b ; sh := define_circular_shade(a,b,ra,rb,ca,cb) ; fill pb withshade sh ; draw pb withcolor cc ; draw pa withcolor cc ; enddef ; \stopbuffer \typebuffer[a] The shade is distributed between two circles, each with a radius and center point. All four can be set, but as the next calls demonstrate, we can normally do with less, which is why we provided the macro with less parameters. \startbuffer[b] test_shade(origin, origin, 0cm, 1cm) ; \stopbuffer \startbuffer[c] test_shade(origin, origin, .25cm, 1cm) ; \stopbuffer \startbuffer[d] test_shade(origin, origin, .50cm, 1cm) ; \stopbuffer \startbuffer[f] \startlinecorrection[blank] \hbox {\processMPbuffer[a,b]\quad \processMPbuffer[a,c]\quad \processMPbuffer[a,d]} \stoplinecorrection \stopbuffer \typebuffer[b,c,d] \getbuffer[f] \startbuffer[b] test_shade(origin, origin shifted (.25cm,0), 0cm, 1cm) ; \stopbuffer \startbuffer[c] test_shade(origin, origin shifted (.25cm,0), .25cm, 1cm) ; \stopbuffer \startbuffer[d] test_shade(origin, origin shifted (.25cm,0), .50cm, 1cm) ; \stopbuffer \typebuffer[b,c,d] \getbuffer[f] \startbuffer[b] test_shade(origin shifted (.25cm,0), origin, 0cm, 1cm) ; \stopbuffer \startbuffer[c] test_shade(origin shifted (.25cm,0), origin, .25cm, 1cm) ; \stopbuffer \startbuffer[d] test_shade(origin shifted (.25cm,0), origin, .50cm, 1cm) ; \stopbuffer \typebuffer[b,c,d] \getbuffer[f] \startbuffer[a] def test_shade (expr a, b) = pickup pencircle scaled 1mm ; color ca ; ca := \MPcolor{mycolora} ; color cb ; cb := \MPcolor{mycolorb} ; color cc ; cc := \MPcolor{mycolorc} ; sh := define_linear_shade(a,b,ca,cb) ; fill fullsquare scaled 2cm withshade sh ; draw a withcolor cc ; draw b withcolor cc ; enddef ; \stopbuffer In a similar fashion, we can define a linear shade. This time we only pass two points and two colors. \typebuffer[a] Although one can control shading to a large extend, in practice only a few cases really make sense. \startbuffer[b] test_shade(origin, origin shifted (1cm,0)) ; \stopbuffer \startbuffer[c] test_shade(origin shifted (-1cm,0), origin shifted (1cm,0)) ; \stopbuffer \startbuffer[d] test_shade(origin shifted (-1cm,-1cm), origin shifted (1cm,1cm)) ; \stopbuffer \startbuffer[f] \startlinecorrection[blank] \hbox {\processMPbuffer[a,b]\quad \processMPbuffer[a,c]\quad \processMPbuffer[a,d]} \stoplinecorrection \stopbuffer \typebuffer[b,c,d] \getbuffer[f] \stopsubsection \startsubsection[title=The new method] By now the shader macros are rather advanced and specifications are easier than before. Here we discuss the new method. An example is: \startbuffer fill fullsquare xyscaled (TextWidth,1cm) withshademethod "linear" withshadevector (1,0) withshadecolors (darkred,darkgreen) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection There are several properties that can be set: \starttabulate[|l|p|] \NC domain \NC The range over which the colors run, with a minimum of 0 and maximum of 1. \NC \NR \NC color \NC A color to start from and one to end with, we default from black to white. \NC \NR \NC type \NC The shading can be linear or circular. \NC \NR \NC center \NC The origin of the shade vector. \NC \NR \NC radius \NC The radius vector of a circular shade. \NC \NR \NC vector \NC Where we start and end the shading. \NC \NR \stoptabulate For a linear shade the centers are the lower left and upper right corners, for a circular shade it's the center of the path. For a circular shade the radius runs from zero to the maximum distance from the center as determined by the boundingbox. The vector is used as follows: the first coordinate (xpart) determines the point on the path where we start, the second coordinate (ypart) the point on the path where we end. \startbuffer[a] fill fullsquare xyscaled (TextWidth,1cm) withshademethod "linear" withshadevector (1,0) withshadecolors (darkred,darkgreen) ; \stopbuffer \startbuffer[b] draw fullsquare xyscaled (TextWidth,1cm) shownshadevector (1,0) withpen pencircle scaled 2 withcolor .5white ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer[a,b] \stoplinecorrection In the end only the x coordinate matters, but using a point on the path sort of fits in \METAPOST. In the case of a rectangle we have 4 points while circle has 8 points. \startbuffer[a] fill fullcircle xyscaled (TextWidth,1cm) withshademethod "linear" withshadevector (2,4) withshadecolors (darkred,darkgreen) ; \stopbuffer \startbuffer[b] draw fullcircle xyscaled (TextWidth,1cm) shownshadevector (2,4) withpen pencircle scaled 2 withcolor .5white ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer[a,b] \stoplinecorrection A triangle has three points. Using 1 and 2 as second vector value gives the same results as do values in the range 0 upto 1 and 2 upto 3 (0 again). \startbuffer[a] fill fulltriangle xyscaled (TextWidth,1cm) withshademethod "linear" withshadevector (0.25,0.75) withshadecolors (darkred,darkgreen) ; \stopbuffer \startbuffer[b] draw fulltriangle xyscaled (TextWidth,1cm) shownshadevector (0.25,0.75) withpen pencircle scaled 2 withcolor .5white ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer[a,b] \stoplinecorrection The shadevector relates to (the x coordinates of) points on the path. A variant is to use the boundingbox: \startbuffer[a] for i=1 upto 3 : fill fulltriangle xyscaled (TextWidth,1cm) shifted (0,-i*15mm) withshademethod "linear" withshadedirection (1,1-i/4) withshadecolors (darkgreen,darkblue) ; endfor ; \stopbuffer \startbuffer[b] for i=1 upto 3 : draw fulltriangle xyscaled (TextWidth,1cm) shifted (0,-i*15mm) shownshadevector (1,1-i/4) withpen pencircle scaled 2 withcolor .5white ; endfor ; \stopbuffer \typebuffer[a] \startlinecorrection[blank] \processMPbuffer[a,b] \stoplinecorrection So, where a vector is defined as going from {\em point xpart a of pth} to {\em point ypart a of pth}, a direction goes from {\em point xpart a of boundingbox pth} to {\em point ypart a of boundingbox pth}. To make life convenient we provide a few constants that indicate directions: \starttyping pair shadedup ; shadedup := (0.5,2.5) ; pair shadeddown ; shadeddown := (2.5,0.5) ; pair shadedleft ; shadedleft := (1.5,3.5) ; pair shadedright ; shadedright := (3.5,1.5) ; \stoptyping \startbuffer[a] for d = shadedup, shadeddown, shadedleft, shadedright : fill fullsquare xyscaled (TextWidth,1cm) withshademethod "linear" withshadedirection d withshadecolors (darkgreen,darkblue) ; currentpicture := currentpicture shifted (0,15mm) ; endfor ; \stopbuffer \startbuffer[b] currentpicture := currentpicture shifted (0,-60mm) ; for d = shadedup, shadeddown, shadedleft, shadedright : draw fullsquare xyscaled (TextWidth,1cm) shownshadedirection d withpen pencircle scaled 2 withcolor .5white ; currentpicture := currentpicture shifted (0,15mm) ; endfor ; \stopbuffer \typebuffer[a] \startlinecorrection[blank] \processMPbuffer[a,b] \stoplinecorrection In case of a circular shade another method comes in handy: \startbuffer[a] fill fullcircle xyscaled (TextWidth,4cm) withshademethod "circular" withshadecenter (.7,.9) withshadecolors (darkblue,darkyellow) ; \stopbuffer \startbuffer[b] draw fullcircle xyscaled (TextWidth,4cm) shownshadecenter (.7,.9) withpen pencircle scaled 2 withcolor .5white ; \stopbuffer \typebuffer Here the values relate to the center of path i.e.\ they shift the center by the given fraction of the width and height of the boundingbox devided by 2. \startlinecorrection[blank] \processMPbuffer[a,b] \stoplinecorrection You can set a center directly i.e.\ unrelated to the center of the path as follows: \startbuffer[a] fill fullcircle xyscaled (TextWidth,4cm) withshademethod "circular" withshadeorigin (-30mm,-15mm) withshadecolors (darkblue,darkyellow) ; \stopbuffer \startbuffer[b] draw fullcircle xyscaled (TextWidth,4cm) shownshadeorigin (-30mm,-15mm) withpen pencircle scaled 2 withcolor .5white ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer[a,b] \stoplinecorrection In a similar way you can set an explicit radius: \startbuffer[a] fill fullcircle xyscaled (TextWidth,1cm) withshademethod "circular" withshaderadius (10mm,50mm) withshadecolors (darkblue,darkyellow) ; currentpicture := currentpicture shifted (0,15mm) ; fill fullcircle xyscaled (TextWidth,1cm) withshademethod "circular" withshaderadius (50mm,10mm) withshadecolors (darkgreen,darkred) ; currentpicture := currentpicture shifted (0,15mm) ; fill fullcircle xyscaled (TextWidth,1cm) withshademethod "circular" withshaderadius (TextWidth/3,0mm) withshadecolors (darkmagenta,darkcyan) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer[a] \stoplinecorrection A more fancy feature is combined shades. This works as follows: \startbuffer[a] fill fullsquare xyscaled (TextWidth,1cm) withshademethod "linear" withshadevector (0,1) withshadestep ( withshadefraction .3 withshadecolors (red,green) ) withshadestep ( withshadefraction .5 withshadecolors (green,blue) ) withshadestep ( withshadefraction .7 withshadecolors (blue,red) ) withshadestep ( withshadefraction 1 withshadecolors (red,yellow) ) ; \stopbuffer \typebuffer[a] By stepwise defining the colored bands you get: \startlinecorrection[blank] \processMPbuffer[a] \stoplinecorrection Shades work well with colors and transparencies. This involves quite some resource managament in the backend but it's hidden by the interface. \startbuffer[a] fill fullsquare scaled 5cm withshademethod "linear" withshadefactor 1 withshadedomain (0,1) withshadevector (0.5,2.75) withshadecolors (red,green) ; fill fullcircle scaled 5cm withshademethod "circular" withshadefactor 1 withshadedomain (0,1) withshadecenter (.25,.25) withshadecolors (green,blue) ; fill fulltriangle scaled 5cm withshademethod "circular" withshadefactor 1 withshadedomain (0,1) withshadecenter (.25,.25) withshadecolors (blue,yellow) ; \stopbuffer \startbuffer[b] fill fullsquare scaled 5cm withcolor white ; fill fullsquare scaled 5cm withshademethod "linear" withshadevector (0.5,2.75) withshadecolors (red,green) withtransparency (1,.5) ; fill fullcircle scaled 5cm withcolor white ; fill fullcircle scaled 5cm withshademethod "circular" withshadecenter (.25,.25) withshadecolors (green,blue) withtransparency (1,.5) ; fill fulltriangle scaled 5cm withcolor white ; fill fulltriangle scaled 5cm withshademethod "circular" withshadecenter (.25,.25) withcolor blue shadedinto yellow withtransparency (1,.5) ; \stopbuffer \startbuffer[c] fill fullsquare scaled 5cm withshademethod "linear" withshadevector (0.5,2.75) withshadecolors (red,green) withtransparency (1,.5) ; fill fullcircle scaled 5cm withshademethod "circular" withshadecenter (.25,.25) withcolor green shadedinto blue withtransparency (1,.5) ; fill fulltriangle scaled 5cm withshademethod "circular" withshadecenter (.25,.25) withcolor blue shadedinto yellow withtransparency (1,.5) ; \stopbuffer Here are some shades without transparency: \typebuffer[a] When the background is white, transparency is just a way to achieve soft colors. We leave out the defaults. \typebuffer[b] Real transparency will show op darker due to the accumulated colors. This time we demonstrate an alternative color specification. \typebuffer[c] \startplacefigure[reference=shades:transparency,title={Transparency applied to shades.}] \startcombination[3*1] {\processMPbuffer[a]} {no transparency} {\processMPbuffer[b]} {transparency on white} {\processMPbuffer[c]} {real transparency} \stopcombination \stopplacefigure Within reasonable bounds you can move around and adapt shaded paths but you need to keep in mind that due to the fact that we are dealing with relatively complex data structures there are some limits. For instance it is possible to define a shade as (kind of) variable and reuse it. it's also possible then to overload some properties. % % still supported but not advertized: % % numeric n ; n = define_linear_shade (center fullcircle,center fullsquare,red,green) ; % % fill fullcircle randomized 1cm xyscaled(10cm,8cm) withshade n ; \startbuffer defineshade myshade withshademethod "circular" withshadefactor 1 withshadedomain (0,1) withshadecolors (black,white) withtransparency (1,.5) ; for i=1 upto 5 : fill fullcircle randomized 1 xyscaled(5cm,3cm) shaded myshade ; endfor ; draw image ( for i=1 upto 5 : fill fullcircle randomized 1 shaded myshade withshadecolors (yellow,blue) ; endfor ; ) xyscaled(5cm,3cm) shifted (5cm,0) ; \stopbuffer \typebuffer We get two groups of five overlayed shades here, one with a different color. The shade properties can only be applied to paths (see \in {figure} [fig:shades:defined]). \startplacefigure[reference=fig:shades:defined,title={Reusing defined shaded.}] \processMPbuffer \stopplacefigure In older versions one could not reposition or scale a shaded path without losing or crippling the shade properties. Nowadays this is no longer a limitation, as we demonstrate in the following examples. You can disable this feature if wanted. The results are shown in \in {figure} [fig:shades:transform]. Without the transform the vectors and such are kept which might be useful in special cases. \startbuffer[a] fill fullsquare xyscaled (15mm, 15mm) withshademethod "linear" withshadedirection shadedright withshadecolors (red,(1,1,1)) ; fill fullsquare xyscaled (10mm, 10mm) withshademethod "circular" withshadecolors (green,blue) ; currentpicture := currentpicture xysized (.4TextWidth,30mm) ; currentpicture := currentpicture shifted (5mm,5mm) ; \stopbuffer \typebuffer[a] The transform can be ignored with: \startbuffer[b] fill fullsquare xyscaled (15mm, 15mm) withshademethod "linear" withshadetransform "no" withshadedirection shadedright withshadecolors (red,(1,1,1)) ; fill fullsquare xyscaled (10mm, 10mm) withshademethod "circular" withshadetransform "no" withshadecolors (green,blue) ; currentpicture := currentpicture xysized (.4TextWidth,30mm) ; currentpicture := currentpicture shifted (5mm,5mm) ; \stopbuffer \typebuffer[b] \startplacefigure[reference=fig:shades:transform,title={Shifting and scaling shades.}] \startcombination {\processMPbuffer[a]} {with transform} {\processMPbuffer[b]} {without transform} \stopcombination \stopplacefigure \stopsubsection \stopsection \startsection[title={Clipping}] \index{clipping} In this section we will use the graphic representation (although simplified) of a Dutch cow to demonstrate clipping. \startbuffer \placefigure {A cow.} {\externalfigure[cow-fun.mps][width=4cm]} \stopbuffer \getbuffer Since this cow is defined as a \METAPOST\ graphic, we use the suffix \type {mps} instead of \type {eps} or a number, although \CONTEXT\ will recognize each as being \METAPOST\ output. The placement of the cow is defined as: \typebuffer Clipping is combined with a matrix, as in \in {figure} [fig:clipped cow 1]. The content to be clipped is divided in \type {nx} by \type {ny} rectangles. For instance, \type {nx=5} and \type {ny=8} will produce a 40~cell grid with 5~columns of 8~rows. \startbuffer \startbuffer \setupclipping[nx=3,ny=2] \startcombination {\clip[x=1,y=1]{\externalfigure[cow-fun.mps][width=4cm]}} {1,1} {\clip[x=3,y=1]{\externalfigure[cow-fun.mps][width=4cm]}} {3,1} \stopcombination \stopbuffer \placefigure [here][fig:clipped cow 1] {A clipped cow.}{\getbuffer} \stopbuffer \getbuffer Here we have divided the cow in six cells, so that we can clip its head and tail. This kind of clipping enables you to zoom in or focus on a specific part of a graphic. \typebuffer Alternatively, we can specify a \type {width}, \type {height}, \type {hoffset} and \type {voffset}, as demonstrated in \in {figure} [fig:clipped cow 2]. \startbuffer \placefigure [here][fig:clipped cow 2] {Another clipped cow.} {\clip [width=2cm,height=2cm,hoffset=0cm,voffset=0cm] {\externalfigure[cow-fun.mps][width=4cm]}} \stopbuffer \getbuffer \typebuffer Because \METAPOST\ supports clipping, it will be no surprise that both techniques can be combined. In the next example we will zoom in on the head of the cow. We also use this opportunity to demonstrate how you can package a clip in a figure definition. \startbuffer \startMPclip{head clip} w := OverlayWidth ; h := OverlayHeight ; clip currentpicture to ((0,h)--(w,h){down}..{left}(0,0)--cycle) ; \stopMPclip \placefigure [here][fig:circular clipped cowhead] {A quarter circle applied to a cows head.} {\ruledhbox {\clip [nx=2,ny=2,x=1,y=1,mp=head clip] {\externalfigure[cow-fun.mps][width=4cm]}}} \stopbuffer \typebuffer A more advanced clip is demonstrated in \in {figure} [fig:circular clipped cowhead]. We added \type {\ruledhbox} to demonstrate the dimensions of the resulting graphic. Putting something in such a ruled box is often a quick way to test spacing. \getbuffer Although a clip path definition can contain any \METAPOST\ command, even graphics, it must contain at least one clipping path. The first one encountered in the resulting graphic is used. In the example we used a path that is built out of three subpaths. \starttyping (0,h)--(w,h){down}..{left}(0,0)--cycle \stoptyping We start in the top left corner and draw a straight line. Next we draw a curve to the origin. Directives like \type {down} and \type {right} force the curve in a certain direction. With \type {cycle} we close the path. Because we use this path as a clipping path, we use \type {clip} instead of \type {draw} or \type {fill}. \startbuffer w := 4cm ; h := 2cm ; draw (0,h)--(w,h){down}..{left}(0,0)--cycle withpen pencircle scaled 1mm withcolor .625red ; \stopbuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection Clipping as such is not limited to graphics. Take for instance the text buffer: \startbuffer \startbuffer[sample] \framed [align=middle,width=4cm,background=screen,frame=off] {A \METAPOST\ clip is not the same as a video clip, although we can use \METAPOST\ to produce a video clip.} \stopbuffer \stopbuffer \typebuffer \getbuffer We can call up such a buffer as if it were an external figure. \in {Figure} [fig:clipped text 1] shows the result. This time we use a different clip path: \startbuffer[a] \startMPclip{text clip} clip currentpicture to fullcircle shifted (.5,.5) xscaled OverlayWidth yscaled OverlayHeight ; \stopMPclip \stopbuffer \typebuffer[a] To load a buffer, we have to specify its name and type, as in: \startbuffer[b] \placefigure [here][fig:clipped text 1] {A clipped buffer (text).} {\clip [nx=1,ny=1,mp=text clip] {\externalfigure[sample][type=buffer,width=4cm]}} \stopbuffer \typebuffer[b] \getbuffer[a,b] The next few lines demonstrate that we can combine techniques like backgrounds and clipping. \startbuffer \startuseMPgraphic{clip outline} draw fullcircle xscaled \overlaywidth yscaled \overlayheight withpen pencircle scaled 4mm withcolor .625red ; \stopuseMPgraphic \defineoverlay[clip outline][\useMPgraphic{clip outline}] \placefigure [here][fig:clipped text 2] {A clipped buffer (text).} {\framed [background=clip outline,offset=overlay,frame=off] {\clip [nx=1,ny=1,mp=text clip] {\externalfigure[sample][type=buffer,width=4cm]}}} \stopbuffer \typebuffer We could have avoided the \type {\framed} here, by using the \typ{clip outline} overlay as a background of the sample. In that case, the resulting linewidth would have been 2.5~mm instead of 5~mm, since the clipping path goes through the center of the line. \getbuffer In most cases, the clip path will be a rather simple path and defining such a path every time you need it, can be annoying. \in {Figure} [fig:clipping paths] shows a collection of predefined clipping paths. These are available after loading the \METAPOST\ clipping library. \starttyping \useMPlibrary[clp] \stoptyping We already saw how the circular clipping path was defined. The diamond is defined in a similar way, using the predefined path \type {diamond}: \starttyping \startMPclip{diamond} clip currentpicture to unitdiamond xscaled OverlayWidth yscaled OverlayHeight ; \stopMPclip \stoptyping The definition of the negated ellipse (\type {negellipse}) uses the primary \type {peepholed}. This primary is defined in one of the \METAPOST\ modules that come with \CONTEXT. \starttyping \startMPclip{negellipse} clip currentpicture to (unitcircle peepholed unitsquare) xscaled OverlayWidth yscaled OverlayHeight ; \stopMPclip \stoptyping The definition of \type {peepholed} is rather dirty and using \type {peepholed} is restricted to well defined situations (like here). It's called a primary because it acts as an operator at the same level as \type {*} and \type {scaled}. \startbuffer \setupclipping [nx=1,ny=1,x=1,y=1] \setupblackrules[width=2cm,height=1cm] \startcombination[6*3] {\clip[mp=urellipse] {\darkred\blackrule}} {urellipse} {\clip[mp=ulellipse] {\darkred\blackrule}} {ulellipse} {\clip[mp=llellipse] {\darkred\blackrule}} {llellipse} {\clip[mp=lrellipse] {\darkred\blackrule}} {lrellipse} {\clip[mp=ellipse] {\darkred\blackrule}} {ellipse} {\clip[mp=negellipse]{\darkred\blackrule}} {negellipse} {\clip[mp=tellipse] {\darkred\blackrule}} {tellipse} {\clip[mp=bellipse] {\darkred\blackrule}} {bellipse} {\clip[mp=lellipse] {\darkred\blackrule}} {lellipse} {\clip[mp=rellipse] {\darkred\blackrule}} {rellipse} {} {} {} {} {\clip[mp=urtriangle]{\darkred\blackrule}} {urtriangle} {\clip[mp=ultriangle]{\darkred\blackrule}} {ultriangle} {\clip[mp=lltriangle]{\darkred\blackrule}} {lltriangle} {\clip[mp=lrtriangle]{\darkred\blackrule}} {lrtriangle} {\clip[mp=diamond] {\darkred\blackrule}} {diamond} {\clip[mp=negdiamond]{\darkred\blackrule}} {negdiamond} \stopcombination \stopbuffer \placefigure [here][fig:clipping paths] {A collection of predefined clipping paths.} {\getbuffer} \stopsection \startsection[title={Including graphics}] \index{graphics+including} This document demonstrates that it is no big problem to include \METAPOST\ graphics in a \TEX\ document. But how about including graphics in a \METAPOST\ picture? In this section we will explore a couple of macros that provide you this feature. Before we go into details, we introduce a very impressive program called \PSTOEDIT\ by Wolfgang Glunz. This program runs on top of \GHOSTSCRIPT\ and is able to convert \POSTSCRIPT\ code into other formats, among them \METAPOST\ (that part of the \PSTOEDIT\ code is due to Scott Pakin). Some of the graphics that we use in this section are produced that way. For us, the next call works well, but the exact call may differ per version or platform. \starttyping pstoedit -ssp -dt -f mpost yourfile.ps newfile.mp \stoptyping We have converted the Dutch cow that shows up in many \CONTEXT\ documents into \METAPOST\ using this program. The resulting \METAPOST\ file encapsulates the cow in \METAPOST\ figure~1: \type {beginfig(1)}. Of course you can process this file like any other, but more interesting is to use this code in an indirect way. \startbuffer loadfigure "mycow.mp" number 1 scaled .5 ; \stopbuffer \typebuffer This call will load figure~1 from the specified \METAPOST\ file, in such a way that there is no interference with the current (encapsulating) figure. \startlinecorrection[blank] \processMPbuffer \stoplinecorrection Because this graphic is the result from a conversion, there are only paths. If you want to import a more complex graphic, you need to make sure that the variables used in there do not conflict with the one currently in use. \METAPOST\ is good in drawing vector graphics, but lacks natural support for bitmaps, but the next macro offers a way out. This macro permits you to include graphics in \PNG, \PDF, and \JPG\ format, or more precise: those formats supported by \PDFTEX.\pagereference[hacker] \startbuffer draw externalfigure "hacker.png" xsized 5cm shifted (-6cm,0) ; draw externalfigure "hacker.png" xsized 5cm slanted .5 ; \stopbuffer \typebuffer You can apply the usual transformations, but only those applied directly will be taken into account. This means that you (currently) cannot store external figures in picture variables in order to transform them afterwards. \startlinecorrection[blank] \processMPbuffer \stoplinecorrection Although you are limited in what you can do with such graphics, you can include them multiple times with a minimum of overhead. Graphics are stored in objects and embedded only once. \startbuffer numeric s ; pair d, c ; for i := 1 upto 5 : s := 3cm randomized 1cm ; % size of picture c := .5(s,s) ; % center of picture d := (2cm*i,.5cm) randomized .5cm ; % displacement draw externalfigure "hacker.png" ysized s rotatedaround (c,0 randomized 30) shifted d ; endfor ; \stopbuffer \typebuffer Because we cannot store the graphic in a picture and scale afterwards, we calculate the scale in advance, so that we can rotate around the center. \startlinecorrection[blank] \processMPbuffer \stoplinecorrection As long as you don't mess around with a stored external figure, you're safe. The following example demonstrates how we can combine two special driven features: figure inclusion and shading. \startbuffer picture p ; p := externalfigure "hacker.png" xsized 150pt ; clip p to unitcircle scaled 150pt ; circular_shade(boundingbox p enlarged 10pt, 0, .2red, .9red) ; addto currentpicture also p ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection We end this section with a few more words to \METAPOST\ inclusion. It may seem that in order to use the features discussed here, you need to use \CONTEXT\ as typesetting engine. This is not true. First of all, you can use the small \TEX\ package \MPTOPDF\ (described in another manual) or you can make small \CONTEXT\ files with one page graphics. The advantage of the last method is that you can manipulate graphics a bit. \starttyping \setupcolors[cmyk=yes,rgb=no,state=start] \starttext \startMPpage[offset=6pt] loadfigure "niceone.mp" number 10 ; \stopMPpage \stoptext \stoptyping The resulting \PDF\ file can be included as any other graphic and has the advantage that it is self contained. \stopsection \startsection[reference=sec:conversion,title={Changing colors}] \index{color+manipulating} One of the advantages of \METAPOST\ graphics is that it is rather easy to force consistency in colors and line widths. You seldom can influence third party graphics that way, but we can use some \METAFUN\ trickery to get around this limitation. \startbuffer loadfigure "mycow.mp" number 1 scaled .35 ; refill currentpicture withcolor .625red ; \stopbuffer Say that we want a red cow instead of a black one. The following code does the trick: \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection In a similar way we can influence the width and colors of the lines. \startbuffer loadfigure "mycow.mp" number 1 scaled .35 ; refill currentpicture withcolor .625red ; redraw currentpicture withpen pencircle scaled 2pt withcolor .625yellow ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection Of course we can also use the more fancy features of \METAFUN, like transparency and shading. \startbuffer loadfigure "mycow.mp" number 1 scaled .35 ; numeric sh ; sh := define_linear_shade (llcorner currentpicture,urcorner currentpicture,.625red, .625yellow) ; refill currentpicture withshade sh ; redraw currentpicture withpen pencircle scaled 2pt withcolor .5white; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection Before we show a next trick, we draw a few circles. \startbuffer[a] fill fullcircle scaled 2cm withcolor yellow ; fill fullcircle scaled 2cm shifted (3cm,0) withcolor red ; \stopbuffer \typebuffer[a] \startlinecorrection[blank] \processMPbuffer[a] \stoplinecorrection The yellow and red color do not match the main document colors, but this is no problem: we can remap them, without spoiling the original definition. \startbuffer[b] remapcolor(yellow,.625yellow) ; remapcolor(red ,.625red) ; recolor currentpicture ; resetcolormap ; \stopbuffer \typebuffer[a,b] \startlinecorrection[blank] \processMPbuffer[a,b] \stoplinecorrection We can combine the inclusion technique with remapping colors. This time using an artist impression of one of Hasselts Canals (gracht in Dutch)\pagereference [canal]. \startbuffer[a] loadfigure "gracht.mp" number 1 scaled .5 ; \stopbuffer \typebuffer[a] \startlinecorrection[blank] \processMPbuffer[a] \stoplinecorrection If you think that the sky is too bright in this picture, and given that you also know which color is used, you can fool the reader by remapping a few colors. \startbuffer[b] color skycolor ; skycolor := (0.8,0.90,1.0) ; color watercolor ; watercolor := (0.9,0.95,1.0) ; remapcolor(skycolor ,.8skycolor ) ; remapcolor(watercolor,.8watercolor) ; recolor currentpicture ; resetcolormap ; \stopbuffer \typebuffer[a,b] \startlinecorrection[blank] \processMPbuffer[a,b] \stoplinecorrection Including another \METAPOST\ graphic, refilling, redrawing, and recoloring are all relatively simple features that use no real tricks. Opposite to the next feature, which is implemented using the \METAPOST\ special driver that comes with \CONTEXT. \METAPOST\ is not really meant for manipulating graphics, but the previous examples demonstrated that we have some control over individual colors. In the next series of examples we will treat the picture as a whole. First we invert the colors using \type {inverted}. \startbuffer loadfigure "gracht.mp" number 1 scaled .5 ; addto currentpicture also inverted currentpicture shifted (bbwidth(currentpicture)+.5cm,0) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection This is a special case of \type {uncolored}. In the next example we explicitly specify the color. \startbuffer loadfigure "gracht.mp" number 1 scaled .5 ; addto currentpicture also (currentpicture uncolored green) shifted (bbwidth(currentpicture)+.5cm,0) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection You can also multiply each color using \type {softened}. In the next sample, the colors have 80\% of their value. \startbuffer loadfigure "gracht.mp" number 1 scaled .5 ; addto currentpicture also (currentpicture softened .8) shifted (bbwidth(currentpicture)+.5cm,0) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection You can also use this operator to harden colors, simply by providing a value larger than~1. Keep in mind that colors are clipped at~1 anyway. \startbuffer loadfigure "gracht.mp" number 1 scaled .5 ; addto currentpicture also (currentpicture softened 1.2) shifted (bbwidth(currentpicture)+.5cm,0) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection By providing a triplet, you can treat each color component independently. \startbuffer loadfigure "gracht.mp" number 1 scaled .5 ; addto currentpicture also (currentpicture softened (.7,.8,.9)) shifted (bbwidth(currentpicture)+.5cm,0) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection After these examples your are probably sick of seeing this picture in color, so let's turn the colors into a weigthed grayscales (in a way similar to the way black and white television treated color). \startbuffer loadfigure "gracht.mp" number 1 scaled .5 ; addto currentpicture also grayed currentpicture shifted (bbwidth(currentpicture)+.5cm,0) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection \stopsection % \startsection[title={Outline fonts}] % % \index{text+outlines} % \index{outlines} % % Outline fonts don't belong to \METAPOST's repertoire of features. Nevertheless we % can simulate this in a reasonable way. We will not discuss all details here, % because most details are covered in the \MAKEMPY\ manual. % % The macro responsible for outline fonts is \type {graphictext}. The first % argument should be a string. This string is processed by \TEX. Additionally you % can provide transformation directives and color specifications. The next example % demonstrates this. % % \startbuffer % graphictext "\bf Fun" scaled 4 zscaled (1,1.5) % withdrawcolor blue % withfillcolor .5white % withpen pencircle scaled 5pt % \stopbuffer % % \typebuffer % % Once the text is typeset by \TEX, it is converted to \POSTSCRIPT\ and converted % into \METAPOST\ by the \PSTOEDIT\ program. The resulting graphic is imported, % analyzed, and processed conforming the specifications of \type {graphictext}. % % \startlinecorrection[blank] % \processMPbuffer % \stoplinecorrection % % By default the shapes are filled after they are drawn. This has the advantage % that in characters built out of pieces, disturbing lines fragments are covered. % The drawback is that you get only half the linewidth. You can reverse the drawing % order by adding the \type {reversefill} directive. The previous graphic then % comes out as: % % \startbuffer % graphictext "\bf Fun" scaled 4 zscaled (1,1.5) % reversefill % withdrawcolor blue % withfillcolor .5white % withpen pencircle scaled 5pt % \stopbuffer % % \typebuffer % % The \type {reversefill} directive can be countered by \type {outlinefill}. % % \startlinecorrection[blank] % \processMPbuffer % \stoplinecorrection % % The next example is taken from the \MAKEMPY\ manual. It demonstrates that you can % combine \TEX's powerful line breaking with \METAPOST's graphic capabilities. % % \startbuffer % \startuseMPgraphic{quotation} % picture one ; one := image ( graphictext % \MPstring{text} % scaled 1.5 % withdrawcolor .625blue % withfillcolor .625white % withpen pencircle scaled 1pt ; ) ; % picture two ; two := image ( graphictext % \MPstring{author} % scaled 2 % withdrawcolor .625red % withfillcolor .625white % withpen pencircle scaled 2pt ; ) ; % currentpicture := one ; % addto currentpicture also two % shifted lrcorner one % shifted - 1.125 lrcorner two % shifted (0, - 1.250 * ypart urcorner two) ; % setbounds currentpicture to boundingbox currentpicture enlarged 3pt ; % \stopuseMPgraphic % \stopbuffer % % \typebuffer \getbuffer % % In this graphic, we have two text fragments, the first one is a text, the second % one the name of the author. We combine the quotation and author into this graphic % using the following definitions: % % \startbuffer % \setMPtext{text} {\vbox{\hsize 8.5cm \input zapf }} % \setMPtext{author}{\hbox{\sl Hermann Zapf}} % \stopbuffer % % \typebuffer \getbuffer % % These definitions assume that the file \type {zapf.tex} is present on the system % (which is the case when you have installed \CONTEXT). The graphic can now be % typeset using the following call: % % \startbuffer % \placefigure % {A text does not need to be an outline in order to be % typeset in an outline font.} % {\useMPgraphic{quotation}} % \stopbuffer % % \typebuffer \getbuffer % % The quality of the output depends on how the glyphs are constructed. For % instance, in \TEX, math symbols are sometimes composed of glyph fragments and % rules. % % \startbuffer % graphictext % "$$\sqrt{1+x}$$" % scaled 8 % withdrawcolor .625red % withpen pencircle scaled 1.5pt % \stopbuffer % % \typebuffer % % \startlinecorrection[blank] % \processMPbuffer % \stoplinecorrection % % This is not really a problem because we can also fill the shapes. It is the % reason why the fill is applied after the draw and in such case the effective line % width is half the size specified. % % \startbuffer % graphictext % "$$\left({{\sqrt{1+x}}\over{\sqrt{2+x^2}}}\right)$$" % scaled 4 % dashed evenly % withdrawcolor .625red % withfillcolor .850white % withpen pencircle scaled 1.5pt % \stopbuffer % % \typebuffer % % In this example we also use a dashed line. Instead of normal colors, we could % have used shades or transparent colors. % % \startlinecorrection[blank] % \processMPbuffer % \stoplinecorrection % % Instead of supplying the text directly, you can use the indirect method. This % permits you to process rather complex data without messing up your \METAPOST\ % code. % % \startbuffer % \setMPtext {some math}% % {\usemodule[mathml] % \xmlprocessdata % {main} % { % % 2 % % x % 1 % % % } % {}} % \stopbuffer % % \typebuffer \getbuffer % % Here we feed some \MATHML\ into \TEX, which in turn shows up as a \METAPOST\ % graphic. % % \startbuffer % graphictext % \MPstring{some math} % scaled 4 % withdrawcolor .625red % withfillcolor .625white % withpen pencircle scaled 1.5pt % \stopbuffer % % \typebuffer % % \startlinecorrection[blank] % \processMPbuffer % \stoplinecorrection % % \stopsection \startsection[title={Outline fonts}] \index{text+outlines} \index{outlines} Outline fonts don't belong to \METAPOST's repertoire of features. Nevertheless we can simulate this in a reasonable way. The current version of \METAFUN\ uses the outline subsystem of \CONTEXT\ \MKIV, but in earlier days we used an external process: a \PDF\ file is generated that has the snippet, that gets converted to \POSTSCRIPT, which in turn is converted to \METAPOST\ with \type {pstoedit} and from that result we filter the outlines. This method uses \type {graphictext} and is covered in the \MAKEMPY\ manual. Here we discuss the new method using \type {outlinetext}. \startbuffer draw outlinetext.b("\bf Funky") (withcolor .5white) (withcolor blue withpen pencircle scaled 1/5) scaled 4 zscaled (1,0.5) ; \stopbuffer \typebuffer Once the text is typeset by \TEX, the result (a node list) is parsed and a \METAPOST\ representation is created. The glyphs are converted to outlines that are taken from the original font. For the moment this only works for \OPENTYPE\ fonts. \startlinecorrection[blank] \processMPbuffer \stoplinecorrection \startbuffer[1] draw outlinetext ("\bf Funky") scaled 3 ; \stopbuffer \startbuffer[2] draw outlinetext.d ("\bf Funky") (withcolor red withpen pencircle scaled 1/5) scaled 3 ; \stopbuffer \startbuffer[3] draw outlinetext.f ("\bf Funky") (withcolor blue) scaled 3 ; \stopbuffer \startbuffer[4] draw outlinetext.b ("\bf Funky") (withcolor blue) (withcolor red withpen pencircle scaled 1/5) scaled 3 ; \stopbuffer \startbuffer[5] draw outlinetext.r ("\bf Funky") (withcolor blue) (withcolor red withpen pencircle scaled 1/5) scaled 3 ; \stopbuffer \startplacetable[reference=tab:outlinetext,title={The four variants of \type {graphictext}.}] \bTABLE[offset=1ex] \dorecurse{5}{\bTR \bTD \processMPbuffer[#1] \eTD \bTD \typebuffer[#1] \eTD \eTR} \eTABLE \stopplacetable The five variants of this command are shown in \in {table} [tab:outlinetext]: the suffix determines the number of arguments and rendering. The \type {r} suffix reverses the order: the fill comes over the draw. There is a \type {p} suffix that returns just the picture. The next example demonstrates that you can combine \TEX's powerful line breaking algorithm with \METAPOST's graphic capabilities. \startbuffer \startuseMPgraphic{quotation} picture one ; one := image ( draw outlinetext.b (\MPstring{text}) (withcolor .625white) (withcolor .625blue withpen pencircle scaled 1/5) scaled 1.5 ) ; picture two ; two := image ( draw outlinetext.b (\MPstring{author}) (withcolor .625white) (withcolor .625red withpen pencircle scaled 1/5) scaled 2 ) ; currentpicture := one ; addto currentpicture also two shifted lrcorner one shifted - 1.125 lrcorner two shifted (0, - 2 * ypart urcorner two) ; setbounds currentpicture to boundingbox currentpicture enlarged 3pt ; \stopuseMPgraphic \stopbuffer \typebuffer \getbuffer In this graphic, we have two text fragments, the first one is a text, the second one the name of the author. We combine the quotation and author into this graphic using the following definitions: \startbuffer \setMPtext {text} {\vbox {\setupalign[verytolerant,stretch] \hsize 8.5cm \input zapf }} \setMPtext {author} {\hbox {\sl Hermann Zapf}} \stopbuffer \typebuffer \getbuffer These definitions assume that the file \type {zapf.tex} is present on the system (which is the case when you have installed \CONTEXT). The graphic can now be typeset using the following call: \startbuffer \placefigure [here] [fig:zapf] {A text does not need to be an outline in order to be typeset in an outline font.} {\useMPgraphic{quotation}} \stopbuffer \typebuffer The result is \in {figure} [fig:zapf]. The quality of the output depends on how the glyphs are constructed. For instance, in \TEX, math symbols are sometimes composed of glyph fragments and rules. \start \def||{-} \getbuffer \stop \startbuffer draw outlinetext.d ("\mathematics{\sqrt{1+x}}") (withcolor .625red withpen pencircle scaled 1/5) scaled 8 \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection This is not really a problem because we can also fill the shapes. It is the reason why the fill is applied after the draw and in such case the effective line width is half the size specified. \startbuffer draw outlinetext.b ("\mathematics{\left(\frac{\sqrt{1+x}}{\sqrt{2+x^2}}\right)}") (withcolor .850white) (withcolor .625red dashed evenly scaled .1 withpen pencircle scaled 1/5) scaled 8 \stopbuffer \typebuffer In this example (shown in \in {figure} [fig:dashedoutline]) we also use a dashed line. \placefigure [here] [fig:dashedoutline] {A dashed outline text.} {\processMPbuffer} Instead of supplying the text directly, you can use the indirect method. This permits you to process rather complex data without messing up your \METAPOST\ code. \startbuffer \usemodule[mathml] \setMPtext {some math}% {\xmlprocessdata {main} { 2 x 1 } {}} \stopbuffer \typebuffer \getbuffer Here we feed some \MATHML\ into \TEX, which in turn shows up as a \METAPOST\ graphic (\in {figure} [fig:mathml]). \startbuffer draw outlinetext.b (\MPstring{some math}) (withcolor .625white) (withcolor .625red withpen pencircle scaled 1/5) scaled 8 \stopbuffer \typebuffer \placefigure [here] [fig:mathml] {A \MATHML\ snippet turned into outlines.} {\processMPbuffer} Outlines are fun to look at. Here are a few ways to visualize a glyph: \startbuffer[1] \startcombination[3*1] {\ruledhbox\bgroup \showshape[character=(,alternative=text]% \egroup} {} {\ruledhbox\bgroup \showshape[character=a,alternative=text]% \egroup} {} {\ruledhbox\bgroup \showshape[character=x,alternative=text]% \egroup} {} \stopcombination \stopbuffer \typebuffer[1] You can control the rendering a bit by setting \type {option}. Possible options are: \type {box}, \type {width}, \type {min}, \type {max} and \type {comment}. The \type {simple} option disables all. The simple results are shown in \in{figure} [fig:showshape]. \startbuffer[2] \startcombination[3*1] {\ruledhbox\bgroup \showshape[character=(,alternative=text,option=simple]% \egroup} {} {\ruledhbox\bgroup \showshape[character=a,alternative=text,option=simple]% \egroup} {} {\ruledhbox\bgroup \showshape[character=x,alternative=text,option=simple]% \egroup} {} \stopcombination \stopbuffer \typebuffer[2] \startplacefigure[reference=fig:showshape,title={Showing shapes.}] \getbuffer[2] \stopplacefigure When you use this feature you need to be aware of the fact that fonts can have features, for instance ligatures and kerns between characters. In \in {figure} [fig:outlines:features] we see a few examples, one with Pagella (the Zapf quote) and one with Dejavu (the Tufte quote). \startplacefigure[reference=fig:outlines:features,title={Pagela and Dejavu}] \startcombination[1*4] \bgroup \def|#1|{-}% \definedfont[file:texgyrepagella-regular.otf*none]% \startMPcode draw outlinetext.b ("\framed[align=normal,width=max]{\input{zapf}}") (withcolor .375white) (withcolor .625red withpen pencircle scaled 1/10) ; \stopMPcode \egroup {pagella / no features} \bgroup \def|#1|{-}% \definedfont[file:texgyrepagella-regular.otf*default]% \startMPcode draw outlinetext.b ("\framed[align=normal,width=max]{\input{zapf}}") (withcolor .375white) (withcolor .625blue withpen pencircle scaled 1/10) ; \stopMPcode \egroup {pagella / default features} \bgroup \def|#1|{-}% \definedfont[file:dejavuserif.ttf*none]% \startMPcode draw outlinetext.b ("\framed[align=normal,width=max]{\input{tufte}}") (withcolor .375white) (withcolor .625green withpen pencircle scaled 1/10) ; \stopMPcode \egroup {dejavu serif / no features} \bgroup \def|#1|{-}% \definedfont[file:dejavuserif.ttf*default]% \startMPcode draw outlinetext.b ("\framed[align=normal,width=max]{\input{tufte}}") (withcolor .375white) (withcolor .625yellow withpen pencircle scaled 1/10) ; \stopMPcode \egroup {dejavu serif / default features} \stopcombination \stopplacefigure Given that a shape has a path that is suitable for it, you can use special effects, like: \startbuffer draw image ( draw outlinetext.d ("Abracadabra") (withpen pencircle scaled 1/10 dashed withdots scaled 1/20) ; ) xsized TextWidth ; \stopbuffer \typebuffer \startlinecorrection \processMPbuffer \stoplinecorrection The next example needs the \type {hanbatang-lvt.ttf} font so when you process this you might want to install that first. In \MKIV\ and \LMTX\ you can put that font in \typ {/texmf-fonts/data/hanbantang} or a similar path. We start by defining the font: % \definefontfeature % [korean-base] % [goodies=hanbatanglvt, % colorscheme=default, % mode=node, % script=hang, % language=kor] \startbuffer \definefontfeature [korean-base] [goodies=hanbatanglvt, colorscheme=default, mode=node, script=hang, language=kor] \definefont[KoreanFont][file:hanbatanglvt*korean-base] \stopbuffer \typebuffer \getbuffer Next we define a macro that will draw the outline: \startbuffer \startMPdefinitions string KoreanColors[] ; KoreanColors[1] := "darkred" ; KoreanColors[2] := "darkgreen" ; KoreanColors[3] := "darkblue" ; KoreanColors[4] := "darkyellow" ; KoreanColors[5] := "darkgray" ; newinternal KoreanSplit ; KoreanSplit := -1 ; newinternal KoreanCode ; KoreanCode := -2 ; newinternal KoreanMode ; KoreanMode := KoreanSplit ; def KoreanOutline(expr txt) = picture p ; p := outlinetext.p(txt) ; numeric n ; n := 0 ; string old, new ; old := "" ; for i within p : if KoreanMode == KoreanSplit : n := n + 1 ; elseif KoreanMode == KoreanCode : new := prescriptpart i ; if new <> old : old := new ; n := n + 1 ; fi ; else : n := KoreanMode ; fi ; if unknown KoreanColors[n] : n := 1 ; fi ; draw pathpart i withpen pencircle scaled 1/10 withcolor KoreanColors[n] ; endfor ; enddef ; def KoreanTest(expr txt) = image ( KoreanMode := KoreanSplit ; KoreanOutline(txt) ; currentpicture := currentpicture shifted (- xpart urcorner currentpicture, 0); KoreanMode := KoreanCode ; KoreanOutline(txt) ; currentpicture := currentpicture shifted (- xpart urcorner currentpicture, 0); KoreanMode := 3 ; KoreanOutline(txt) ; ) enddef ; \stopMPdefinitions \stopbuffer Because we want to reuse this definition, we define it for all what comes: \typebuffer \getbuffer % entered as three characters: ᄅ ᅡ ᆺ (mail collapses) % % \startMPcode KoreanTest("\KoreanFont 랏") ; \stopMPcode \startbuffer \startcombination[3*2] {\startMPcode draw KoreanTest("\KoreanFont 랏") ysized 15mm ; \stopMPcode} {} {\startMPcode draw KoreanTest("\KoreanFont 논") ysized 15mm ; \stopMPcode} {} {\startMPcode draw KoreanTest("\KoreanFont 왕") ysized 15mm ; \stopMPcode} {} {\startMPcode draw KoreanTest("\KoreanFont 닭") ysized 15mm ; \stopMPcode} {} {\startMPcode draw KoreanTest("\KoreanFont 박") ysized 15mm ; \stopMPcode} {} {\startMPcode draw KoreanTest("\KoreanFont 서") ysized 15mm ; \stopMPcode} {} \stopcombination \stopbuffer We use this macro in the following example. The results can be seen in \in {figure} [koreanoutlines]. There is one drawback of this example: It contributes a lot to the runtime: about 2.5~seconds to a 16~second run without this example. \footnote {This is partly due to an enforced intermediate garbage collection step.} The font itself loads fast but the outlines take their time because a few hundred megabytes of \LUA\ tables are involved. Instead you can define the feature to use \typ {goodies=hanbatanglvt} and \typ {colorscheme=default} and play with that. \typebuffer \startplacefigure[title=Some Korean magic,reference=koreanoutlines] \doifelsemode{optional} { \getbuffer } { \framed{A large optional example is not shown here!} } \stopplacefigure On the mailing list occasionally questions pop op with respect to outlines and user Garulfo came up with a neat solution for shaded text. First some examples: \startbuffer \startMPcode picture p ; p := lmt_outline [ text = "\strut foo f o o", drawcolor = "white", rulethickness = .2 ] ysized 3cm ; fill boundingbox p withshademethod "linear" withshadedirection(0,1) withshadecolors ("darkblue", "darkyellow") ; draw p; \stopMPcode \stopbuffer \typebuffer Here the background shines through the text: \startlinecorrection \getbuffer \stoplinecorrection You can actually use the effects features which for a larger text is more efficient because it just renders the font differently. The result is shown in \in {figure} [fig:effects:text]. \startbuffer[effects-text] \startuseMPgraphic{MyShade} fill OverlayBox withshademethod "linear" withshadedirection(0,1) withshadecolors (red, blue) ; \stopuseMPgraphic \defineoverlay[MyShade][\useMPgraphic{MyShade}] \setupbackgrounds[page][background=MyShade] \startmakeup \definedfont[SerifBold*default @ 50pt] \setupinterlinespace \defineeffect[MyOutline][alternative=outer,rulethickness=1pt] \startcolor[white] \starteffect[MyOutline] \input jojomayer \stopeffect \stopcolor \stopmakeup \stopbuffer \typebuffer[effects-text] \startplacefigure[title=Regular text effects,reference=fig:effects:text] \typesetbuffer[effects-text][height=.3\textheight] \stopplacefigure We now come to the neat example: \startbuffer \startMPcode picture tt ; tt := lmt_outline [ kind = "fillup", text = "\definedfont[name:texgyrepagellabold*default]foo f o o", ] xsized 12cm ; path bb ; bb := boundingbox tt ; path pp ; pp := bb enlarged 2cm ; fill pp withshademethod "linear" withshadedirection down withshadecolors ("darkred", "darkblue") ; for i within tt : nofill pathpart i; endfor ; eofill bb withcolor "darkgray" ; clip currentpicture to bb ; \stopMPcode \stopbuffer \typebuffer It uses a clever combination of refilling the shape and background: \startlinecorrection \getbuffer \stoplinecorrection \stopsection \startsection[title=Transparency groups] The following feature is not that usefull but implemented anyway. The \PDF\ reference says: \startitemize \startitem A group may be isolated or non-isolated, which shall determine the initial backdrop against which its stack is composited. \stopitem \startitem A group may be knockout or non-knockout, which shall determine whether the objects within its stack are composited with one another or only with the group’s backdrop. \stopitem \stopitemize and then carries on with a detailed explanation of groups. Here we stick to just mentioning how one can create a group in a picture. First we define a helper: \startbuffer \startMPdefinitions def ShowGroup (expr clr) (text grouped) = draw image ( drawarrow (10,0) -- (0,0) withtransparency(1,.5) withcolor clr ; ) grouped ; currentpicture := currentpicture xsized (TextWidth/8) ; setbounds currentpicture to boundingbox currentpicture enlarged 2mm ; addbackground withcolor .5white ; enddef ; \stopMPdefinitions \stopbuffer \typebuffer \getbuffer \startlinecorrection[blank] \startcombination[5*1] {\startMPcode ShowGroup(.5red) () \stopMPcode} {\tttf no group} {\startMPcode ShowGroup(.5green) (asgroup "") \stopMPcode} {\tttf group} {\startMPcode ShowGroup(.5blue) (asgroup "isolated") \stopMPcode} {\tttf isolated} {\startMPcode ShowGroup(.5cyan) (asgroup "knockout") \stopMPcode} {\tttf knockout} {\startMPcode ShowGroup(.5magenta)(asgroup "isolated,knockout") \stopMPcode} {\tttf isolated\crlf knockout} \stopcombination \stoplinecorrection The syntax is: \starttyping draw somepicture|somepath grouped "[isolated|knockout] ; \stoptyping The group becomes an object and is no longer part of the stream of graphic operators but a reference. For what it's worth: I never needed this feature. \stopsection \startsection[title=Decorating] Although the \METAPOST\ language is quite powerful the number of data types is not that large and when it comes to drawing stuff there are only paths and pictures. A path is a list of points (with controlpoints) and a few properties, like the pen, linewidth, linecap, color and such. For a long time in \METAFUN\ we used so called specials to implement extensions (like shading). This was done by using special colors and associating these with entries in the special section at the top of the output. Nowadays we use the pre- and postscript properties of paths. The advantage is that we can add whatever we want, as long as the backend supports it and because the backend is written in \LUA\ there are no real limitations. So, instead of extending \METAPOST\ we extend the \METAFUN\ macros and backend. Most extensions use the prescripts. Think of this: \starttyping draw fullcircle withprescript "do this" withprescript "and that" withprescript "and even more" ; \stoptyping Eventually this becomes a string: \starttyping and even moreand thatdo this \stoptyping \typebuffer The prescripts get prepended, while the postscripts (that we use for text only) get appended. When we draw a picture with properties (like color) they get overwritten but not so (with good reason) for the pre- and postscripts: these just accumulate. We will now demonstrate how we can manipulate the picture (a bit). \startbuffer picture MyShape ; MyShape := image ( fill fullsquare xyscaled (4,1) withcolor .625red ; fill fullsquare xyscaled (3,1) withcolor .625green ; fill fullsquare xyscaled (2,1) withcolor .625blue ; fill fullsquare xyscaled (1,1) withcolor .625yellow ; ) xysized (TextWidth,1cm) ; draw MyShape; \stopbuffer \typebuffer We just draw the (natural) picture: \startlinecorrection[blank] \processMPbuffer \stoplinecorrection When we draw the picture with a new color, all its components get recolored: \startbuffer draw MyShape withcolor .625magenta ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection However, when we add a transparency only the first component gets adapted because we use prescripts for this extension. (An extension using the postscripts would affect the last component.) \startbuffer draw MyShape withcolor .625magenta withtransparency (1,.5) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection The same logic applied to the \type {image}: prescripts get prepended to the first copmponent, postscripts to the last. \startbuffer draw image (draw MyShape) withcolor .625cyan ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection \startbuffer draw image (draw MyShape) withcolor .625cyan withtransparency (1,.5) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection The \type {undecorated} macro ignores the properties. We can't reset the scripts as this could ruin the effects like shading. \startbuffer draw undecorated (draw MyShape) withcolor .625white ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection The \type {decorated} macro applies the properties to each component. \startbuffer draw decorated (draw MyShape) withtransparency (1,.5) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection Here we kept the colors as they are but next we redo them: \startbuffer draw decorated (draw MyShape) withcolor .625magenta withtransparency (1,.5) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection The \type {redecorated} macro is the most intrusive as it resets the properties. This also means that you will loose texts, shades etc. \startbuffer draw redecorated (draw MyShape) withtransparency (1,.5) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection Indeed we get no color (but black) but we can bring back some color: \startbuffer draw redecorated (draw MyShape) withcolor .625yellow withtransparency (1,.5) ; \stopbuffer \typebuffer \startlinecorrection[blank] \processMPbuffer \stoplinecorrection \stopsection \startsection[title=Properties] The (plain) \METAPOST\ macro \type {drawoptions} stored its arguments in a macro that gets expanded when something is drawn (or filled). So, when you say \starttyping drawoptions(withcolor red) ; draw somepath ; \stoptyping This effectively is: \starttyping draw somepath withcolor red ; \stoptyping A disadvantage is that there is not much control over where it gets applied, especially when you hide drawing operations in macros. It's the reason why personally I always prefer explicit options. If you want some abstraction you can use the properties feature: \startbuffer \startMPcode property p[] ; p1 = properties(withcolor "darkred") ; p2 = properties(withcolor "darkblue") ; p3 = properties(withcolor "darkgreen") ; fill fullsquare xysized (TextWidth,12mm) withproperties p1 ; fill fullsquare xysized (TextWidth, 8mm) withproperties p2 ; fill fullsquare xysized (TextWidth, 4mm) withproperties p3 ; fill fullsquare xysized (TextWidth, 2mm) withproperties p1 ; \stopMPcode \stopbuffer \typebuffer We get: \startlinecorrection \getbuffer \stoplinecorrection Here we use an \quote {array} of properties but a single property is also possible: \startbuffer \startMPcode property p ; p = properties(withcolor "darkyellow") ; fill fullsquare xysized (TextWidth,4mm) withproperties p ; \stopMPcode \stopbuffer \typebuffer We get: \startlinecorrection \getbuffer \stoplinecorrection \stopsection \stopchapter \stopcomponent