From b9611ae3385982684139541e25153c73dae7af6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vlas=C3=A1k?= Date: Fri, 4 Feb 2022 21:08:06 +0100 Subject: [PATCH 1/9] Proof of concept resource management --- metapost/minim-mp.lua | 40 +++++++++++---------------------------- minim/minim-alloc.lua | 44 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/metapost/minim-mp.lua b/metapost/minim-mp.lua index 4bb600f..88b2f29 100644 --- a/metapost/minim-mp.lua +++ b/metapost/minim-mp.lua @@ -30,18 +30,8 @@ local M = {} local patterns = { }; M.patterns = patterns local colourspaces = { }; M.colourspaces = colourspaces -local global_resources, pattern_dict_objnum, colourspace_dict_objnum -function M.enable_resource_management() - if global_resources then return end - -- central dictionary objects - pattern_dict_objnum = pdf.reserveobj() - colourspace_dict_objnum = pdf.reserveobj() - global_resources = string.format('/Pattern %d 0 R /ColorSpace %d 0 R', - pattern_dict_objnum, colourspace_dict_objnum) - -- add to page and xform resources - pdf.setpageresources((pdf.getpageresources() or '')..global_resources) - pdf.setxformresources((pdf.getxformresources() or '')..global_resources) -end +-- dummy pattern to kick off the resources +alloc.add_page_resource('Pattern', 'MnmP', 'null') -- Saved patterns should have the following fields: -- objnum the reserved object number for the pattern (optional) @@ -55,29 +45,22 @@ end -- content the colour space contents (a pdf array) function M.write_resources() - if not global_resources then return end -- patterns - local used_patterns = { '<<' } for name, pat in pairs(patterns) do if pat.used then local objnum = pat.objnum or pdf.reserveobj() pdf.immediateobj(objnum, 'stream', pat.stream, pat.attr) - table.insert(used_patterns, string.format('%s %d 0 R', name, objnum)) + alloc.add_page_resource('Pattern', name, string.format('%d 0 R', objnum)) end end - table.insert(used_patterns, '>>') - pdf.immediateobj(pattern_dict_objnum, table.concat(used_patterns, ' ')) -- colour spaces - local used_spaces = { '<<' } for name, space in pairs(colourspaces) do if space.used then local objnum = space.objnum or pdf.reserveobj() pdf.immediateobj(objnum, space.content) - table.insert(used_spaces, string.format('%s %d 0 R', name, objnum)) + alloc.add_page_resource('ColorSpace', name, string.format('%d 0 R', objnum)) end end - table.insert(used_spaces, '>>') - pdf.immediateobj(colourspace_dict_objnum, table.concat(used_spaces, ' ')) end -- Write out resource objects at the end of the run @@ -337,14 +320,14 @@ end -- variables ‘stroke’ and ‘fill’ that record the last-used colour settings. -- preload device colour pattern colour spaces -colourspaces['/PsG'] = { content = '[ /Pattern /DeviceGray ]' } -colourspaces['/PsRG'] = { content = '[ /Pattern /DeviceRGB ]' } -colourspaces['/PsK'] = { content = '[ /Pattern /DeviceCMYK ]' } +colourspaces['PsG'] = { content = '[ /Pattern /DeviceGray ]' } +colourspaces['PsRG'] = { content = '[ /Pattern /DeviceRGB ]' } +colourspaces['PsK'] = { content = '[ /Pattern /DeviceCMYK ]' } local colour_template = { '%.3f ', '%.3f %.3f ', '%.3f %.3f %.3f ', '%.3f %.3f %.3f %.3f ' } local colour_stroke_operators = { 'G', nil, 'RG', 'K' } local colour_fill_operators = { 'g', nil, 'rg', 'k' } -local colour_pattern_spaces = { '/PsG', nil, '/PsRG', '/PsK' } +local colour_pattern_spaces = { 'PsG', nil, 'PsRG', 'PsK' } local function get_colour_params(cr) return format_numbers(colour_template[#cr], table.unpack(cr)) @@ -361,7 +344,7 @@ local function get_fill_colour(cr, pattern) if ptype == 2 then -- coloured pattern local space = colour_pattern_spaces[#cr] colourspaces[space].used = true - return string.format('%s cs %s%s scn', space, params, pname) + return string.format('/%s cs %s/%s scn', space, params, pname) elseif ptype == 1 then -- uncoloured pattern return string.format('/Pattern cs %s scn', pname) else -- should be unreachable @@ -720,8 +703,7 @@ end -- 2 patterns prescripts.fillpattern = function(append, str, object) - M.enable_resource_management() - local name = '/MnmP'..tonumber(str) + local name = 'MnmP'..tonumber(str) local pat = patterns[name] if not pat then alloc.err('Unknown pattern %s', name) @@ -783,7 +765,7 @@ local function definepattern(head, user, bb) string.format('%s\n/Matrix [ %s %s %s %s %s %s ]', bb, m.xx, m.xy, m.yx, m.yy, m.x, m.y), resources }, '') -- remember the pattern - patterns['/MnmP'..i.nr] = pat + patterns['MnmP'..i.nr] = pat end cb.register('finish_mpfigure', function(img) diff --git a/minim/minim-alloc.lua b/minim/minim-alloc.lua index f0cce35..13a99b8 100644 --- a/minim/minim-alloc.lua +++ b/minim/minim-alloc.lua @@ -331,6 +331,50 @@ end callback.register ('pre_dump', dump_saved_tables) +-- + +if pdf.add_page_resource then + + M.add_page_resource = pdf.add_page_resource + +else + local pdfdict_mt = { + __tostring = function(dict) + local out = {"<<"} + for k, v in pairs(dict) do + out[#out+1] = fmt("%s %s", M.pdf_name(k), tostring(v)) + end + out[#out+1] = ">>" + return table.concat(out, "\n") + end, + } + local function pdf_dict(t) + return setmetatable(t or {}, pdfdict_mt) + end + + local resource_dict_objects = {} + local page_resources = {} + function M.add_page_resource(type, name, value) + local resources = page_resources[type] + if not resources then + local obj = pdf.reserveobj() + pdf.setpageresources(fmt("%s /%s %d 0 R", pdf.getpageresources() or "", type, obj)) + resource_dict_objects[type] = obj + resources = pdf_dict() + page_resources[type] = resources + end + page_resources[type][name] = value + end + + callback.register("finish_pdffile", function() + for type, dict in pairs(page_resources) do + local obj = resource_dict_objects[type] + pdf.immediateobj(obj, tostring(dict)) + end + end) + +end + -- return M -- GitLab From 2a2e494a7975846fe3c477b637bcbc6fe69fce74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vlas=C3=A1k?= Date: Wed, 16 Feb 2022 19:13:34 +0100 Subject: [PATCH 2/9] Insert nil resource instead of null --- metapost/minim-mp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metapost/minim-mp.lua b/metapost/minim-mp.lua index 88b2f29..a5f855b 100644 --- a/metapost/minim-mp.lua +++ b/metapost/minim-mp.lua @@ -31,7 +31,7 @@ local patterns = { }; M.patterns = patterns local colourspaces = { }; M.colourspaces = colourspaces -- dummy pattern to kick off the resources -alloc.add_page_resource('Pattern', 'MnmP', 'null') +alloc.add_page_resource('Pattern', 'MnmP', nil) -- Saved patterns should have the following fields: -- objnum the reserved object number for the pattern (optional) -- GitLab From 9c60d85a25602302f89879fe9a250ecb5f591c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vlas=C3=A1k?= Date: Fri, 18 Feb 2022 17:59:45 +0100 Subject: [PATCH 3/9] Use string.format instead of fmt --- minim/minim-alloc.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/minim/minim-alloc.lua b/minim/minim-alloc.lua index 13a99b8..a57d80e 100644 --- a/minim/minim-alloc.lua +++ b/minim/minim-alloc.lua @@ -342,7 +342,7 @@ else __tostring = function(dict) local out = {"<<"} for k, v in pairs(dict) do - out[#out+1] = fmt("%s %s", M.pdf_name(k), tostring(v)) + out[#out+1] = string.format("%s %s", M.pdf_name(k), tostring(v)) end out[#out+1] = ">>" return table.concat(out, "\n") @@ -358,7 +358,7 @@ else local resources = page_resources[type] if not resources then local obj = pdf.reserveobj() - pdf.setpageresources(fmt("%s /%s %d 0 R", pdf.getpageresources() or "", type, obj)) + pdf.setpageresources(string.format("%s /%s %d 0 R", pdf.getpageresources() or "", type, obj)) resource_dict_objects[type] = obj resources = pdf_dict() page_resources[type] = resources -- GitLab From 9a7991ff6b013c71f05e1cab19f65d9fa2db9a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vlas=C3=A1k?= Date: Fri, 18 Feb 2022 18:09:06 +0100 Subject: [PATCH 4/9] Add PDF resources as they are used --- metapost/minim-mp.lua | 44 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/metapost/minim-mp.lua b/metapost/minim-mp.lua index a5f855b..014e498 100644 --- a/metapost/minim-mp.lua +++ b/metapost/minim-mp.lua @@ -30,9 +30,6 @@ local M = {} local patterns = { }; M.patterns = patterns local colourspaces = { }; M.colourspaces = colourspaces --- dummy pattern to kick off the resources -alloc.add_page_resource('Pattern', 'MnmP', nil) - -- Saved patterns should have the following fields: -- objnum the reserved object number for the pattern (optional) -- used true if the pattern is in use (should be set automatically) @@ -44,28 +41,27 @@ alloc.add_page_resource('Pattern', 'MnmP', nil) -- used true if the pattern is in use (should be set automatically) -- content the colour space contents (a pdf array) -function M.write_resources() - -- patterns - for name, pat in pairs(patterns) do - if pat.used then - local objnum = pat.objnum or pdf.reserveobj() - pdf.immediateobj(objnum, 'stream', pat.stream, pat.attr) - alloc.add_page_resource('Pattern', name, string.format('%d 0 R', objnum)) - end - end - -- colour spaces - for name, space in pairs(colourspaces) do - if space.used then - local objnum = space.objnum or pdf.reserveobj() - pdf.immediateobj(objnum, space.content) - alloc.add_page_resource('ColorSpace', name, string.format('%d 0 R', objnum)) - end +local function use_pattern(name) + local pat = patterns[name] + if not pat.used then + pat.used = true + local objnum = pat.objnum or pdf.reserveobj() + pat.objnum = objnum + pdf.immediateobj(objnum, 'stream', pat.stream, pat.attr) + alloc.add_page_resource('Pattern', name, string.format('%d 0 R', objnum)) end end --- Write out resource objects at the end of the run -cb.register('finish_pdffile', M.write_resources) - +local function use_colour_space(name) + local space = colourspaces[name] + if not space.used then + space.used = true + local objnum = space.objnum or pdf.reserveobj() + space.objnum = objnum + pdf.immediateobj(objnum, space.content) + alloc.add_page_resource('ColorSpace', name, string.format('%d 0 R', objnum)) + end +end -- 2 state metatable -- q Q store/restore graphics state @@ -343,7 +339,7 @@ local function get_fill_colour(cr, pattern) local ptype, pname = table.unpack(pattern) if ptype == 2 then -- coloured pattern local space = colour_pattern_spaces[#cr] - colourspaces[space].used = true + use_colour_space(space) return string.format('/%s cs %s/%s scn', space, params, pname) elseif ptype == 1 then -- uncoloured pattern return string.format('/Pattern cs %s scn', pname) @@ -709,7 +705,7 @@ prescripts.fillpattern = function(append, str, object) alloc.err('Unknown pattern %s', name) else append.pattern = { pat.painttype, name } - pat.used = true + use_pattern(name) end end -- GitLab From fa532ad2342b7b7727f08c29b92311fafc36c096 Mon Sep 17 00:00:00 2001 From: Esger Renkema Date: Thu, 17 Feb 2022 12:00:26 +0100 Subject: [PATCH 5/9] [minim] Optex register allocation compatibility Check for existence of optex allocation counts Remove unused lua-side local register allocation --- minim/minim-alloc.doc | 7 +++++-- minim/minim-alloc.lua | 30 ++++++++++++++---------------- minim/minim-alloc.tex | 5 ++++- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/minim/minim-alloc.doc b/minim/minim-alloc.doc index 9bd90f6..567d5a0 100644 --- a/minim/minim-alloc.doc +++ b/minim/minim-alloc.doc @@ -148,6 +148,7 @@ will be called. These are Register ⟦nil⟧ at the callback to pop a function off the stack. Finally, for the ⟦*simple⟧ callbacks +⟦uselanguage⟧, ⟦contribute_filter⟧, ⟦pre_dump⟧, ⟦wrapup_run⟧, @@ -159,8 +160,10 @@ Finally, for the ⟦*simple⟧ callbacks ⟦process_rule⟧. all registered functions are called in order with the same arguments. -The new ⟦*mlist_to_mlist⟧ callback is called before ⟦mlist_to_hlist⟧ and should -not convert noads to nodes. +Two callbacks are new: +the new ⟦*mlist_to_mlist⟧ callback is called before ⟦mlist_to_hlist⟧ and should +not convert noads to nodes, while the ⟦*uselanguage⟧ callback is called from +⟦\uselanguage⟧. If you create a new callback with a number for a name, that callback will replace the ⟦*process_rule⟧ callback when its number matches the index property diff --git a/minim/minim-alloc.lua b/minim/minim-alloc.lua index a57d80e..c189fab 100644 --- a/minim/minim-alloc.lua +++ b/minim/minim-alloc.lua @@ -206,7 +206,11 @@ M.unset = -0x7FFFFFFF -- works for both \chardef and the likes of \countdef function M.registernumber(csname) - return token.create(csname).index + if token.is_defined(csname) then + return token.create(csname).index + else + return -- would return 0 otherwise + end end -- we need remember lua-made allocations in the format file, since otherwise, @@ -241,8 +245,9 @@ make_alloc_new ('userrule' , 'e@alloc@rule@count' ) -- We need different allocation functions for the older registers, because -- etex’s global allocation macros are off-by-one w.r.t. all other. -- -local function make_alloc_old(fname, globcount, loccount) +local function make_alloc_old(fname, globcount) allocations[fname] = allocations[fname] or { } + local globcount = M.registernumber('_'..fname..'alloc') or globcount M['new_'..fname] = function (id) local nr if id and allocations[fname][id] then @@ -255,23 +260,16 @@ local function make_alloc_old(fname, globcount, loccount) end return nr end - if loccount then - M['local_'..fname] = function () - local nr = tex.count[loccount] - 1 - tex.setcount(loccount, nr) - return nr - end - end end -- existing allocation counters -make_alloc_old ('count', 260, 270 ) -make_alloc_old ('dimen', 261, 271 ) -make_alloc_old ('skip', 262, 272 ) -make_alloc_old ('muskip', 263, 273 ) -make_alloc_old ('box', 264, 274 ) -make_alloc_old ('toks', 265, 275 ) -make_alloc_old ('marks', 266, 276 ) +make_alloc_old ('count', 260 ) +make_alloc_old ('dimen', 261 ) +make_alloc_old ('skip', 262 ) +make_alloc_old ('muskip', 263 ) +make_alloc_old ('box', 264 ) +make_alloc_old ('toks', 265 ) +make_alloc_old ('marks', 266 ) function M.luadef (csname, fn, ...) local nr = M.new_function(csname) diff --git a/minim/minim-alloc.tex b/minim/minim-alloc.tex index 135b310..593bc04 100644 --- a/minim/minim-alloc.tex +++ b/minim/minim-alloc.tex @@ -132,7 +132,10 @@ % initialise new catcode tables \def\catcode:chardef#1#2{\chardef#1#2\initcatcodetable#2} -\csname e@alloc@ccodetable@count\endcsname = 4 % because ltluatex allocates 4... +% ltluatex initialises the catcode tables 1–4, so we make sure not to claim +% those ourselves: +\ifnum\csname e@alloc@ccodetable@count\endcsname = 0 + \csname e@alloc@ccodetable@count\endcsname = 4 \fi % set initial chunk name value \def\chardef:chunk#1#2{\chardef#1#2\directlua{lua.name[\the#2]='\csstring#1'}} -- GitLab From 55e6a2eaf9df3798440940f67508866a26bf73bf Mon Sep 17 00:00:00 2001 From: Esger Renkema Date: Sat, 19 Feb 2022 09:55:33 +0100 Subject: [PATCH 6/9] [minim] Improved ltluatex callback compatibility --- mathematics/minim-math.lua | 4 +- minim/README | 6 +- minim/minim-alloc.lua | 2 +- minim/minim-alloc.tex | 2 +- minim/minim-callbacks.lua | 162 +++++++++++++++++++++++++------------ xmp/minim-xmp.lua | 3 +- 6 files changed, 123 insertions(+), 56 deletions(-) diff --git a/mathematics/minim-math.lua b/mathematics/minim-math.lua index 7341e39..6373809 100644 --- a/mathematics/minim-math.lua +++ b/mathematics/minim-math.lua @@ -2,7 +2,7 @@ local M = {} local alloc = require ('minim-alloc') -local callbacks = require ('minim-callbacks') +local cb = require ('minim-callbacks') alloc.remember('minim-math') @@ -403,7 +403,7 @@ local function inspect_noads (h,d,n) return true end -callbacks.register ('mlist_to_mlist', inspect_noads) +cb.register ('mlist_to_mlist', inspect_noads) -- 1 Reading the math character table diff --git a/minim/README b/minim/README index b31907a..aa75e19 100644 --- a/minim/README +++ b/minim/README @@ -34,9 +34,13 @@ HISTORY 2022/1.1 (1/1/2022) - Updated the manual to reflect the latest versions of the other minims. + - Included a few helper functions moved in from minim-pdf. - Updated the allocation mechanism, distinguishing the new_() allocators from the new registernumber() function. - - Included a few helper functions moved in from minim-pdf. + - Fixed a bug where the primitive callback.register() could not remove list + callbacks (the module’s M.register() still cannot). + - Added an M.deregister() function for callbacks. + - Added a uselanguage callback. 2021/1.0 (1/6/2021) diff --git a/minim/minim-alloc.lua b/minim/minim-alloc.lua index c189fab..2bdac31 100644 --- a/minim/minim-alloc.lua +++ b/minim/minim-alloc.lua @@ -327,7 +327,7 @@ local function dump_saved_tables() lua.bytecode[saved_tables_bytecode] = load(saved_tables) end -callback.register ('pre_dump', dump_saved_tables) +cb.register ('pre_dump', dump_saved_tables) -- diff --git a/minim/minim-alloc.tex b/minim/minim-alloc.tex index 593bc04..642a7b2 100644 --- a/minim/minim-alloc.tex +++ b/minim/minim-alloc.tex @@ -82,7 +82,7 @@ % restore register allocation functions \directlua{ local C = require('minim-callbacks') callback.register, callback.find, callback.list - = C.register, C.find, C.list }% + = C.primitiveregister, C.find, C.list }% \let\noexpand\endinput=\noexpand\endinput:saved \noexpand\endinput}\fi} \def\minim:ltltx:fix#1{% diff --git a/minim/minim-callbacks.lua b/minim/minim-callbacks.lua index fb9368a..6ac9916 100644 --- a/minim/minim-callbacks.lua +++ b/minim/minim-callbacks.lua @@ -1,7 +1,9 @@ local M = {} -local function log(msg, ...) +local function log(...) end +local function alog(...) end +local function do_log(msg, ...) texio.write_nl('log', string.format(msg, ...)) end @@ -20,22 +22,31 @@ primitives.register = callback.register primitives.find = callback.find primitives.list = callback.list -local own_callbacks = {} -local callback_lists = {} +-- go through ltluatex if needed +local primitive_register = primitives.register +if luatexbase then + primitive_register = function(cb, f) + luatexbase.add_to_callback(cb, f, 'minim callback') + end +end + + +local own_callbacks = {} +local callback_lists = {} local callback_stacks = {} -- 1 finding callbacks -function M.find (name) - local f = own_callbacks[name] +function M.find(cb) + local f = own_callbacks[cb] if f == nil then - return primitives.find(name) + return primitives.find(cb) else return f end end -function M.list () +function M.list() local t = {} for n,f in pairs(callback_lists) do if f then @@ -44,14 +55,16 @@ function M.list () t[n] = false end end - for n,f in pairs(own_callbacks) do + -- no stack callbacks, since the active callback is in one of the two below + for n,f in pairs(primitives.list()) do if f then t[n] = t[n] or true else t[n] = t[n] or false end end - for n,f in pairs(primitives.list()) do + -- this might obscure primitive callbacks (this is intended) + for n,f in pairs(own_callbacks) do if f then t[n] = t[n] or true else @@ -63,42 +76,73 @@ end -- 1 registering callbacks -local function register_simple (cb,f) +local function register_simple(cb,f) -- prefer user-defined callbacks over built-in - local x = own_callbacks[cb] - if x == nil then - return primitives.register (cb, f) + local own = own_callbacks[cb] + log ('callback %s: %s (%s)', f == nil and 'removed' or f and 'set' or 'disabled', + cb, own == nil and 'primitive' or 'user-defined') + if own == nil then -- may be set to ‘false’ + return primitive_register(cb, f) else - -- default to false because nil would delete the callback itself - own_callbacks[cb] = f or false + own_callbacks[cb] = f or false -- ‘nil’ would delete the callback return -1 end end -- will be redefined later -local function announce_callback(cb, f) end -function M.register (cb, f) - announce_callback(cb, f) +function M.register(cb, f) local list = callback_lists[cb] + if list then + if list == nil then + return tex.error('Use ‘deregister’ for removing list callbacks') + else + list[#list+1] = f + log('callback set: %s (#%d on list)', cb, #list) + return -2 + end + end local stack = callback_stacks[cb] if stack then if f == nil then -- pop local p = stack[#stack] stack[#stack] = nil - return register_simple (cb,p) + return register_simple(cb,p) else -- push - stack[#stack+1] = M.find (cb) - return register_simple (cb,f) + stack[#stack+1] = M.find(cb) + return register_simple(cb,f) end - elseif list ~= nil then - list[#list+1] = f - return -2 - else - return register_simple (cb,f) end + return register_simple(cb, f) end +function M.deregister(cb, f) + local list = callback_lists[cb] + if list then + for i,g in ipairs(list) do + if f == g then + log('callback removed: %s (#%d on list)', cb, i) + table.remove(list, i) + return true, -2 + end + end + return false + end + local stack = callback_stacks[cb] + if stack then + for i,g in ipairs(stack) do + if f == g then + log('callback removed: %s (#%d on stack)', cb, i) + table.remove(stack, i) + return true, -3 + end + end + -- no return: fall through to next + end + if f == M.find(cb) then + return true, register_simple(cb, nil) + end +end -- 1 lists of callback functions @@ -169,22 +213,40 @@ function M.call_callback (name, ...) end end +-- 1 replace the primitive registering + +-- TODO: preserve return values +local primitively_registered = { } +function M.primitiveregister(cb, f) + local rv = false + if f == nil then + f = primitively_registered[cb] + if f == nil then + rv = M.register(cb) + else + _, rv = M.deregister(cb, f) + end + else + rv = M.register(cb, f) + end + alog(' through primitive interface') + primitively_registered[cb] = f + return rv +end + + -- 1 initialisation -- save all registered callbacks -local saved = {} -for n,s in pairs(primitives.list()) do - if s then - log('save callback: %s', n) - saved[n] = primitives.find(n) +if not luatexbase then + for n,s in pairs(primitives.list()) do + if s then + do_log('save callback: %s', n) + primitively_registered[n] = primitives.find(n) + end end end --- replace the primitive registering -callback.register = M.register -callback.find = M.find -callback.list = M.list - -- string processing callbacks register_list ('process_input_buffer', call_list_data) register_list ('process_output_buffer', call_list_data) @@ -202,7 +264,7 @@ register_list ('pre_output_filter', call_list_node) M.new_callback ('mlist_to_mlist', 'node') M.new_callback ('mlist_to_hlist', 'stack') M.register ('mlist_to_hlist', node.mlist_to_hlist ) -primitives.register ('mlist_to_hlist', function (head, ...) +primitive_register ('mlist_to_hlist', function (head, ...) local newhead = M.call_callback ('mlist_to_mlist', head, ...) if newhead ~= true then head = newhead or head @@ -232,7 +294,7 @@ stack_callback ('build_page_insert') -- process_rule M.new_callback ('process_rule', 'simple') -primitives.register ('process_rule', function (rule, ...) +primitive_register ('process_rule', function (rule, ...) local p = own_callbacks[rule.index] if p then p (rule, ...) @@ -242,23 +304,23 @@ primitives.register ('process_rule', function (rule, ...) end) -- restore all registered callbacks -for n,f in pairs(saved) do - log('restore callback: %s', n) - M.register (n,f) +for n,f in pairs(primitively_registered) do + do_log('restore callback: %s', n) + M.primitiveregister (n,f) end saved = nil +-- -local function announce_callback(cb, f) - if f then - log('callback added: %s', cb) - else - log('callback removed: %s', cb) - end -end - +-- replace primitive callbacks +callback.find = M.find +callback.list = M.list +callback.register = M.primitiveregister --- +log = do_log +local function alog(msg, ...) + texio.write('log', string.format(msg, ...)) +end return M diff --git a/xmp/minim-xmp.lua b/xmp/minim-xmp.lua index 096c24b..95275ae 100644 --- a/xmp/minim-xmp.lua +++ b/xmp/minim-xmp.lua @@ -2,6 +2,7 @@ local M = { } local alloc = require('minim-alloc') alloc.remember('minim-xmp') +local cb = require('minim-callbacks') local function sorted_pairs(t) local keys, i = { }, 0 @@ -506,7 +507,7 @@ M.aliases = { version = { 'xmpMM:VersionID' }, } -callback.register('finish_pdffile', function() +cb.register('finish_pdffile', function() if tex.count['writedocumentmetadata'] == 0 then return end if #XMP > 1 then alloc.err('Not all metadata has been written out.') -- GitLab From d16704f03cf5fb6850b25314f020a8e9387cbf58 Mon Sep 17 00:00:00 2001 From: Esger Renkema Date: Sat, 19 Feb 2022 10:27:40 +0100 Subject: [PATCH 7/9] [minim] Document the last commit --- minim/minim-alloc.doc | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/minim/minim-alloc.doc b/minim/minim-alloc.doc index 567d5a0..edf268c 100644 --- a/minim/minim-alloc.doc +++ b/minim/minim-alloc.doc @@ -97,21 +97,24 @@ take no parameters. As noted at the beginning of this chapter, the callback functions are only available after you say ⟦local C = require('minim-callbacks')⟧. -This module will override the primitive callback functions with its own -⟦*C.register⟧, ⟦*C.find⟧ and ⟦*C.list⟧; the original primitive functions can be -found in the ⟦*C.primitives⟧ table. - The simple function of this module is allowing multiple callbacks to co-exist. Different callbacks call for different implementations, and some callbacks can -only contain a single function. -Any callbacks that are already assigned before loading this module will be -preserved; this includes the ltluatex callback mechanism if it has already been -installed. +only contain a single function. Its interface matches the primitive interface, +with ⟦*C.register(callback, fn)⟧, ⟦*C.find(callback)⟧ and ⟦*C.list()⟧ taking +the same arguments. In addition to these, ⟦*C.deregister(fn)⟧ will allow you to +remove a callback. This is necessary when you want to remove a callback from +a list or from the bottom of a stack. The ⟦fn⟧ variable should point to the +same object. -You can create your own callbacks with ⟦*C.new_callback(name, type)⟧. The ⟦type⟧ -should be one of the types mentioned below or ⟦'single'⟧ for callbacks that -allow only one function. If the ⟦name⟧ is that of a primitive callback, new -registrations will target your new callback. +Any callbacks that are already assigned before loading this module will be +preserved and the primitive callback interface is still available, though +callbacks registered through the latter will actually use the new functions. +Ltluatex may be loaded either before or after this module. + +You can create your own callbacks with ⟦*C.new_callback(name, type)⟧. The +⟦type⟧ should be one of the types mentioned below or ⟦'single'⟧ for callbacks +that allow only one function. If the ⟦name⟧ is that of a primitive callback, +new registrations will target your new callback. You can call the new callback with ⟦*C.call_callback(name, ...)⟧, adding any number of parameters. @@ -126,7 +129,6 @@ Callbacks of this type are ⟦vpack_filter⟧, ⟦pre_output_filter⟧ and ⟦mlist_to_mlist⟧. -There is no way of unregistering callbacks of this type. Similarly, for the ⟦*data⟧ callbacks ⟦process_input_buffer⟧, -- GitLab From 7a59a742613f4d83527604d3325912e521c2c27e Mon Sep 17 00:00:00 2001 From: Esger Renkema Date: Fri, 25 Feb 2022 17:06:51 +0100 Subject: [PATCH 8/9] [minim] Fixes to the last three commits --- metapost/minim-mp.lua | 1 + minim/minim-alloc.lua | 1 - minim/minim-callbacks.lua | 12 +++++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/metapost/minim-mp.lua b/metapost/minim-mp.lua index 014e498..907bba0 100644 --- a/metapost/minim-mp.lua +++ b/metapost/minim-mp.lua @@ -139,6 +139,7 @@ local debugging = false function M.enable_debugging() debugging = true pdf.setcompresslevel(0) + pdf.setobjcompresslevel(0) end local function print_prop(append, obj, prop) diff --git a/minim/minim-alloc.lua b/minim/minim-alloc.lua index 2bdac31..ab5de3b 100644 --- a/minim/minim-alloc.lua +++ b/minim/minim-alloc.lua @@ -247,7 +247,6 @@ make_alloc_new ('userrule' , 'e@alloc@rule@count' ) -- local function make_alloc_old(fname, globcount) allocations[fname] = allocations[fname] or { } - local globcount = M.registernumber('_'..fname..'alloc') or globcount M['new_'..fname] = function (id) local nr if id and allocations[fname][id] then diff --git a/minim/minim-callbacks.lua b/minim/minim-callbacks.lua index 6ac9916..7268cb4 100644 --- a/minim/minim-callbacks.lua +++ b/minim/minim-callbacks.lua @@ -22,11 +22,17 @@ primitives.register = callback.register primitives.find = callback.find primitives.list = callback.list --- go through ltluatex if needed +-- use the ltluatex functions if needed local primitive_register = primitives.register if luatexbase then primitive_register = function(cb, f) - luatexbase.add_to_callback(cb, f, 'minim callback') + if f == nil then + luatexbase.remove_from_callback(cb, 'minim callback') + elseif f == false then + luatexbase.disable_callback(cb) + else + luatexbase.add_to_callback(cb, f, 'minim callback') + end end end @@ -94,7 +100,7 @@ end function M.register(cb, f) local list = callback_lists[cb] if list then - if list == nil then + if f == nil then return tex.error('Use ‘deregister’ for removing list callbacks') else list[#list+1] = f -- GitLab From 49c711bab493926edd4dcf974e542b7725247949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vlas=C3=A1k?= Date: Fri, 25 Feb 2022 17:39:18 +0100 Subject: [PATCH 9/9] Don't uninstall luatexbase, minim works with it --- minim/minim-callbacks.lua | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/minim/minim-callbacks.lua b/minim/minim-callbacks.lua index 7268cb4..af3db59 100644 --- a/minim/minim-callbacks.lua +++ b/minim/minim-callbacks.lua @@ -9,13 +9,6 @@ end -- 1 capturing the callback mechanism --- if ltluatex is loaded, we must get callback.register back -if luatexbase then - local luatex_base = luatexbase - luatexbase.uninstall() - luatexbase = luatex_base -end - local primitives = { } M.primitives = primitives primitives.register = callback.register @@ -35,7 +28,7 @@ if luatexbase then end end end - + local own_callbacks = {} local callback_lists = {} -- GitLab