pack-obj.lua /size: 7380 b    last modification: 2023-12-21 09:44
1if not modules then modules = { } end modules ['pack-obj'] = {
2    version   = 1.001,
3    comment   = "companion to pack-obj.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-- We save object references in the main utility table; job objects are reusable
10-- components.
11
12local context         = context
13local codeinjections  = backends.codeinjections
14local ctx_doifelse    = commands.doifelse
15
16local report          = logs.reporter("objects")
17local trace           = false  trackers.register("objects",function(v) trace = v end)
18
19local nuts            = nodes.nuts
20
21local setlink         = nuts.setlink
22local getlist         = nuts.getlist
23local setbox          = nuts.setbox
24
25local new_latelua     = nuts.pool.latelua
26
27local settexdimen     = tokens.setters.dimen
28
29local getcount        = tex.getcount
30
31local implement       = interfaces.implement
32local setmacro        = interfaces.setmacro
33
34local allocate        = utilities.storage.allocate
35
36local collected       = allocate()
37local tobesaved       = allocate()
38
39local jobobjects      = {
40    collected = collected,
41    tobesaved = tobesaved,
42}
43
44job.objects           = jobobjects
45
46local function initializer()
47    collected = jobobjects.collected
48    tobesaved = jobobjects.tobesaved
49end
50
51job.register('job.objects.collected', tobesaved, initializer, nil)
52
53local function saveobject(tag,number,page)
54    local data = { number, page }
55    tobesaved[tag] = data
56    collected[tag] = data
57end
58
59local function saveobjectspec(specification)
60    local tag  = specification.tag
61    local data = { specification.number, specification.page }
62    tobesaved[tag] = data
63    collected[tag] = data
64end
65
66local function setobject(tag,number,page)
67    collected[tag] = { number, page }
68end
69
70local function getobject(tag)
71    return collected[tag] or tobesaved[tag]
72end
73
74local function getobjectnumber(tag,default)
75    local o = collected[tag] or tobesaved[tag]
76    return o and o[1] or default
77end
78
79local function getobjectpage(tag,default)
80    local o = collected[tag] or tobesaved[tag]
81    return o and o[2] or default
82end
83
84jobobjects.save   = saveobject
85jobobjects.set    = setobject
86jobobjects.get    = getobject
87jobobjects.number = getobjectnumber
88jobobjects.page   = getobjectpage
89
90-- implement {
91--     name      = "saveobject",
92--     actions   = saveobject
93-- }
94--
95-- implement {
96--     name      = "setobject",
97--     actions   = setobject,
98--     arguments = { "string", "integer", "integer" }
99-- }
100--
101-- implement {
102--     name      = "objectnumber",
103--     actions   = { getobjectnumber, context },
104--     arguments = "2 strings",
105-- }
106--
107-- implement {
108--     name      = "objectpage",
109--     actions   = { getobjectpage, context },
110--     arguments = "2 strings",
111-- }
112--
113-- implement {
114--     name      = "doifelseobjectreferencefound",
115--     actions   = { getobject, commands.doifelse },
116--     arguments = "string"
117-- }
118
119-- if false then
120--     -- we can flush the inline ref ourselves now if we want
121--     local flush = new_latelua("pdf.flushxform("..index..")")
122--     flush.next = list
123--     next.prev = flush
124-- end
125
126local data = table.setmetatableindex("table")
127
128objects = {
129    data = data,
130    n    = 0,
131}
132
133local objects = objects
134
135function objects.register(ns,id,b,referenced,offset,mode)
136    local n = objects.n + 1
137    objects.n = n
138    nodes.handlers.finalizebox(b)
139    if mode == 0 then
140        -- tex
141        data[ns][id] = {
142            codeinjections.registerboxresource(b), -- a box number
143            offset,
144            referenced or false,
145            mode,
146        }
147    else
148        -- box (backend)
149        data[ns][id] = {
150            codeinjections.registerboxresource(b,offset), -- a box number
151            false,
152            referenced,
153            mode,
154        }
155    end
156    if trace then
157        report("registering object %a (n=%i)",id,n)
158    end
159end
160
161function objects.restore(ns,id) -- why not just pass a box number here too (ok, we also set offset)
162    local d = data[ns][id]
163    if d then
164        local index  = d[1]
165        local offset = d[2]
166        local status = d[3]
167        local mode   = d[4]
168        local hbox   = codeinjections.restoreboxresource(index) -- a nut !
169        if status then
170            local list = getlist(hbox)
171            local page = new_latelua {
172                action = saveobjectspec,
173                tag    = ns .. "::" .. id,
174                number = index,
175                page   = getcount("realpageno"),
176            }
177            -- list is a rule
178            setlink(list,page)
179        end
180        setbox("objectbox",hbox)
181        settexdimen("objectoff",offset or 0)
182    else
183        setbox("objectbox",nil)
184        settexdimen("objectoff",0) -- for good old times
185    end
186    if trace then
187        report("restoring object %a",id)
188    end
189end
190
191function objects.dimensions(index)
192    local d = data[ns][id]
193    if d then
194        return codeinjections.boxresourcedimensions(d[1])
195    else
196        return 0, 0, 0, 0
197    end
198end
199
200function objects.reference(ns,id)
201    local d = data[ns][id]
202    if d then
203        return d[1]
204    else
205        return getobjectnumber(ns .."::" .. id,0)
206    end
207end
208
209function objects.page(ns,id)
210    return getobjectpage(ns .."::" .. id,getcount("realpageno"))
211end
212
213function objects.found(ns,id)
214    return data[ns][id]
215end
216
217implement {
218    name      = "registerreferencedobject",
219    arguments = { "string", "string", "integer", true, "dimension", "integer" },
220    actions   = objects.register,
221}
222
223implement {
224    name      = "registerobject",
225    arguments = { "string", "string", "integer", false, "dimension", "integer" },
226    actions   = objects.register,
227}
228
229implement {
230    name      = "restoreobject",
231    arguments = "2 strings",
232    actions   = objects.restore,
233}
234
235implement {
236    name      = "doifelseobject",
237    arguments = "2 strings",
238    actions   = function(ns,id)
239        ctx_doifelse(data[ns][id])
240     -- ctx_doifelse(objects.reference(ns,id))
241    end,
242}
243
244implement {
245    name      = "doifelseobjectreference",
246    arguments = "2 strings",
247    actions   = function(ns,id)
248     -- ctx_doifelse(data[ns][id])
249        ctx_doifelse(objects.reference(ns,id))
250    end,
251}
252
253implement {
254    name      = "getobjectreference",
255    arguments = { "string", "string", "csname" },
256    actions   = function(ns,id,target)
257        setmacro(target,objects.reference(ns,id),"global")
258    end
259}
260
261implement {
262    name      = "getobjectreferencepage",
263    arguments = { "string", "string", "csname" },
264    actions   = function(ns,id,target)
265        setmacro(target,objects.page(ns,id),"global")
266    end
267}
268
269implement {
270    name      = "getobjectdimensions",
271    arguments = "2 strings",
272    actions   = function(ns,id)
273        local object = data[ns][id]
274        local w, h, d, o = 0, 0, 0, 0
275        if object then
276            w, h, d, o = codeinjections.boxresourcedimensions(object[1])
277        end
278        settexdimen("objectwd",w or 0)
279        settexdimen("objectht",h or 0)
280        settexdimen("objectdp",d or 0)
281        settexdimen("objectoff",o or #objects > 2 and object[2] or 0)
282    end
283}
284
285-- for the moment here:
286
287implement {
288    name      = "registerbackendsymbol",
289    arguments = { "string", "integer" },
290    actions   = function(...)
291        codeinjections.registersymbol(...)
292    end
293}
294