1if not modules then modules = { } end modules ['driv-ini'] = {
2 version = 1.001,
3 comment = "companion to driv-ini.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local type = type
10local addsuffix = file.addsuffix
11
12local setmetatableindex = table.setmetatableindex
13local formatters = string.formatters
14
15local starttiming = statistics.starttiming
16local stoptiming = statistics.stoptiming
17
18local report = logs.reporter("drivers")
19
20local instances = { }
21local helpers = { }
22local converters = { }
23local prepared = { }
24local wrappedup = { }
25local cleanedup = { }
26local currentdriver = "default"
27local currentinstance = nil
28
29local shipout = tex.shipout
30local texgetbox = tex.getbox
31local texgetcount = tex.getcount
32
33local c_realpageno = tex.iscount("realpageno")
34
35function converters.engine(driver,boxnumber,mode,number,specification)
36 return shipout(boxnumber)
37end
38
39local prepare = nil
40local convert = nil
41local wrapup = nil
42local cleanup = nil
43local outputfilename = nil
44
45drivers = drivers or {
46 instances = instances,
47 helpers = helpers,
48 converters = converters,
49 lmtxversion = 0.10,
50 report = report,
51}
52
53local dummy = function() end
54
55local defaulthandlers = {
56 prepare = dummy,
57 initialize = dummy,
58 finalize = dummy,
59 updatefontstate = dummy,
60 wrapup = dummy,
61 cleanup = dummy,
62 convert = dummy,
63 outputfilename = dummy,
64}
65
66local installwhatsits do
67
68 local round = math.round
69
70 local leaderlevel = 0
71 local backends = backends
72 local trace = true
73
74 local latelua = backends.latelua
75 local writeout = backends.writeout
76 local openout = backends.openout
77 local closeout = backends.closeout
78
79 trackers.register("backends.whatsits",function(v) trace = v end)
80
81 local function pushleaderlevel()
82 leaderlevel = leaderlevel + 1
83 end
84
85 local function popleaderlevel()
86 leaderlevel = leaderlevel - 1
87 end
88
89 local function flushlatelua(current,h,v)
90
91
92 return latelua(current,h,v)
93 end
94
95 local function flushwriteout(current)
96 if leaderlevel == 0 then
97 writeout(current)
98 end
99 end
100
101 local function flushopenout(current)
102 if leaderlevel == 0 then
103 openout(current)
104 end
105 end
106
107 local function flushcloseout(current)
108 if leaderlevel == 0 then
109 closeout(current)
110 end
111 end
112
113 local function flushsavepos(current,pos_h,pos_v)
114 local jp = job.positions
115 jp.lastx = round(pos_h)
116 jp.lasty = round(pos_v)
117 end
118
119 local function flushuserdefined()
120
121 end
122
123 local whatsitcodes = nodes.whatsitcodes
124
125 installwhatsits = function(name,flushers)
126
127
128
129
130
131
132
133
134
135
136 local function checkagain(t, k)
137 local v = rawget(flushers,k)
138 if not v then
139 if trace then
140 report("unsupported whatsit %a in driver %a",whatsitcodes[k] or k,name)
141 end
142 v = function() end
143 end
144 t[k] = v
145 return v
146 end
147
148
149
150 local whatsit ; whatsit = setmetatableindex ( {
151 [whatsitcodes.literal] = flushers.literal or function(...) return checkagain(whatsit,whatsitcodes.literal )(...) end,
152 [whatsitcodes.save] = flushers.save or function(...) return checkagain(whatsit,whatsitcodes.save )(...) end,
153 [whatsitcodes.restore] = flushers.restore or function(...) return checkagain(whatsit,whatsitcodes.restore )(...) end,
154 [whatsitcodes.setmatrix] = flushers.setmatrix or function(...) return checkagain(whatsit,whatsitcodes.setmatrix )(...) end,
155 [whatsitcodes.startmatrix] = flushers.startmatrix or function(...) return checkagain(whatsit,whatsitcodes.startmatrix )(...) end,
156 [whatsitcodes.stopmatrix] = flushers.stopmatrix or function(...) return checkagain(whatsit,whatsitcodes.stopmatrix )(...) end,
157 [whatsitcodes.startscaling] = flushers.startscaling or function(...) return checkagain(whatsit,whatsitcodes.startscaling )(...) end,
158 [whatsitcodes.stopscaling] = flushers.stopscaling or function(...) return checkagain(whatsit,whatsitcodes.stopscaling )(...) end,
159 [whatsitcodes.startrotation] = flushers.startrotation or function(...) return checkagain(whatsit,whatsitcodes.startrotation )(...) end,
160 [whatsitcodes.stoprotation] = flushers.stoprotation or function(...) return checkagain(whatsit,whatsitcodes.stoprotation )(...) end,
161 [whatsitcodes.startmirroring] = flushers.startmirroring or function(...) return checkagain(whatsit,whatsitcodes.startmirroring)(...) end,
162 [whatsitcodes.stopmirroring] = flushers.stopmirroring or function(...) return checkagain(whatsit,whatsitcodes.stopmirroring )(...) end,
163 [whatsitcodes.startclipping] = flushers.startclipping or function(...) return checkagain(whatsit,whatsitcodes.startclipping )(...) end,
164 [whatsitcodes.stopclipping] = flushers.stopclipping or function(...) return checkagain(whatsit,whatsitcodes.stopclippin )(...) end,
165 [whatsitcodes.setstate] = flushers.setstate or function(...) return checkagain(whatsit,whatsitcodes.setstate )(...) end,
166
167 [whatsitcodes.latelua] = flushlatelua,
168 [whatsitcodes.userdefined] = flushuserdefined,
169 [whatsitcodes.savepos] = flushsavepos,
170 [whatsitcodes.open] = flushopenout,
171 [whatsitcodes.close] = flushcloseout,
172 [whatsitcodes.write] = flushwriteout,
173 }, checkagain)
174
175 flushers.whatsit = whatsit
176
177 flushers.pushleaderlevel = pushleaderlevel
178 flushers.popleaderlevel = popleaderlevel
179
180 end
181
182end
183
184function drivers.install(specification)
185 local name = specification.name
186 if not name then
187 report("missing driver name")
188 return
189 end
190 local actions = specification.actions
191 if not actions then
192 report("no actions for driver %a",name)
193 return
194 end
195 local flushers = specification.flushers
196 if not flushers then
197 report("no flushers for driver %a",name)
198 return
199 end
200 installwhatsits(name,flushers)
201
202 setmetatableindex(actions, defaulthandlers)
203 setmetatableindex(flushers, function() return dummy end)
204 instances[name] = specification
205end
206
207function drivers.convert(boxnumber)
208 if currentinstance then
209 callbacks.functions.start_page_number()
210 starttiming(drivers)
211 convert(currentinstance,boxnumber,texgetcount(c_realpageno))
212 stoptiming(drivers)
213 callbacks.functions.stop_page_number()
214 end
215end
216
217function drivers.outputfilename()
218 if currentinstance then
219 return outputfilename(currentinstance)
220 end
221end
222
223luatex.wrapup(function()
224 if currentinstance and wrapup and not wrappedup[currentdriver] then
225 starttiming(drivers)
226 wrapup(currentinstance)
227 stoptiming(drivers)
228 wrappedup[currentdriver] = true
229 cleanedup[currentdriver] = true
230 end
231end)
232
233luatex.cleanup(function()
234 if currentinstance and cleanup and not cleanedup[currentdriver] then
235 starttiming(drivers)
236 cleanup(currentinstance)
237 stoptiming(drivers)
238 wrappedup[currentdriver] = true
239 cleanedup[currentdriver] = true
240 end
241end)
242
243function drivers.enable(name)
244 if name ~= currentdriver then
245 if currentinstance then
246 starttiming(drivers)
247 cleanup(currentinstance)
248 stoptiming(drivers)
249 end
250 currentdriver = name or "none"
251 currentinstance = instances[currentdriver]
252 if currentinstance then
253 local actions = currentinstance.actions
254 prepare = actions.prepare
255 wrapup = actions.wrapup
256 cleanup = actions.cleanup
257 convert = actions.convert
258 outputfilename = actions.outputfilename
259
260 if prepare and not prepared[currentdriver] then
261 starttiming(drivers)
262 prepare(currentinstance)
263 stoptiming(drivers)
264 prepared[currentdriver] = true
265 end
266 else
267 report("bad driver")
268 end
269 end
270end
271
272statistics.register("driver time",function()
273 return statistics.elapsedseconds(drivers)
274end)
275
276interfaces.implement {
277 name = "shipoutpage",
278 arguments = "integer",
279 actions = drivers.convert,
280}
281
282interfaces.implement {
283 name = "enabledriver",
284 arguments = "string",
285 actions = drivers.enable,
286}
287
288do
289
290 local function prepare(driver)
291 converter = drivers.converters.lmtx
292 end
293
294 local function convert(driver,boxnumber,pagenumber)
295 converter(driver,texgetbox(boxnumber),"page",pagenumber)
296 end
297
298 drivers.install {
299 name = "empty",
300 actions = {
301 prepare = prepare,
302 convert = convert,
303 },
304 flushers = { },
305 }
306
307end
308
309setmetatableindex(instances,function() return instances.default end)
310
311
312
313drivers.install {
314 name = "none",
315 actions = { },
316 flushers = { },
317}
318
319drivers.enable("none")
320 |