driv-ini.lua /size: 6714 b    last modification: 2021-10-28 13:50
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
9-- This file is a bit overkill because it was meant for both luatex and luametatex
10-- but after the splti I decided not to simplify this one. It can only introduce
11-- issues.
12
13local type = type
14local addsuffix = file.addsuffix
15
16local setmetatableindex = table.setmetatableindex
17local formatters        = string.formatters
18
19local starttiming       = statistics.starttiming
20local stoptiming        = statistics.stoptiming
21
22local report            = logs.reporter("drivers")
23
24local instances         = { }
25local helpers           = { }
26local converters        = { }
27local prepared          = { }
28local wrappedup         = { }
29local cleanedup         = { }
30local currentdriver     = "default"
31local currentinstance   = nil
32
33local shipout           = tex.shipout
34local texgetbox         = tex.getbox
35local texgetcount       = tex.getcount
36
37function converters.engine(driver,boxnumber,mode,number,specification)
38    return shipout(boxnumber)
39end
40
41local prepare           = nil
42local convert           = nil
43local wrapup            = nil
44local cleanup           = nil
45local outputfilename    = nil
46
47drivers = drivers or {
48    instances   = instances,
49    helpers     = helpers,
50    converters  = converters,
51    lmtxversion = 0.10,
52    report      = report,
53}
54
55local dummy = function() end
56
57local defaulthandlers = {
58    prepare         = dummy,
59    initialize      = dummy,
60    finalize        = dummy,
61    updatefontstate = dummy,
62    wrapup          = dummy,
63    cleanup         = dummy,
64    convert         = dummy,
65    outputfilename  = dummy,
66}
67
68function drivers.install(specification)
69    local name = specification.name
70    if not name then
71        report("missing driver name")
72        return
73    end
74    local actions = specification.actions
75    if not actions then
76        report("no actions for driver %a",name)
77        return
78    end
79    local flushers = specification.flushers
80    if not flushers then
81        report("no flushers for driver %a",name)
82        return
83    end
84 -- report("driver %a is installed",name)
85    setmetatableindex(actions, defaulthandlers)
86    setmetatableindex(flushers, function() return dummy end)
87    instances[name] = specification
88end
89
90function drivers.convert(boxnumber)
91    if currentinstance then
92        callbacks.functions.start_page_number()
93        starttiming(drivers)
94        convert(currentinstance,boxnumber,texgetcount("realpageno"))
95        stoptiming(drivers)
96        callbacks.functions.stop_page_number()
97    end
98end
99
100function drivers.outputfilename()
101    if currentinstance then
102        return outputfilename(currentinstance)
103    end
104end
105
106luatex.wrapup(function()
107    if currentinstance and wrapup and not wrappedup[currentdriver] then
108        starttiming(drivers)
109        wrapup(currentinstance)
110        stoptiming(drivers)
111        wrappedup[currentdriver] = true
112        cleanedup[currentdriver] = true
113    end
114end)
115
116luatex.cleanup(function()
117    if currentinstance and cleanup and not cleanedup[currentdriver] then
118        starttiming(drivers)
119        cleanup(currentinstance)
120        stoptiming(drivers)
121        wrappedup[currentdriver] = true
122        cleanedup[currentdriver] = true
123    end
124end)
125
126function drivers.enable(name)
127    if name ~= currentdriver then
128        if currentinstance then
129            starttiming(drivers)
130            cleanup(currentinstance)
131            stoptiming(drivers)
132        end
133        currentdriver   = name or "default"
134        currentinstance = instances[currentdriver]
135        if currentinstance then
136            local actions   = currentinstance.actions
137            prepare         = actions.prepare
138            wrapup          = actions.wrapup
139            cleanup         = actions.cleanup
140            convert         = actions.convert
141            outputfilename  = actions.outputfilename
142            --
143            if prepare and not prepared[currentdriver] then
144                starttiming(drivers)
145                prepare(currentinstance)
146                stoptiming(drivers)
147                prepared[currentdriver] = true
148            end
149        else
150            report("bad driver")
151        end
152    end
153end
154
155statistics.register("driver time",function()
156    return statistics.elapsedseconds(drivers)
157end)
158
159interfaces.implement {
160    name      = "shipoutpage",
161    arguments = "integer",
162    actions   = drivers.convert,
163}
164
165interfaces.implement {
166    name      = "enabledriver",
167    arguments = "string",
168    actions   = drivers.enable,
169}
170
171-- The default driver:
172
173do
174
175    local filename = nil
176
177    drivers.install {
178        name     = "default",
179        actions  = {
180            convert        = drivers.converters.engine,
181            outputfilename = function(driver)
182                if not filename then
183                    filename = addsuffix(tex.jobname,"pdf")
184                end
185                return filename
186            end,
187        },
188        flushers = {
189            -- we always need this entry
190        },
191    }
192
193end
194
195-- No driver:
196
197do
198
199    drivers.install {
200        name     = "none",
201        actions  = { },
202        flushers = { },
203    }
204
205end
206
207do
208
209    local function prepare(driver)
210        converter = drivers.converters.lmtx
211    end
212
213    local function convert(driver,boxnumber,pagenumber)
214        converter(driver,texgetbox(boxnumber),"page",pagenumber)
215    end
216
217    drivers.install {
218        name     = "empty",
219        actions  = {
220            prepare = prepare,
221            convert = convert,
222        },
223        flushers = { },
224    }
225
226end
227
228--
229
230setmetatableindex(instances,function() return instances.default end)
231
232-- for now:
233
234drivers.enable("default")
235
236-- helpers
237
238local s_matrix_0 = "1 0 0 1"
239local f_matrix_2 = formatters["%.6N 0 0 %.6N"]
240local f_matrix_4 = formatters["%.6N %.6N %.6N %.6N"]
241
242function helpers.tomatrix(rx,sx,sy,ry,tx,ty) -- todo: tx ty
243    if type(rx) == "string" then
244        return rx
245    else
246        if not rx then
247            rx = 1
248        elseif rx == 0 then
249            rx = 0.0001
250        end
251        if not ry then
252            ry = 1
253        elseif ry == 0 then
254            ry = 0.0001
255        end
256        if not sx then
257            sx = 0
258        end
259        if not sy then
260            sy = 0
261        end
262        if sx == 0 and sy == 0 then
263            if rx == 1 and ry == 1 then
264                return s_matrix_0
265            else
266                return f_matrix_2(rx,ry)
267            end
268        else
269            return f_matrix_4(rx,sx,sy,ry)
270        end
271    end
272end
273