diff options
author | Norbert Preining <norbert@preining.info> | 2022-03-04 03:01:04 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2022-03-04 03:01:04 +0000 |
commit | 575ab7d0e7534edd510bbc89a2ef4b04582af591 (patch) | |
tree | 9fc4cf55b7ca8b168bdfd747be21de4c9ef2b30e /macros/luatex/generic/minim | |
parent | 6b9ed20cb01cb52c7aaf2a48202f5d8aa588ff79 (diff) |
CTAN sync 202203040301
Diffstat (limited to 'macros/luatex/generic/minim')
-rw-r--r-- | macros/luatex/generic/minim/README | 28 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-alloc.doc | 105 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-alloc.lua | 183 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-alloc.tex | 107 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-callbacks.lua | 175 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-doc.sty | 64 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-hooks.lua | 18 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-hooks.tex | 8 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-lmodern.tex | 18 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-pdfresources.lua | 154 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-pdfresources.tex | 51 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim-plain.tex | 14 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim.doc | 11 | ||||
-rw-r--r-- | macros/luatex/generic/minim/minim.pdf | bin | 285949 -> 317085 bytes |
14 files changed, 691 insertions, 245 deletions
diff --git a/macros/luatex/generic/minim/README b/macros/luatex/generic/minim/README index 4a16b4e801..31c34b28bf 100644 --- a/macros/luatex/generic/minim/README +++ b/macros/luatex/generic/minim/README @@ -1,4 +1,4 @@ -Version: 2021/1.0 +Version: 2022/1.1 SUMMARY @@ -29,9 +29,33 @@ For the sake of completeness, this manual also includes the documentation of the packages mentioned above. +HISTORY + +2022/1.1 (3/3/2022) + + Major changes: + + * Updated the allocation mechanism, distinguishing the new_<register>() + allocators from the new registernumber() function. + * Included a new (pgf-compatible) pdf resource manager. + + Minor changes: + + * Updated the manual to reflect the latest versions of the other minims. + * 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) + + This was the original release. + + COPYING -(c) 2021 Esger Renkema +(c) 2022 Esger Renkema, Michal Vlasák These files may be distributed under the terms of the European Union Public Licence (EUPL) version 1.2 or later. A copy can be obtained at: diff --git a/macros/luatex/generic/minim/minim-alloc.doc b/macros/luatex/generic/minim/minim-alloc.doc index fa08988bf4..edf268c81d 100644 --- a/macros/luatex/generic/minim/minim-alloc.doc +++ b/macros/luatex/generic/minim/minim-alloc.doc @@ -1,6 +1,8 @@ \input minim-doc.sty +\chapter Programming macros + This chapter describes the programming helper modules on which all the above modules depend. It mainly concerns register allocation, callback management and format file inclusion. @@ -78,15 +80,8 @@ name, the number of that register will be returned. You will need this when you want to allow your lua code to be included in a format file; it has nothing to do with the tex-side ⟦\countdef⟧ and the like. -For the new allocation macros listed above and (as a special case) for -⟦\newbox⟧, -after saying ⟦\newwhatsit\name⟧, the call ⟦M.new_whatsit('name')⟧ will return -the number of ⟦\name⟧. For the other (older) allocation macros, this is not the -case. After all, because of the ⟦\countdef⟧ etc. included in ⟦\newcount⟧ etc. -you can already use ⟦tex.count['name']⟧ etc. for retrieving tex-side -allocations from lua. The exceptions to this are ⟦\newbox⟧, which is why it is -included with the new macros, and ⟦\newattribute⟧, for which you can use both -methods. +If you want to access from lua a register defined in tex, the function +⟦*M.registernumber('name')⟧ will give you the index of register ⟦\name⟧. Besides ⟦\newluachunkname\name⟧, you can also use ⟦*\setluachunkname \name {actual name}⟧ @@ -102,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. @@ -131,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⟧, @@ -153,6 +150,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⟧, @@ -164,21 +162,50 @@ 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 of the rule. +\section Programming helpers + +Optional keyword arguments to tex macros can be defined with help of +⟦*M.options_scanner()⟧. An example from the definition of minim-pdf’s +⟦\outline⟧: + +⟦ local s = M.options_scanner() + :keyword('open', 'closed') + :string('dest') + :scan() + s.title = token.scan_string() + M.add_bookmark(s)⟧ + +Here, the ⟦keyword⟧ function adds two opposite keywords: if one is present, its +value will be set to ⟦true⟧ and the other’s to ⟦false⟧ (the second keyword is +optional). The ⟦string⟧ function stores the result of ⟦token.scan_string⟧ under +its key. Of the same form you have ⟦int⟧, ⟦glue⟧, ⟦dimen⟧, ⟦argument⟧, ⟦word⟧ +and ⟦list⟧. All these take an optional second argument: if ⟦true⟧ then the +keyword can be repeated and its values will be stored as a list. + +The ⟦scan⟧ function, finally, scans all keywords, which may appear in any +order. You can give it a table with default values. In the example given above, +the argument ⟦s⟧ to ⟦M.add_bookmark⟧ will consist of a table with at most the +following entries: ⟦open⟧, ⟦closed⟧, ⟦dest⟧ and ⟦title⟧, though entries whose +keywords do not occur will not be present. + +This function is particularly useful when used together with +⟦*M.luadef('csname', function, ...)⟧, which defines primitive-like tex macros +from lua. There, ⟦function⟧ can be any function (it will be assigned a lua +function register) and at the place of the dots you may append ⟦'protected'⟧ +and/or ⟦'global'⟧. -\section Miscellaneous functions -This section describes functions and macros that are internal to this package, -but might be of general usefulness. +\section Miscellaneous functions -For instance, you might find the function ⟦*M.table_to_text(table)⟧ useful when -debugging lua code. The small functions ⟦*M.msg(...)⟧, ⟦*M.log(...)⟧ and ⟦*M.err(...)⟧ include a call to ⟦M.string.format⟧; @@ -186,14 +213,24 @@ additionally, ⟦*M.amsg(...)⟧ and ⟦*M.alog(...)⟧ do not start a new line. -Very useful is ⟦*M.luadef('csname', function, ...)⟧ for defining primitive-like -tex macros from lua: ⟦function⟧ can be any function (it will be assigned a lua -function register) and at the place of the dots you may append ⟦'protected'⟧ -and/or ⟦'global'⟧. - Both ⟦*M.unset⟧ and ⟦*\unset⟧ contain the value ⟦-0x7FFFFFFF⟧ that can be used for clearing attributes. +When writing data to pdf literals, ⟦*M.pdf_string(...)⟧, +⟦*M.pdf_name(...)⟧ and ⟦*M.pdf_date(...)⟧ may be useful: they produce strings +that can be written to the pdf directly. Surrounding ⟦<>⟧ or ⟦()⟧ characters or +a leading ⟦/⟧ will be included in the return value. The ⟦M.pdf_date⟧ function +expects a value of the form ⟦yyyy[-mm[-dd]]⟧ and returns a date of the form +⟦(D:yyyymmdd)⟧. +The function ⟦M.pdf_string⟧ is also available to tex through the macro +⟦*\pdfstring⟧. + +Finally the function ⟦*M.table_to_text(table)⟧ may be useful when debugging lua +code: it dumps a table as a (lua-readable) string. Cyclic references will spin +in into an eternal loop, however. + +\section Miscellaneous helper macros + On the tex side, ⟦*\voidbox⟧, ⟦*\ignore⟧, ⟦*\spacechar⟧, ⟦*\unbrace⟧, ⟦*\firstoftwo⟧ and ⟦*\secondoftwo⟧ should be self-explanatory and uncontroversial additions. For looking ahead, you can use diff --git a/macros/luatex/generic/minim/minim-alloc.lua b/macros/luatex/generic/minim/minim-alloc.lua index c99ca2c73d..8f6a69ed0d 100644 --- a/macros/luatex/generic/minim/minim-alloc.lua +++ b/macros/luatex/generic/minim/minim-alloc.lua @@ -27,6 +27,131 @@ function M.err (...) tex.error(string.format(...)) end +-- 1 pdf helpers + +local function insert_formatted(t, ...) + table.insert(t, string.format(...)) +end + +local function hexify(c) + return string.format('#%02x', c:byte()) +end +function M.pdf_name(n) + return '/'..n + :gsub('[][(){}<>#%%/\\]', hexify) + :gsub('%G', hexify) +end + +-- re-encode to utf-16 +local function pdf_hex_string(text) + local str = { [1] = '<feff' } + for i in text:utfvalues() do + if i <= 0xffff then + insert_formatted(str, '%04x', i) + else + i = i - 0x10000 + m = math.floor(i/0x400) + 0xd800 + n = ( i % 0x400 ) + 0xdc00 + insert_formatted(str, '%04x%04x', m, n) + end + end + table.insert(str, '>') + return table.concat(str,'') +end +local function octify(c) + return string.format('\\%03o', c:byte()) +end +function M.pdf_string(text) + -- do note that \ddd is decimal in lua, octal in pdf + if text:match('[^%g\009\010\13 ]') then + return pdf_hex_string(text) + else + return string.format('(%s)', text + :gsub('[()\\]','\\%0') + :gsub('%c', octify)) + end +end + +-- try and produce a date of the format (D:YYYYMMDD) +function M.pdf_date(text) + local y, m, d = string.match(text, '^([12][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$') + if not y then d, m, y = string.match(text, '^([0-9][0-9]?)-([0-9][0-9]?)-([12][0-9][0-9][0-9])$') end + if y then + return string.format('(D:%4d%02d%02d)', y, m, d) + else + return string.format('(D:%s)', text) + end +end + +-- 1 scanning helpers + +local function make_scanner(fn) + return function(this, name, multiple) + this.scanners[name] = multiple and function() + this.res[name] = this.res[name] or { } + table.insert(this.res[name], fn()) + end or function() + this.scanners[name] = nil + this.res[name] = fn() + end + return this + end +end + +function M.options_scanner() + return { scanners = { }, res = { }, + int = make_scanner(token.scan_int), + glue = make_scanner(token.scan_glue), + dimen = make_scanner(token.scan_dimen), + string = make_scanner(token.scan_string), + argument = make_scanner(token.scan_argument), + word = make_scanner(token.scan_word), + list = make_scanner(token.scan_list), + keyword = function(this, name, opposite) + this.scanners[name] = function() + this.res[name] = true + if opposite then this.res[opposite] = false end + end + if opposite then + this.scanners[opposite] = function() + this.res[name] = false + this.res[opposite] = true + end + end + return this + end, + table = function(this, name) + this.scanners[name] = function() + this.res[name] = this.res[name] or { } + this.res[name][token.scan_string()] = token.scan_string() + end + return this + end, + subtable = function(this, name) + this.scanners[name] = function() + this.res[name] = this.res[name] or { } + local sub = token.scan_string(); + this.res[name][sub] = this.res[name][sub] or { } + this.res[name][sub][token.scan_string()] = token.scan_string() + end + return this + end, + scan = function(this, defaults) + this.res = defaults or this.res + repeat + local matched = false + for name, scanner in pairs(this.scanners) do + if token.scan_keyword(name) then + matched = true + scanner() + end + end + until not matched + return this.res + end + } +end + --1 saving modules and tables local tables = package.loaded['minim-saved-tables'] @@ -70,7 +195,7 @@ function M.table_to_text (tbl) return '{ ' .. table.concat (r,', ') .. ' }' end -require('minim-callbacks') +local cb = require('minim-callbacks') M.remember('minim-callbacks') M.remember('minim-alloc') @@ -79,11 +204,23 @@ M.remember('minim-alloc') -- like \unset M.unset = -0x7FFFFFFF -local allocations = M.saved_table ('minim:allocations') +-- works for both \chardef and the likes of \countdef +function M.registernumber(csname) + 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, +-- a different register will be reserved when the lua code is seen again in the +-- actual run. +local allocations = M.saved_table('minim lua-side allocations') -local function make_alloc_new (fname, globcount) +local function make_alloc_new(fname, globcount) allocations[fname] = allocations[fname] or { } - M['new_'..fname] = function (id) + M['new_'..fname] = function(id) local nr if id and allocations[fname][id] then nr = allocations[fname][id] @@ -108,7 +245,7 @@ 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 { } M['new_'..fname] = function (id) local nr @@ -122,21 +259,16 @@ local function make_alloc_old (fname, globcount, loccount) end return nr end - M['local_'..fname] = function () - local nr = tex.count[loccount] - 1 - tex.setcount(loccount, nr) - return nr - 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) @@ -144,8 +276,19 @@ function M.luadef (csname, fn, ...) token.set_lua(csname, nr, ...) end -M.luadef ('minim:rememberalloc', function() - allocations[token.scan_string()][token.scan_string()] = tex.count['allocationnumber'] +-- the current file +M.luadef('minim:currentfile', function() + tex.sprint((status.filename:gsub('^.*/', ''))) +end) + +-- make pdf_string() available as \pdfstring{...} +M.luadef('pdfstring', function() M.pdf_string(token.scan_string()) end) + +-- uselanguage hook callback +cb.new_callback('uselanguage', 'simple') +M.luadef('minim:uselanguagecallback', function() + local langname = token.scan_string() + cb.call_callback('uselanguage', langname) end) --1 dumping information to the format file @@ -188,7 +331,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/macros/luatex/generic/minim/minim-alloc.tex b/macros/luatex/generic/minim/minim-alloc.tex index 66f08c9045..8752c2e336 100644 --- a/macros/luatex/generic/minim/minim-alloc.tex +++ b/macros/luatex/generic/minim/minim-alloc.tex @@ -62,58 +62,48 @@ % 1 ltluatex compatibility +% \ProvidesFile identifies most problematic files +\ifdefined \ProvidesFile + \let\minim:providesfile=\ProvidesFile\else + \def\minim:providesfile#1#2[#3]{% + \wlog{Loading file #1 version #3.}}\fi +\def\ProvidesFile#1{\begincsname minim:intercept:#1\endcsname + \minim:providesfile{#1}} + + % repair ltluatex, which, without apparent reason, resets all allocation % counters, even if they already exist -\def\minim:ltltx:file{ltluatex.tex} -\let\ProvidesFile:saved=\ProvidesFile -\def\ProvidesFile#1#2[#3]{% - \ifdefined\ProvidesFile:saved \ProvidesFile:saved{#1}#2[#3]\fi - \def\minim:ltltx:arg{#1}% - \ifx\minim:ltltx:file\minim:ltltx:arg - \let\ProvidesFile=\ProvidesFile:saved - \let\endinput:saved=\endinput - \protected\edef\endinput{% - \minim:ltltx:fix{e@alloc@attribute@count}% - \minim:ltltx:fix{e@alloc@whatsit@count}% - \minim:ltltx:fix{e@alloc@bytecode@count}% - \minim:ltltx:fix{e@alloc@luafunction@count}% - \minim:ltltx:fix{e@alloc@luachunk@count}% - \minim:ltltx:fix{e@alloc@ccodetable@count}% - % also patch in remembering allocations to lua - \alloc:patch \noexpand\attribute - \alloc:patch \noexpand\whatsit - \alloc:patch \noexpand\luabytecode - \alloc:patch \noexpand\luachunkname - \alloc:patch \noexpand\catcodetable - \alloc:patch \noexpand\userrule - % restore register allocation functions - \directlua{ local C = require('minim-callbacks') - callback.register, callback.find, callback.list - = C.register, C.find, C.list }% - \let\noexpand\endinput=\noexpand\endinput:saved - \noexpand\endinput}\fi} +\expandafter\def\csname minim:intercept:ltluatex.tex\endcsname + {\wlog{minim: applying ltluatex patches.}% + \edef\endinput{\let\noexpand\endinput=\noexpand\minim:endinput + \minim:ltltx:fix{e@alloc@attribute@count}% + \minim:ltltx:fix{e@alloc@whatsit@count}% + \minim:ltltx:fix{e@alloc@bytecode@count}% + \minim:ltltx:fix{e@alloc@luafunction@count}% + \minim:ltltx:fix{e@alloc@luachunk@count}% + \minim:ltltx:fix{e@alloc@ccodetable@count}% + % restore register allocation functions + \noexpand\directlua{ callback.register = + require('minim-callbacks').primitiveregister }% + \noexpand\endinput}} +\let\minim:endinput = \endinput \def\minim:ltltx:fix#1{% \ifnum0<\the\csname#1\endcsname \wlog{Restoring \csname#1\endcsname to previous value \the\csname#1\endcsname}% \expandafter\noexpand\csname#1\endcsname =\the\csname#1\endcsname\relax\fi} -\protected\def\alloc:patch#1{% - \expandafter\expandafter\expandafter\let - \expandafter\expandafter\csname\csstring#1:ltluatex:new\endcsname - \csname new\csstring#1\endcsname - \expandafter\edef\csname new\csstring#1\endcsname##1{% - \noexpand\minim:rememberalloc{\csstring#1}{\noexpand\csstring##1}% - \expandafter\noexpand\csname\csstring#1:ltluatex:new\endcsname{##1}}} % 1 allocation % use global allocation (see etex.src) -\let\newcount = \globcount -\let\newdimen = \globdimen -\let\newskip = \globskip -\let\newmuskip = \globmuskip -\let\newbox = \globbox -\let\newtoks = \globtoks -\let\newmarks = \globmarks +\ifdefined \globcount + \let\newcount = \globcount + \let\newdimen = \globdimen + \let\newskip = \globskip + \let\newmuskip = \globmuskip + \let\newbox = \globbox + \let\newtoks = \globtoks + \let\newmarks = \globmarks +\fi % new allocation macros @@ -121,8 +111,7 @@ \unless\ifcsname#3\endcsname \expandafter\newcount \csname#3\endcsname \csname#3\endcsname 0\fi - \ifcsname new\csstring#1\endcsname - \alloc:patch#1\else + \unless\ifcsname new\csstring#1\endcsname \expandafter\edef\csname new\csstring#1\endcsname{% \noexpand\minim:alloc\noexpand#1\noexpand#2% \expandafter\noexpand\csname#3\endcsname}\fi} @@ -131,9 +120,7 @@ \global\advance#31% \allocationnumber#3% \global#2#4\allocationnumber - \wlog{\string#4=\string#1\the\allocationnumber}% - % minim:rememberalloc will be defined from lua side - \minim:rememberalloc{\csstring#1}{\csstring#4}} + \wlog{\string#4=\string#1\the\allocationnumber}} % all names and counters below are identical to those from ltluatex % note: we cannot use \newluafunction, or ltluatex will not load @@ -147,7 +134,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'}} @@ -156,17 +146,22 @@ \protected\def\setluachunkname#1#2{\newluachunkname#1% \directlua{lua.name[\the#1]='\luaescapestring{#2}'}} -% patch in remembering box allocations -\def\minim:boxchardef#1{% - \minim:rememberalloc{box}{\csstring#1}% - \mathchardef#1} -\edef\newbox{% - \expandafter\noexpand\csname et@xglob\endcsname - 4\box\noexpand\minim:boxchardef} - % undefine our helper functions \let\alloc:makenew=\undefined +% patch in our callback to \uselanguage +% \minim:uselanguagecallback is defined from Lua +\ifcsname uselanguage@hook\endcsname + \expandafter\let + \expandafter\minim:uselanguagehook + \lastnamedcs \fi +\expandafter\edef\csname uselanguage@hook\endcsname#1{% + % our uselanguage callback + \noexpand\minim:uselanguagecallback{#1}% + % previous definitions + \ifdefined\minim:uselanguagehook + \noexpand\minim:uselanguagehook{#1}\fi} + % 1 format file compatibility % all other work is done at the lua end diff --git a/macros/luatex/generic/minim/minim-callbacks.lua b/macros/luatex/generic/minim/minim-callbacks.lua index 3ac075dc01..af3db59e24 100644 --- a/macros/luatex/generic/minim/minim-callbacks.lua +++ b/macros/luatex/generic/minim/minim-callbacks.lua @@ -1,41 +1,51 @@ 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 --1 capturing the callback mechanism --- if ltluatex is loaded, we must get callback.register back -if luatexbase ~= nil then - local luatex_base = luatexbase - luatexbase.uninstall () - luatexbase = luatex_base -end - local primitives = { } M.primitives = primitives primitives.register = callback.register primitives.find = callback.find primitives.list = callback.list -local own_callbacks = {} -local callback_lists = {} +-- use the ltluatex functions if needed +local primitive_register = primitives.register +if luatexbase then + primitive_register = function(cb, f) + 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 + + +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 (name) +function M.list() local t = {} for n,f in pairs(callback_lists) do if f then @@ -44,14 +54,16 @@ function M.list (name) 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 +75,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 f == 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 +212,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] = callback.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 +263,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 +293,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 +303,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/macros/luatex/generic/minim/minim-doc.sty b/macros/luatex/generic/minim/minim-doc.sty index 1d3c2d4cea..93e770153b 100644 --- a/macros/luatex/generic/minim/minim-doc.sty +++ b/macros/luatex/generic/minim/minim-doc.sty @@ -6,6 +6,7 @@ \expandafter\endinput\fi \input minim +%\decompressedpdf \pdfalevel 3a \overfullrule = 0pt @@ -15,7 +16,6 @@ \pdfvariable horigin 0pt \pdfvariable vorigin 0pt \frenchspacing -\raggedbottom \uselanguage{ukenglish} \hyphenation { @@ -38,27 +38,27 @@ % 1 fonts \input luaotfload.sty -\font\tenrm {Latin Modern Roman:script=latn;protrusion=default} at 10pt -\font\tenbf {Latin Modern Roman/B:script=latn} at 10pt -\font\tenit {Latin Modern Roman/I:script=latn} at 10pt -\font\tentt {Latin Modern Mono:script=latn;+smcp} at 10pt -\font\title {Latin Modern Roman/B:script=latn} at 12pt -\font\Title {Latin Modern Roman/B:script=latn} at 16pt - -\font\tenmath {Latin Modern Math:mode=base;script=math;ssty=0} at 10pt -\font\tenmaths {Latin Modern Math:mode=base;script=math;ssty=1} at 7pt -\font\tenmathss {Latin Modern Math:mode=base;script=math;ssty=2} at 5pt -\textfont 0 = \tenmath -\scriptfont 0 = \tenmaths -\scriptscriptfont 0 = \tenmathss - -\font\altmath {Tex Gyre Pagella Math:mode=base;script=math;ssty=0} at 10pt -\font\altmaths {Tex Gyre Pagella Math:mode=base;script=math;ssty=1} at 7pt -\font\altmathss {Tex Gyre Pagella Math:mode=base;script=math;ssty=2} at 5pt +\font\tenrm {Latin Modern Roman:script=latn;protrusion=default;} at 10pt +\font\tenbf {Latin Modern Roman/B:script=latn;} at 10pt +\font\tenit {Latin Modern Roman/I:script=latn;} at 10pt +\font\tentt {Latin Modern Mono:script=latn;+smcp;} at 10pt +\font\title {Latin Modern Roman/B:script=latn;} at 12pt +\font\Title {Latin Modern Roman/B:script=latn;} at 16pt + +\font\altmath {Tex Gyre Pagella Math:mode=base;script=math;ssty=0;} at 10pt +\font\altmaths {Tex Gyre Pagella Math:mode=base;script=math;ssty=1;} at 7pt +\font\altmathss {Tex Gyre Pagella Math:mode=base;script=math;ssty=2;} at 5pt \textfont 1 = \altmath \scriptfont 1 = \altmaths \scriptscriptfont 1 = \altmathss +\font\tenmath {Latin Modern Math:mode=base;script=math;ssty=0;} at 10pt +\font\tenmaths {Latin Modern Math:mode=base;script=math;ssty=1;} at 7pt +\font\tenmathss {Latin Modern Math:mode=base;script=math;ssty=2;} at 5pt +\textfont 0 = \tenmath +\scriptfont 0 = \tenmaths +\scriptscriptfont 0 = \tenmathss + \expandglyphsinfont \tenrm 40 25 5 \protrudechars=2 \adjustspacing=2 \tenrm @@ -67,21 +67,31 @@ % 1 code typesetting -\def\red#1{\quitvmode\pdfextension - literal{0.75 0 0 rg}{#1}\pdfextension literal{0 g}} +\chardef\thecolourstack = \pdffeedback colorstackinit page {0 g 0 G} +\def\pushcolour#1{\pdfextension colorstack \thecolourstack push {#1}} +\def\popcolour{\pdfextension colorstack \thecolourstack pop\relax} +\def\red#1{\pushcolour{0.75 0 0 rg}{#1}\popcolour} \def\emph#1{{\tenit #1\/}} +\newattributeclass Code + attr Layout Placement /Block + attr CSS-2.00 display (block) + \def\breakablespace{\penalty0~} \catcode`\⟦=\active \def⟦{\quitvmode\begingroup\catcode`\∥=0\relax \markparagraphsfalse \def\do##1{\catcode`##1=12}\dospecials - \catcode`\ =\active - \letcharcode`\ =\breakablespace\obeylines - \parskip0pt\tentt + \catcode`\%=\active \letcharcode`\%=\verbatimcomment + \catcode`\ =\active \letcharcode`\ =\breakablespace + \def\par{\ifhmode\tentt\endgraf\else\vskip\baselineskip\fi}% + \everypar{\stopelement{Code}% + \startelement class Code {Code}}% + \parskip0pt\tentt \obeylines \nextif*{\verbatim\ignore}{\expandafter\ignore\verbatim}} \def\verbatim#1⟧{\red{\markelement{Code}{#1}}\endgroup} +\def\verbatimcomment{\tenit\Uchar`\%} % 1 the minim symbol @@ -109,7 +119,6 @@ endfig;} \setbox\notehead=\hbox{\markartifact{Layout}{\box\notehead}} \closemetapostinstance \mnmMP -% % 1 document structure % page artifacts @@ -134,9 +143,9 @@ endfig;} \ensurestopelement{Section}% \startelement{Chapter}% \outline open {#1}% - \nextpartag{H}\red{\Title#1\hfill\copy\notehead}% \addtotoc{\chapter{#1}{\lastdestinationname}}% - \bigskip} + \nextpartag{H}\quitvmode + \red{\Title#1\hfill\copy\notehead}\bigskip\nobreak} % \section Title \par \addstructuretype Sect Section @@ -144,8 +153,8 @@ endfig;} \bigskip\penalty-50\relax \startelement{Section}% \outline closed {#1}% - \nextpartag{H}\quitvmode \addtotoc{\section{#1}{\lastdestinationname}}% + \nextpartag{H}\quitvmode \red{\title#1}% \par\nobreak} @@ -200,7 +209,6 @@ obtained at {\hyperlink url {https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12}% https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\endlink}$$\startformulatagging} - % for identifying which file we are typesetting \edef\thejobname{\expandafter\scantextokens\expandafter{\jobname}} \newif \ifchapter diff --git a/macros/luatex/generic/minim/minim-hooks.lua b/macros/luatex/generic/minim/minim-hooks.lua index c399547c9e..f11ce27875 100644 --- a/macros/luatex/generic/minim/minim-hooks.lua +++ b/macros/luatex/generic/minim/minim-hooks.lua @@ -1,13 +1,11 @@ --- Adds a callback just before a box is shipped out, opposite to --- 'finish_pdfpage'. - -local alloc = require('minim-alloc') local cb = require ('minim-callbacks') -alloc.remember('minim-hooks') local M = { } +-- Add a callback just before a box is shipped out, opposite to +-- 'finish_pdfpage'. + cb.new_callback('pre_shipout', 'simple') M.primitive_shipout = tex.shipout @@ -16,15 +14,5 @@ function tex.shipout(nr) M.primitive_shipout(nr) end -local shipout_box = alloc.new_box('minim:shipout:box') - -alloc.luadef('minim:shipout', function() - tex.box[shipout_box] = token.scan_list() - cb.call_callback('pre_shipout', shipout_box) - -- we must let tex do the rest, because some other package may have - -- redefined \shipout before us. - tex.sprint(token.create('minim:shipout:do')) -end, 'protected') - return M diff --git a/macros/luatex/generic/minim/minim-hooks.tex b/macros/luatex/generic/minim/minim-hooks.tex index b3b8092654..deef66fc9a 100644 --- a/macros/luatex/generic/minim/minim-hooks.tex +++ b/macros/luatex/generic/minim/minim-hooks.tex @@ -21,13 +21,17 @@ \chardef\minimhooksloaded = \catcode`\: \catcode`\: = 11 -\input minim-alloc +\directlua{ require('minim-hooks') } % 1 the pre_shipout callback \newbox\minim:shipout:box \let\minim:shipout:orig = \shipout \def\minim:shipout:do{\minim:shipout:orig\box\minim:shipout:box} -\directlua{require('minim-hooks')} \let\shipout\minim:shipout +\protected\def\minim:shipout:new{\directlua{ + tex.box[\the\minim:shipout:box] = token.scan_list() + require('minim-callbacks').call_callback('pre_shipout', \the\minim:shipout:box) + token.put_next(token.create('minim:shipout:do'))}} +\let\shipout = \minim:shipout:new % 1 invisibly adding to \everypar diff --git a/macros/luatex/generic/minim/minim-lmodern.tex b/macros/luatex/generic/minim/minim-lmodern.tex index 61bc0054e9..e420dd2a1c 100644 --- a/macros/luatex/generic/minim/minim-lmodern.tex +++ b/macros/luatex/generic/minim/minim-lmodern.tex @@ -11,15 +11,15 @@ \def\preloadfont#1#2#3{\def#1{\initfontloader\font#1{#2}at#3#1}} \def\initfontloader{\input luaotfload.sty \let\initfontloader=\relax} -\preloadfont \tenrm {Latin Modern Roman:script=latn;+liga;+kern;+dlig}{10pt} -\preloadfont \tenit {Latin Modern Roman/I:script=latn;+liga;+kern;+dlig}{10pt} -\preloadfont \tenbf {Latin Modern Roman/B:script=latn;+liga;+kern;+dlig}{10pt} -\preloadfont \tensl {Latin Modern Roman Slanted:script=latn;+liga;+kern;+dlig}{10pt} -\preloadfont \tentt {Latin Modern Mono:script=latn;+liga;+kern;+dlig}{10pt} - -\preloadfont\tenmath {Latin Modern Math:mode=base;script=math;ssty=0}{10pt} -\preloadfont\tenmaths {Latin Modern Math:mode=base;script=math;ssty=1}{7pt} -\preloadfont\tenmathss {Latin Modern Math:mode=base;script=math;ssty=2}{5pt} +\preloadfont \tenrm {Latin Modern Roman:script=latn;+liga;+kern;+dlig;}{10pt} +\preloadfont \tenit {Latin Modern Roman/I:script=latn;+liga;+kern;+dlig;}{10pt} +\preloadfont \tenbf {Latin Modern Roman/B:script=latn;+liga;+kern;+dlig;}{10pt} +\preloadfont \tensl {Latin Modern Roman Slanted:script=latn;+liga;+kern;+dlig;}{10pt} +\preloadfont \tentt {Latin Modern Mono:script=latn;+liga;+kern;+dlig;}{10pt} + +\preloadfont\tenmath {Latin Modern Math:mode=base;script=math;ssty=0;}{10pt} +\preloadfont\tenmaths {Latin Modern Math:mode=base;script=math;ssty=1;}{7pt} +\preloadfont\tenmathss {Latin Modern Math:mode=base;script=math;ssty=2;}{5pt} \toksapp\everyjob{\tenmath\tenmaths\tenmathss\tenrm \textfont0=\tenmath\scriptfont0=\tenmaths\scriptscriptfont0=\tenmathss} diff --git a/macros/luatex/generic/minim/minim-pdfresources.lua b/macros/luatex/generic/minim/minim-pdfresources.lua new file mode 100644 index 0000000000..bc09aeaf40 --- /dev/null +++ b/macros/luatex/generic/minim/minim-pdfresources.lua @@ -0,0 +1,154 @@ + +local M = { } + +local alloc = require 'minim-alloc' +local cb = require 'minim-callbacks' + +-- the standard table design +local function init_resources() + return { + ExtGState = { }, + ColorSpace = { }, + Pattern = { }, + Shading = { }, + } +end + +-- the module will use optex’s functions if present +M.self_destruct = pdf.add_page_resource or false + +-- resource_data is a table that can contain any data. only the following keys +-- are used by this module: +-- +-- _entry_ internal value; do not use +-- value value in the resource dictionary +-- write() called for writing the resource to the pdf; returns value +-- +-- of the last two, only one needs be present; if the value is missing it will +-- be set at first use to the result of write(). +-- +local resource_data = init_resources() -- name ↦ { [write = ... | value = ...], ... } +-- +function M.add_resource(kind, name, resource) + resource_data[kind][name] = resource +end +function M.get_resource(kind, name) + return resource_data[kind][name] +end +function M.use_resource(kind, name) + local res = resource_data[kind][name] + if not res then + return alloc.err('Unknown %s resource: %s', kind, name) + end + res.value = res.value or res:write() + if not res._entry_ then -- first-use + res._entry_ = string.format('%s %s', alloc.pdf_name(name), res.value) + if M.self_destruct then + M.self_destruct(kind, name, res.value) + end + end + return res._entry_ +end + +-- global resources are mainly for pgf compatibility: contains adds entries to +-- the resource dictionaries that will be added for every page. +-- +local global_resources = init_resources() -- name ↦ '/Key <value>' +-- +function M.add_global_resource(kind, name, value) + local r = global_resources[kind] + if M.self_destruct then + M.self_destruct(kind, name, value) + elseif name == nil then -- used for pgf compatibility + if value ~= '' then + r[''] = r[''] and string.format('%s %s', global_resources[kind][''], value) or value + end + else + r[name] = string.format('%s %s', alloc.pdf_name(name), value) + end +end + +-- we can now provide optex’s interface +if not M.self_destruct then + pdf.add_page_resource = M.add_global_resource +end + +-- for nonglobal resources, every use must be markes with a late_lua node. from +-- those, the M.use_resouce() function will be called automatically. +-- +local page_resources = init_resources() -- name ↦ '/Key <value>' +-- +function _with_pdf_resource_(kind, name) -- global, for use in latelua + page_resources[kind][name] = M.use_resource(kind, name) +end +function M.use_resource_node(kind, name) + local n = node.new('whatsit', 'late_lua') + n.data = string.format('_with_pdf_resource_("%s", "%s")', kind, name) + return n +end + +-- construction and caching of resource dictionaries. +-- +local previous_dicts = init_resources() -- pdf dict ↦ objnum +-- +local function make_resource_entry(kind) + local arr = { } + for _, entry in pairs(page_resources[kind]) do table.insert(arr, entry) end + for _, entry in pairs(global_resources[kind]) do table.insert(arr, entry) end + if #arr == 0 then return false end + table.sort(arr) + arr[0] = '<<'; table.insert(arr, '>>') + local dict = table.concat(arr, ' ', 0) + local objnum = previous_dicts[kind][dict] + if not objnum then + objnum = pdf.obj(dict) + pdf.refobj(objnum) + previous_dicts[kind][dict] = objnum + end + return string.format('/%s %d 0 R', kind, objnum) +end + +local removal_regex = { + ExtGState = ' */ExtGState *%d+ +0 *R', + ColorSpace = ' */ColorSpace *%d+ +0 *R', + Pattern = ' */Pattern *%d+ +0 *R', + Shading = ' */Shading *%d+ +0 *R' } + +local function update_page_resources(shippingout) + if M.self_destruct then return end + local resources = shippingout and pdf.getpageresources() or pdf.getxformresources() or '' + for kind, used in pairs(page_resources) do + resources = string.gsub(resources, removal_regex[kind], '') + local entry = make_resource_entry(kind) + if entry then + resources = resources == '' and entry or string.format('%s %s', resources, entry) + end + end + -- update page resources + if shippingout then + pdf.setpageresources(resources) + else + pdf.setxformresources(resources) + end + page_resources = init_resources() +end + +cb.register('finish_pdfpage', update_page_resources) + +-- for pgf compatibility, reroute the pgf resource registration functions to +-- our global resource pool. +-- +alloc.luadef('minim:pgf:fix:luaside', function() + alloc.luadef('pgf@sys@addpdfresource@extgs@plain', function() + M.add_global_resource('ExtGState', nil, token.scan_string()) + end) + alloc.luadef('pgf@sys@addpdfresource@patterns@plain', function() + M.add_global_resource('Pattern', nil, token.scan_string()) + end) + alloc.luadef('pgf@sys@addpdfresource@colorspaces@plain', function() + M.add_global_resource('ColorSpace', nil, token.scan_string()) + end) +end) + +return M + diff --git a/macros/luatex/generic/minim/minim-pdfresources.tex b/macros/luatex/generic/minim/minim-pdfresources.tex new file mode 100644 index 0000000000..6b8dc29577 --- /dev/null +++ b/macros/luatex/generic/minim/minim-pdfresources.tex @@ -0,0 +1,51 @@ + +\ifdefined \minimpdfresourcesloaded + \message{(skipped)} + \expandafter\endinput\fi +\chardef\minimpdfresourcesloaded=\catcode`\: +\catcode`\:=11 + +% at the moment, this file only deals with pgf compatibility. if you do not use +% pgf, you only need the lua module. + +\directlua{ require 'minim-pdfresources' } + +% 1 pgf compatibility + +% this ballet inserts our fix directly at the end of pgfsys-luatex.def +\expandafter\def\csname minim:intercept:pgfsys-luatex.def\endcsname + {\wlog{minim: applying pgf patches...}\newtoks\minim:pgf:fix:toks + \minim:pgf:fix:toks\csname pgfutil@everybye\endcsname + \let\endinput=\minim:pgf:fix:endinput} +\def\minim:pgf:fix:endinput{% + \begincsname minim:pgf:fix:\minim:currentfile\endcsname + \minim:endinput} +\expandafter\def\csname minim:pgf:fix:pgfsys-luatex.def\endcsname{% + \csname pgfutil@everybye\endcsname\minim:pgf:fix:toks \minim:pgf:fix:common + \let\endinput=\minim:endinput \wlog{minim: done applying pgf patches}} + +\def\minim:pgf:fix:common{\directlua{% + local pdfres = require 'minim-pdfresources' + pdfres.add_global_resource('ExtGState', nil, + '\luaescapestring{\csname pgf@sys@pgf@resource@list@extgs\endcsname}') + pdfres.add_global_resource('Pattern', nil, + '\luaescapestring{\csname pgf@sys@pgf@resource@list@patterns\endcsname}') + pdfres.add_global_resource('ColorSpace', nil, + '\luaescapestring{\csname pgf@sys@pgf@resource@list@colorspaces\endcsname}')} + \expandafter\let\csname pgf@sys@pdf@possible@resources\endcsname = \empty + \minim:pgf:fix:luaside \pdfvariable pageresources{}} + +% if pgf has already been loaded, copy the already-defined resources +\ifcsname pgf@sys@pdf@extgs@objnum\endcsname \minim:pgf:fix:common + % three empty registers will be written at the end. having three unused + % empty objects in the pdf is not ideal, but will not lead to problems. + \expandafter\let\csname pgf@sys@pgf@resource@list@extgs\endcsname = \empty + \expandafter\let\csname pgf@sys@pgf@resource@list@patterns\endcsname = \empty + \expandafter\let\csname pgf@sys@pgf@resource@list@colorspaces\endcsname = \empty +\fi + +% + +\catcode`\:=\minimpdfresourcesloaded +\endinput + diff --git a/macros/luatex/generic/minim/minim-plain.tex b/macros/luatex/generic/minim/minim-plain.tex index 85fd802b8b..1fc0178ed8 100644 --- a/macros/luatex/generic/minim/minim-plain.tex +++ b/macros/luatex/generic/minim/minim-plain.tex @@ -490,8 +490,6 @@ \def\leavevmode{\unhbox\voidb@x} % begins a paragraph, if necessary \def\_{\leavevmode \kern.06em \vbox{\hrule width.3em}} -\def\AA{\leavevmode\setbox0\hbox{!}\dimen@\ht0\advance\dimen@-1ex% - \rlap{\raise.67\dimen@\hbox{\char'27}}A} \def\mathhexbox#1#2#3{\leavevmode \hbox{$\m@th \mathchar"#1#2#3$}} @@ -512,18 +510,6 @@ \def\dots{\relax\ifmmode\ldots\else$\m@th\ldots\,$\fi} \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX} -\def\`#1{{\accent18 #1}} -\def\'#1{{\accent19 #1}} -\def\v#1{{\accent20 #1}} \let\^^_=\v -\def\u#1{{\accent21 #1}} \let\^^S=\u -\def\=#1{{\accent22 #1}} -\def\^#1{{\accent94 #1}} \let\^^D=\^ -\def\.#1{{\accent95 #1}} -\def\H#1{{\accent"7D #1}} -\def\~#1{{\accent"7E #1}} -\def\"#1{{\accent"7F #1}} -\def\t#1{{\edef\next{\the\font}\the\textfont1\accent"7F\next#1}} - \def\hrulefill{\leaders\hrule\hfill} \def\dotfill{\cleaders\hbox{$\m@th \mkern1.5mu.\mkern1.5mu$}\hfill} \def\rightarrowfill{$\m@th\smash-\mkern-7mu% diff --git a/macros/luatex/generic/minim/minim.doc b/macros/luatex/generic/minim/minim.doc index d16250a0fe..a0ad8f2d4a 100644 --- a/macros/luatex/generic/minim/minim.doc +++ b/macros/luatex/generic/minim/minim.doc @@ -4,8 +4,8 @@ \startmetadata author {Esger Renkema} title {minim} - date {2021-06-01} - version {2021/1.0} + date {2022-03-03} + version {2022/1.1} keywords {LuaTeX; Plain TeX; MetaPost; PDF/A; Tagged PDF; accessibility; a11y; Unicode mathematics; XMP; metadata; hypertext; bookmarks} stopmetadata @@ -62,12 +62,7 @@ Please get in touch if you find this not the case. Particular care has been taken to be compatible with \red{ltluatex}. All overlapping functions should produce the same results and ltluatex can be loaded either before or after minim. - -One point of incompatibility exists between \red{tikz/pgf} and the pattern -functionality of minim-mp, due to conflicting implementations of pdf resource -management. -If you do not use filling patterns, however, the two packages can be used -together. +Earlier incompatibilities with \red{pgf} have been resolved. \licencesection diff --git a/macros/luatex/generic/minim/minim.pdf b/macros/luatex/generic/minim/minim.pdf Binary files differindex 715525bcf9..1596eb65d4 100644 --- a/macros/luatex/generic/minim/minim.pdf +++ b/macros/luatex/generic/minim/minim.pdf |