summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/cld/cld-graphics.tex
blob: 93ab80c2c44fc7446e2f3fb6f0d9afe69dc84307 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
% language=uk

\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