% language=us runpath=texruns:manuals/cld \startcomponent cld-graphics \environment cld-environment \startchapter[title=Graphics] \startsection[title=The regular interface] If you are familiar with \CONTEXT, which by now probably is the case, you will have noticed that it integrates the \METAPOST\ graphic subsystem. Drawing a graphic is not that complex: \startbuffer context.startMPcode() context [[ draw fullcircle scaled 1cm withpen pencircle scaled 1mm withcolor .5white dashed dashpattern (on 2mm off 2mm) ; ]] context.stopMPcode() \stopbuffer \typebuffer We get a gray dashed circle rendered with an one millimeter thick line: \startlinecorrection \ctxluabuffer \stoplinecorrection So, we just use the regular commands and pass the drawing code as strings. Although \METAPOST\ is a rather normal language and therefore offers loops and conditions and the lot, you might want to use \LUA\ for anything else than the drawing commands. Of course this is much less efficient, but it could be that you don't care about speed. The next example demonstrates the interface for building graphics piecewise. \startbuffer context.resetMPdrawing() context.startMPdrawing() context([[fill fullcircle scaled 5cm withcolor (0,0,.5) ;]]) context.stopMPdrawing() context.MPdrawing("pickup pencircle scaled .5mm ;") context.MPdrawing("drawoptions(withcolor white) ;") for i=0,50,5 do context.startMPdrawing() context("draw fullcircle scaled %smm ;",i) context.stopMPdrawing() end for i=0,50,5 do context.MPdrawing("draw fullsquare scaled " .. i .. "mm ;") end context.MPdrawingdonetrue() context.getMPdrawing() \stopbuffer \typebuffer This gives: \startlinecorrection \ctxluabuffer \stoplinecorrection I the first loop we can use the format options associated with the simple \type {context} call. This will not work in the second case. Even worse, passing more than one argument will definitely give a faulty graphic definition. This is why we have a special interface for \METAFUN. The code above can also be written as: \startbuffer local metafun = context.metafun metafun.start() metafun("fill fullcircle scaled 5cm withcolor %s ;", metafun.color("darkblue")) metafun("pickup pencircle scaled .5mm ;") metafun("drawoptions(withcolor white) ;") for i=0,50,5 do metafun("draw fullcircle scaled %smm ;",i) end for i=0,50,5 do metafun("draw fullsquare scaled %smm ;",i) end metafun.stop() \stopbuffer \typebuffer Watch the call to \type {color}, this will pass definitions at the \TEX\ end to \METAPOST. Of course you really need to ask yourself \quotation {Do I want to use \METAPOST\ this way?}. Using \LUA\ loops instead of \METAPOST\ ones makes much more sense in the following case: \startbuffer local metafun = context.metafun function metafun.barchart(t) metafun.start() local t = t.data for i=1,#t do metafun("draw unitsquare xyscaled(%s,%s) shifted (%s,0);", 10, t[i]*10, i*10) end metafun.stop() end local one = { 1, 4, 6, 2, 3, } local two = { 8, 1, 3, 5, 9, } context.startcombination() context.combination(metafun.delayed.barchart { data = one }, "one") context.combination(metafun.delayed.barchart { data = two }, "two") context.stopcombination() \stopbuffer \typebuffer We get two barcharts alongside: \startlinecorrection \ctxluabuffer \stoplinecorrection \startbuffer local template = [[ path p, q ; color c[] ; c1 := \MPcolor{darkblue} ; c2 := \MPcolor{darkred} ; p := fullcircle scaled 50 ; l := length p ; n := %s ; q := subpath (0,%s/n*l) of p ; draw q withcolor c2 withpen pencircle scaled 1 ; fill fullcircle scaled 5 shifted point length q of q withcolor c1 ; setbounds currentpicture to unitsquare shifted (-0.5,-0.5) scaled 60 ; draw boundingbox currentpicture withcolor c1 ; currentpicture := currentpicture xsized(1cm) ; ]] local function steps(n) for i=0,n do context.metafun.start() context.metafun(template,n,i) context.metafun.stop() if i < n then context.quad() end end end context.hbox(function() steps(10) end) \stopbuffer \typebuffer \startlinecorrection \ctxluabuffer \stoplinecorrection Using a template is quite convenient but at some point you can loose track of the replacement values. Also, adding an extra value can force you to adapt the following ones which enlarges the change for making an error. An alternative is to use the template mechanism. Although this mechanism was originally made for other purposes, you can use it for whatever you like. \startbuffer local template = [[ path p ; p := fullcircle scaled 4cm ; draw p withpen pencircle scaled .5mm withcolor red ; freedotlabel ("%lefttop%", point 1 of p,origin) ; freedotlabel ("%righttop%", point 3 of p,origin) ; freedotlabel ("%leftbottom%", point 5 of p,origin) ; freedotlabel ("%rightbottom%",point 7 of p,origin) ; ]] local variables = { lefttop = "one", righttop = "two", leftbottom = "three", rightbottom = "four" , } context.metafun.start() context.metafun(utilities.templates.replace(template,variables)) context.metafun.stop() \stopbuffer \typebuffer Here we use named placeholders and pass a table with associated values to the replacement function. Apart from convenience it's also more readable. And the overhead is rather minimal. \startlinecorrection \ctxluabuffer \stoplinecorrection To some extent we fool ourselves with this kind of \LUA fication of \METAPOST\ code. Of course we can make a nice \METAPOST\ library and put the code in a macro instead. In that sense, doing this in \CONTEXT\ directly often gives better and more efficient code. Of course you can use all relevant commands in the \LUA\ interface, like: \starttyping context.startMPpage() context("draw origin") for i=0,100,10 do context("..{down}(%d,0)",i) end context(" withcolor \\MPcolor{darkred} ;") context.stopMPpage() \stoptyping to get a graphic that has its own page. Don't use the \type {metafun} namespace here, as it will not work here. This drawing looks like: \startlinecorrection \startluacode context.startMPcode() context("draw origin") for i=0,100,10 do context("..{down}(%d,0)",i) end context(" withcolor red ;") context.stopMPcode() \stopluacode \stoplinecorrection \stopsection \startsection[title=The \LUA\ interface] Messing around with graphics is normally not needed and if you do it, you'd better know what you're doing. For \TEX\ a graphic is just a black box: a rectangle with dimensions. You specify a graphic, in a format that the backend can deal with, either or not apply some scaling and from then on a reference to that graphic, normally wrapped in a normal \TEX\ box, enters the typesetting machinery. Because the backend, the part that is responsible for translating typeset content onto a viewable or printable format like \PDF, is built into \LUATEX, at some point the real image has to be injected and the backend can only handle a few image formats: \PNG, \JPG, \JBIG\ and \PDF. In \CONTEXT\ some more image formats are supported but in practice this boils down to converting the image to a format that the backend can handle. Such a conversion depends on an external programs and in order not to redo the conversion each run \CONTEXT\ keeps track of the need to redo it. Some converters are built in, for example one that deals with \GIF\ images. This is normally not a preferred format, but it happens that we have to deal with it in cases where organizations use that format (if only because they use the web). Here is how this works at the \LUA\ end: \starttyping figures.converters.gif = { pdf = function(oldname,newname) os.execute(string.format("gm convert %s %s",oldname,newname)) end } \stoptyping We use \type {gm} (Graphic Magic) for the conversion and pass the old and new names. Given this definition at the \TEX\ end we can say: \starttyping \externalfigure[whatever.gif][width=4cm] \stoptyping Here is a another one: \starttyping figures.converters.bmp = { pdf = function(oldname,newname) os.execute(string.format("gm convert %s %s",oldname,newname)) end } \stoptyping In both examples we convert to \PDF\ because including this filetype is quite fast. But you can also go to other formats: \starttyping figures.converters.png = { png = function(oldname,newname,resolution) local command = string.format('gm convert -depth 1 "%s" "%s"',oldname,newname) logs.report(string.format("running command %s",command)) os.execute(command) end } \stoptyping Instead of directly defining such a table, you can better do this: \starttyping figures.converters.png = figures.converters.png or { } figures.converters.png.png = function(oldname,newname,resolution) local command = string.format('gm convert -depth 1 "%s" "%s"',oldname,newname) logs.report(string.format("running command %s",command)) os.execute(command) end \stoptyping Here we check if a table exists and if not we extend the table. Such converters work out of the box if you specify the suffix, but you can also opt for a simple: \starttyping \externalfigure[whatever][width=4cm] \stoptyping In this case \CONTEXT\ will check for all known supported formats, which is not that efficient when no graphic can be found. In order to let for instance files with suffix \type {bmp} can be included you have to register it as follows. The second argument is the target. \starttyping figures.registersuffix("bmp","bmp") \stoptyping At some point more of the graphic inclusion helpers will be opened up for general use but for now this is what you have available. \stopsection \stopchapter \stopcomponent