diff options
Diffstat (limited to 'doc/context/sources/general/manuals/metafun/metafun-effects.tex')
-rw-r--r-- | doc/context/sources/general/manuals/metafun/metafun-effects.tex | 2596 |
1 files changed, 2596 insertions, 0 deletions
diff --git a/doc/context/sources/general/manuals/metafun/metafun-effects.tex b/doc/context/sources/general/manuals/metafun/metafun-effects.tex new file mode 100644 index 000000000..74e7d487e --- /dev/null +++ b/doc/context/sources/general/manuals/metafun/metafun-effects.tex @@ -0,0 +1,2596 @@ +% language=uk +% +% copyright=pragma-ade readme=readme.pdf licence=cc-by-nc-sa + +% 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) ; +\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}{a=normal}} {\tttf normal} + {\useMPgraphic{test}{a=multiply}} {\tttf multiply} + {\useMPgraphic{test}{a=screen}} {\tttf screen} + {\useMPgraphic{test}{a=overlay}} {\tttf overlay} + {\useMPgraphic{test}{a=softlight}} {\tttf softlight} + {\useMPgraphic{test}{a=hardlight}} {\tttf hardlight} + {\useMPgraphic{test}{a=colordodge}} {\tttf colordodge} + {\useMPgraphic{test}{a=colorburn}} {\tttf colorburn} + {\useMPgraphic{test}{a=darken}} {\tttf darken} + {\useMPgraphic{test}{a=lighten}} {\tttf lighten} + {\useMPgraphic{test}{a=difference}} {\tttf difference} + {\useMPgraphic{test}{a=exclusion}} {\tttf exclusion} + {\useMPgraphic{test}{a=hue}} {\tttf hue} + {\useMPgraphic{test}{a=saturation}} {\tttf saturation} + {\useMPgraphic{test}{a=color}} {\tttf color} + {\useMPgraphic{test}{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[ta][s=.9,t=.7,a=11] +\definecolor[tb][s=.7,t=.7,a=11] +\definecolor[tc][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[ta]{\tf Hello}") scaled 5 ; +draw textext("\color[tb]{\bf Hello}") scaled 5 ; +draw textext("\color[tc]{\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[a][darkyellow] +\definecolor[b][s=.8] +\definecolor[c][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{a},\MPcolor{b}) ; +\stopuniqueMPgraphic + +\startuniqueMPgraphic{LinearShade} + path p ; + p := unitsquare xscaled \overlaywidth yscaled \overlayheight ; + linear_shade(p,0,\MPcolor{a},\MPcolor{b}); +\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{a},\MPcolor{b}) ; + \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{a},\MPcolor{b}) ; +% 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{a},\MPcolor{b}) ; +% 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{a},\MPcolor{b}) ; +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{a} ; + color cb ; cb := \MPcolor{b} ; + color cc ; cc := \MPcolor{c} ; + + 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{a} ; + color cb ; cb := \MPcolor{b} ; + color cc ; cc := \MPcolor{c} ; + + 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 := \width ; h := \height ; + 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 \width yscaled \height ; +\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 \width yscaled \height ; +\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 \width yscaled \height ; +\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" scaled 5cm shifted (-6cm,0) ; +draw externalfigure "hacker.png" scaled 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" + scaled 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" scaled 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} +% {<math xmlns='http://www.w3c.org/mathml' version='2.0'> +% <apply> <log/> +% <logbase> <cn> 2 </cn> </logbase> +% <apply> <plus/> +% <ci> x </ci> +% <cn> 1 </cn> +% </apply> +% </apply> +% </math>} +% {}} +% \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({{\sqrt{1+x}}\over{\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} + {<math xmlns='http://www.w3c.org/mathml' version='2.0'> + <apply> <log/> + <logbase> <cn> 2 </cn> </logbase> + <apply> <plus/> + <ci> x </ci> + <cn> 1 </cn> + </apply> + </apply> + </math>} + {}} +\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 with and without features, one with +Pagella (the Zapf quote) and one with Optima Nova (the Tufte quote). + +\startplacefigure[reference=fig:outlines:features,title={Pagela (\OPENTYPE) and Optima Nova (\TYPEONE)}] + \startcombination[1*4] + \bgroup + \def|#1|{-}% + \definedfont[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[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[lt55476.afm*none]% optima nova + \startMPcode + draw outlinetext.b + ("\framed[align=normal,width=max]{\input{tufte}}") + (withcolor .375white) + (withcolor .625green withpen pencircle scaled 1/10) ; + \stopMPcode + \egroup {optima nova / no features} + \bgroup + \def|#1|{-}% + \definedfont[lt55476.afm*default]% optima nova + \startMPcode + draw outlinetext.b + ("\framed[align=normal,width=max]{\input{tufte}}") + (withcolor .375white) + (withcolor .625yellow withpen pencircle scaled 1/10) ; + \stopMPcode + \egroup {optima nova / 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 + +\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 more<newline>and that<newline>do 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 |