From 9d2ad7dea5c20379f6679c57c3b16752b1af445a Mon Sep 17 00:00:00 2001
From: Hans Hagen <pragma@wxs.nl>
Date: Tue, 19 Oct 2021 00:16:55 +0200
Subject: 2021-10-18 23:13:00

---
 tex/context/base/mkii/cont-new.mkii                |   2 +-
 tex/context/base/mkii/context.mkii                 |   2 +-
 tex/context/base/mkii/mult-en.mkii                 |  23 ++
 tex/context/base/mkii/mult-fr.mkii                 |   1 +
 tex/context/base/mkiv/cont-new.mkiv                |   2 +-
 tex/context/base/mkiv/context.mkiv                 |   6 +-
 tex/context/base/mkiv/grph-epd.lua                 |  55 ---
 tex/context/base/mkiv/status-files.pdf             | Bin 24822 -> 24825 bytes
 tex/context/base/mkiv/status-lua.pdf               | Bin 253826 -> 253873 bytes
 tex/context/base/mkxl/attr-col.lmt                 |  48 ++-
 tex/context/base/mkxl/back-ext.mkxl                |  93 -----
 tex/context/base/mkxl/back-imp-lua.lmt             | 378 +++++++++++++++++++++
 tex/context/base/mkxl/back-imp-lua.mkxl            |  16 +
 tex/context/base/mkxl/back-imp-mps.lmt             | 215 ++++++++++++
 tex/context/base/mkxl/back-imp-mps.mkxl            |  16 +
 tex/context/base/mkxl/back-imp-pdf.lmt             |  49 +++
 tex/context/base/mkxl/back-imp-pdf.mkxl            | 160 +++++++++
 tex/context/base/mkxl/back-imp-pdp.lmt             | 289 ++++++++++++++++
 tex/context/base/mkxl/back-imp-u3d.mkxl            | 160 +++++++++
 tex/context/base/mkxl/back-ini.lmt                 |  42 ++-
 tex/context/base/mkxl/back-lua.lmt                 | 372 --------------------
 tex/context/base/mkxl/back-lua.mkxl                |  16 -
 tex/context/base/mkxl/back-mps.lmt                 | 212 ------------
 tex/context/base/mkxl/back-mps.mkxl                |  16 -
 tex/context/base/mkxl/back-pdf.lmt                 |  50 ---
 tex/context/base/mkxl/back-pdf.mkxl                | 161 ---------
 tex/context/base/mkxl/back-pdp.lmt                 | 289 ----------------
 tex/context/base/mkxl/back-res.lmt                 | 142 +++++---
 tex/context/base/mkxl/back-res.mkxl                |   6 +-
 tex/context/base/mkxl/back-u3d.mkxl                | 158 ---------
 tex/context/base/mkxl/cont-new.mkxl                |   2 +-
 tex/context/base/mkxl/context.mkxl                 |  14 +-
 tex/context/base/mkxl/core-def.mkxl                |   1 +
 tex/context/base/mkxl/driv-ini.lmt                 | 134 ++------
 tex/context/base/mkxl/font-tex.lmt                 |   4 +-
 tex/context/base/mkxl/font-vfc.lmt                 |  18 +-
 tex/context/base/mkxl/grph-epd.lmt                 |  55 +++
 tex/context/base/mkxl/grph-epd.lua                 |  55 +++
 tex/context/base/mkxl/grph-epd.mkxl                |   2 +-
 tex/context/base/mkxl/grph-inc.lmt                 |  20 +-
 tex/context/base/mkxl/grph-rul.lmt                 |  19 +-
 tex/context/base/mkxl/lpdf-ano.lmt                 |  10 +-
 tex/context/base/mkxl/lpdf-col.lmt                 |  91 +++--
 tex/context/base/mkxl/lpdf-emb.lmt                 |   4 +-
 tex/context/base/mkxl/lpdf-epa.lmt                 |  13 +-
 tex/context/base/mkxl/lpdf-fld.lmt                 |   6 +-
 tex/context/base/mkxl/lpdf-fmt.lmt                 |   7 +-
 tex/context/base/mkxl/lpdf-grp.lmt                 |  14 +-
 tex/context/base/mkxl/lpdf-img.lmt                 |  10 +-
 tex/context/base/mkxl/lpdf-ini.lmt                 |  71 ++--
 tex/context/base/mkxl/lpdf-lmt.lmt                 | 191 +++--------
 tex/context/base/mkxl/lpdf-mis.lmt                 |  11 +-
 tex/context/base/mkxl/lpdf-ren.lmt                 |  11 +-
 tex/context/base/mkxl/lpdf-res.lmt                 |  41 ---
 tex/context/base/mkxl/lpdf-rul.lmt                 |  18 +-
 tex/context/base/mkxl/lpdf-tag.lmt                 |  11 +-
 tex/context/base/mkxl/lpdf-u3d.lmt                 |   5 +-
 tex/context/base/mkxl/lpdf-wid.lmt                 |  12 +-
 tex/context/base/mkxl/lpdf-xmp.lmt                 |   7 +-
 tex/context/base/mkxl/mlib-lmt.lmt                 |   2 +-
 tex/context/base/mkxl/mlib-scn.lmt                 |   6 +-
 tex/context/base/mkxl/mlib-svg.lmt                 |  24 +-
 tex/context/base/mkxl/node-ext.lmt                 |   2 +-
 tex/context/base/mkxl/node-ext.mkxl                |  93 +++++
 tex/context/base/mkxl/node-ini.mkxl                |   2 -
 tex/context/base/mkxl/node-pro.lmt                 |   1 +
 tex/context/base/mkxl/node-ref.lmt                 |  28 +-
 tex/context/base/mkxl/node-syn.mkxl                |  20 ++
 tex/context/base/mkxl/scrn-ref.mklx                |   4 +-
 tex/context/base/mkxl/strc-lst.mklx                |   2 +-
 tex/context/interface/mkii/keys-en.xml             |  23 ++
 tex/context/interface/mkii/keys-fr.xml             |   1 +
 tex/context/modules/mkxl/m-openstreetmap.lmt       |   3 +-
 tex/context/modules/mkxl/m-openstreetmap.mkxl      |  50 +--
 tex/generic/context/luatex/luatex-fonts-merged.lua |   2 +-
 75 files changed, 2094 insertions(+), 2005 deletions(-)
 delete mode 100644 tex/context/base/mkiv/grph-epd.lua
 delete mode 100644 tex/context/base/mkxl/back-ext.mkxl
 create mode 100644 tex/context/base/mkxl/back-imp-lua.lmt
 create mode 100644 tex/context/base/mkxl/back-imp-lua.mkxl
 create mode 100644 tex/context/base/mkxl/back-imp-mps.lmt
 create mode 100644 tex/context/base/mkxl/back-imp-mps.mkxl
 create mode 100644 tex/context/base/mkxl/back-imp-pdf.lmt
 create mode 100644 tex/context/base/mkxl/back-imp-pdf.mkxl
 create mode 100644 tex/context/base/mkxl/back-imp-pdp.lmt
 create mode 100644 tex/context/base/mkxl/back-imp-u3d.mkxl
 delete mode 100644 tex/context/base/mkxl/back-lua.lmt
 delete mode 100644 tex/context/base/mkxl/back-lua.mkxl
 delete mode 100644 tex/context/base/mkxl/back-mps.lmt
 delete mode 100644 tex/context/base/mkxl/back-mps.mkxl
 delete mode 100644 tex/context/base/mkxl/back-pdf.lmt
 delete mode 100644 tex/context/base/mkxl/back-pdf.mkxl
 delete mode 100644 tex/context/base/mkxl/back-pdp.lmt
 delete mode 100644 tex/context/base/mkxl/back-u3d.mkxl
 create mode 100644 tex/context/base/mkxl/grph-epd.lmt
 create mode 100644 tex/context/base/mkxl/grph-epd.lua
 delete mode 100644 tex/context/base/mkxl/lpdf-res.lmt
 create mode 100644 tex/context/base/mkxl/node-ext.mkxl
 create mode 100644 tex/context/base/mkxl/node-syn.mkxl

(limited to 'tex')

diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index a550984d2..8c09daa83 100644
--- a/tex/context/base/mkii/cont-new.mkii
+++ b/tex/context/base/mkii/cont-new.mkii
@@ -11,7 +11,7 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
-\newcontextversion{2021.10.15 13:57}
+\newcontextversion{2021.10.18 23:11}
 
 %D This file is loaded at runtime, thereby providing an
 %D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii
index 6eaebb20d..1d1d61d0b 100644
--- a/tex/context/base/mkii/context.mkii
+++ b/tex/context/base/mkii/context.mkii
@@ -20,7 +20,7 @@
 %D your styles an modules.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2021.10.15 13:57}
+\edef\contextversion{2021.10.18 23:11}
 
 %D For those who want to use this:
 
diff --git a/tex/context/base/mkii/mult-en.mkii b/tex/context/base/mkii/mult-en.mkii
index 5af7737d1..f990c83e5 100644
--- a/tex/context/base/mkii/mult-en.mkii
+++ b/tex/context/base/mkii/mult-en.mkii
@@ -79,6 +79,7 @@
 \setinterfacevariable{anchor}{anchor}
 \setinterfacevariable{and}{and}
 \setinterfacevariable{answerarea}{answerarea}
+\setinterfacevariable{append}{append}
 \setinterfacevariable{appendices}{appendices}
 \setinterfacevariable{appendix}{appendix}
 \setinterfacevariable{april}{april}
@@ -150,6 +151,7 @@
 \setinterfacevariable{commands}{commands}
 \setinterfacevariable{comment}{comment}
 \setinterfacevariable{component}{component}
+\setinterfacevariable{compress}{compress}
 \setinterfacevariable{compressseparator}{compressseparator}
 \setinterfacevariable{compressstopper}{compressstopper}
 \setinterfacevariable{concept}{concept}
@@ -186,6 +188,7 @@
 \setinterfacevariable{enumeration}{enumeration}
 \setinterfacevariable{environment}{environment}
 \setinterfacevariable{even}{even}
+\setinterfacevariable{explicit}{explicit}
 \setinterfacevariable{export}{export}
 \setinterfacevariable{external}{external}
 \setinterfacevariable{extremestretch}{extremestretch}
@@ -436,6 +439,7 @@
 \setinterfacevariable{postscript}{postscript}
 \setinterfacevariable{precedingpage}{precedingpage}
 \setinterfacevariable{preference}{preference}
+\setinterfacevariable{prepend}{prepend}
 \setinterfacevariable{preview}{preview}
 \setinterfacevariable{previous}{previous}
 \setinterfacevariable{previousevenpage}{previousevenpage}
@@ -1367,6 +1371,7 @@
 \setinterfaceelement{load}{load}
 \setinterfaceelement{local}{local}
 \setinterfaceelement{makeup}{makeup}
+\setinterfaceelement{namednotation}{namednotation}
 \setinterfaceelement{namedtyping}{namedtyping}
 \setinterfaceelement{next}{next}
 \setinterfaceelement{place}{place}
@@ -1536,6 +1541,7 @@
 \setinterfacecommand{definereferencelist}{definereferencelist}
 \setinterfacecommand{defineregister}{defineregister}
 \setinterfacecommand{definerule}{definerule}
+\setinterfacecommand{definesavebuffer}{startsavebuffer}
 \setinterfacecommand{definesection}{definesection}
 \setinterfacecommand{definesectionblock}{definesectionblock}
 \setinterfacecommand{definesorting}{definesorting}
@@ -1712,6 +1718,9 @@
 \setinterfacecommand{moveformula}{moveformula}
 \setinterfacecommand{moveongrid}{moveongrid}
 \setinterfacecommand{movesidefloat}{movesidefloat}
+\setinterfacecommand{namedconstruction}{namedconstruction}
+\setinterfacecommand{nameddescription}{nameddescription}
+\setinterfacecommand{namedenumeration}{namedenumeration}
 \setinterfacecommand{navigating}{navigating}
 \setinterfacecommand{nodimension}{nodimension}
 \setinterfacecommand{noheaderandfooterlines}{noheaderandfooterlines}
@@ -2083,6 +2092,13 @@
 \setinterfacecommand{startmakeup}{startmakeup}
 \setinterfacecommand{startmarginblock}{startmarginblock}
 \setinterfacecommand{startmarginrule}{startmarginrule}
+\setinterfacecommand{startnamedconstruction}{startnamedconstruction}
+\setinterfacecommand{startnameddescription}{startnameddescription}
+\setinterfacecommand{startnamedenumeration}{startnamedenumeration}
+\setinterfacecommand{startnamedmatrix}{startnamedmatrix}
+\setinterfacecommand{startnamedsection}{startnamedsection}
+\setinterfacecommand{startnamedsubformulas}{startnamedsubformulas}
+\setinterfacecommand{startnamedtyping}{startnamedtyping}
 \setinterfacecommand{startnarrower}{startnarrower}
 \setinterfacecommand{startopposite}{startopposite}
 \setinterfacecommand{startoverlay}{startoverlay}
@@ -2126,6 +2142,13 @@
 \setinterfacecommand{stopmakeup}{stopmakeup}
 \setinterfacecommand{stopmarginblock}{stopmarginblock}
 \setinterfacecommand{stopmarginrule}{stopmarginrule}
+\setinterfacecommand{stopnamedconstruction}{stopnamedconstruction}
+\setinterfacecommand{stopnameddescription}{stopnameddescription}
+\setinterfacecommand{stopnamedenumeration}{stopnamedenumeration}
+\setinterfacecommand{stopnamedmatrix}{stopnamedmatrix}
+\setinterfacecommand{stopnamedsection}{stopnamedsection}
+\setinterfacecommand{stopnamedsubformulas}{stopnamedsubformulas}
+\setinterfacecommand{stopnamedtyping}{stopnamedtyping}
 \setinterfacecommand{stopnarrower}{stopnarrower}
 \setinterfacecommand{stopopposite}{stopopposite}
 \setinterfacecommand{stopoverlay}{stopoverlay}
diff --git a/tex/context/base/mkii/mult-fr.mkii b/tex/context/base/mkii/mult-fr.mkii
index 369931ac8..6abaaec24 100644
--- a/tex/context/base/mkii/mult-fr.mkii
+++ b/tex/context/base/mkii/mult-fr.mkii
@@ -188,6 +188,7 @@
 \setinterfacevariable{enumeration}{énumération}
 \setinterfacevariable{environment}{environnement}
 \setinterfacevariable{even}{paire}
+\setinterfacevariable{explicit}{explicit}
 \setinterfacevariable{export}{exporter}
 \setinterfacevariable{external}{externe}
 \setinterfacevariable{extremestretch}{etirementextreme}
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index c97e9b74b..4fd44d874 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -13,7 +13,7 @@
 
 % \normalend % uncomment this to get the real base runtime
 
-\newcontextversion{2021.10.15 13:57}
+\newcontextversion{2021.10.18 23:11}
 
 %D This file is loaded at runtime, thereby providing an excellent place for hacks,
 %D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 24aa443d2..80678ac75 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -11,6 +11,10 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
+%D There is some residual code in \MKIV\ that results from the transition to \LMTX\
+%D but removeing it can have side effects due to oversights. There is no impact on
+%D performance to I leave at that.
+
 % Here is some timing (2015-04-01) luajittex format generation:
 %
 % 2.6 sec : normal make
@@ -45,7 +49,7 @@
 %D {YYYY.MM.DD HH:MM} format.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2021.10.15 13:57}
+\edef\contextversion{2021.10.18 23:11}
 
 %D Kind of special:
 
diff --git a/tex/context/base/mkiv/grph-epd.lua b/tex/context/base/mkiv/grph-epd.lua
deleted file mode 100644
index 0993270f1..000000000
--- a/tex/context/base/mkiv/grph-epd.lua
+++ /dev/null
@@ -1,55 +0,0 @@
-if not modules then modules = { } end modules ['grph-epd'] = {
-    version   = 1.001,
-    comment   = "companion to grph-epd.mkiv",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-local variables = interfaces.variables
-local settings_to_hash = utilities.parsers.settings_to_hash
-local codeinjections = backends.pdf.codeinjections
-
-local trace  = false  trackers.register("figures.merging", function(v) trace = v end)
-
-local report = logs.reporter("backend","merging")
-
-local function mergegoodies(optionlist)
-    local options = settings_to_hash(optionlist)
-    local yes     = options[variables.yes]
-    local all     = options[variables.all]
-    if next(options) then
-        report("% t",table.sortedkeys(options))
-    end
-    if all or yes or options[variables.reference] then
-        codeinjections.mergereferences()
-    end
-    if all or options[variables.comment] then
-        codeinjections.mergecomments()
-    end
-    if all or yes or options[variables.bookmark] then
-        codeinjections.mergebookmarks()
-    end
-    if all or options[variables.field] then
-        codeinjections.mergefields()
-    end
-    if all or options[variables.layer] then
-        codeinjections.mergeviewerlayers()
-    end
-    codeinjections.flushmergelayer()
-end
-
-function figures.mergegoodies(optionlist)
-    -- todo: we can use runlocal instead
-    context.stepwise(function()
-        -- we use stepwise because we might need to define symbols
-        -- for stamps that have no default appearance
-        mergegoodies(optionlist)
-    end)
-end
-
-interfaces.implement {
-    name      = "figure_mergegoodies",
-    actions   = figures.mergegoodies,
-    arguments = "string"
-}
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 6bcf6b371..1fc58def7 100644
Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index aaba8ae4f..7fb96ed2c 100644
Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ
diff --git a/tex/context/base/mkxl/attr-col.lmt b/tex/context/base/mkxl/attr-col.lmt
index 9c542a942..bda57595c 100644
--- a/tex/context/base/mkxl/attr-col.lmt
+++ b/tex/context/base/mkxl/attr-col.lmt
@@ -48,7 +48,6 @@ local report_transparencies = logs.reporter("transparencies","support")
 
 local states          = attributes.states
 local nodeinjections  = backends.nodeinjections
-local registrations   = backends.registrations
 local unsetvalue      = attributes.unsetvalue
 
 local enableaction    = nodes.tasks.enableaction
@@ -348,10 +347,18 @@ function colors.spot(parent,f,d,p)
     return { 5, .5, .5, .5, .5, 0, 0, 0, .5, parent, f, d, p }
 end
 
-local function graycolor(...) graycolor = nodeinjections.graycolor return graycolor(...) end
-local function rgbcolor (...) rgbcolor  = nodeinjections.rgbcolor  return rgbcolor (...) end
-local function cmykcolor(...) cmykcolor = nodeinjections.cmykcolor return cmykcolor(...) end
-local function spotcolor(...) spotcolor = nodeinjections.spotcolor return spotcolor(...) end
+local graycolor = nodeinjections.graycolor
+local rgbcolor  = nodeinjections.rgbcolor
+local cmykcolor = nodeinjections.cmykcolor
+local spotcolor = nodeinjections.spotcolor
+
+updaters.register("backends.injections.latebindings",function()
+    local nodeinjections = backends.nodeinjections
+    graycolor = nodeinjections.graycolor
+    rgbcolor  = nodeinjections.rgbcolor
+    cmykcolor = nodeinjections.cmykcolor
+    spotcolor = nodeinjections.spotcolor
+end)
 
 local function extender(colors,key)
     if colors.supported and key == "none" then
@@ -513,15 +520,14 @@ local f_transparency      = formatters["%s:%s"]
 registerstorage("attributes/transparencies/registered", registered, "attributes.transparencies.registered")
 registerstorage("attributes/transparencies/values",     values,     "attributes.transparencies.values")
 
-local function inject_transparency(...)
-    inject_transparency = nodeinjections.transparency
-    return inject_transparency(...)
-end
+local register_transparency = nodeinjections.registertransparency
+local inject_transparency   = nodeinjections.injecttransparency
 
-local function register_transparency(...)
-    register_transparency = registrations.transparency
-    return register_transparency(...)
-end
+updaters.register("backends.injections.latebindings",function()
+    local nodeinjections = backends.nodeinjections
+    register_transparency = nodeinjections.registertransparency
+    inject_transparency   = nodeinjections.injecttransparency
+end)
 
 function transparencies.register(name,a,t,force) -- name is irrelevant here (can even be nil)
     -- Force needed here for metapost converter. We could always force
@@ -614,7 +620,17 @@ colorintents.registered = allocate {
     knockout  = 2,
 }
 
-local data, registered = colorintents.data, colorintents.registered
+local inject_overprint = nodeinjections.injectoverprint
+local inject_knockout  = nodeinjections.injectknockout
+
+updaters.register("backends.injections.latebindings",function()
+    local nodeinjections = backends.nodeinjections
+    inject_overprint = nodeinjections.injectoverprint
+    inject_knockout  = nodeinjections.injectknockout
+end)
+
+local data       = colorintents.data
+local registered = colorintents.registered
 
 local function extender(colorintents,key)
     if key == "none" then
@@ -626,11 +642,11 @@ end
 
 local function reviver(data,n)
     if n == 1 then
-        local d = nodeinjections.overprint() -- called once
+        local d = inject_overprint() -- called once
         data[1] = d
         return d
     elseif n == 2 then
-        local d = nodeinjections.knockout() -- called once
+        local d = inject_knockout() -- called once
         data[2] = d
         return d
     end
diff --git a/tex/context/base/mkxl/back-ext.mkxl b/tex/context/base/mkxl/back-ext.mkxl
deleted file mode 100644
index 4fae3d54e..000000000
--- a/tex/context/base/mkxl/back-ext.mkxl
+++ /dev/null
@@ -1,93 +0,0 @@
-%D \module
-%D   [       file=back-ext,
-%D        version=2019.02.08, % and later, merged file
-%D          title=\CONTEXT\ Backend Macros,
-%D       subtitle=Output,
-%D         author=Hans Hagen,
-%D           date=\currentdate,
-%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-% \registerctxluafile{back-ext}{autosuffix}
-
-\unprotect
-
-% \let\normalopenout \openout
-% \let\normalwrite   \write
-% \let\normalcloseout\closeout
-% \let\normallatelua \latelua
-% \let\normalspecial \special
-
-% rotation
-
-% \permanent\protected\def\dostartrotation#1{\forcecolorhack\clf_startrotation#1\relax}
-% \permanent\protected\def\dostoprotation   {\clf_stoprotation\forcecolorhack}
-
-\permanent\protected\def\dostartrotation#1{\clf_startrotation#1\relax}
-\permanent\protected\def\dostoprotation   {\clf_stoprotation}
-
-% scaling
-
-% \permanent\protected\def\dostartscaling#1#2{\forcecolorhack\clf_startscaling rx #1 ry #2\relax}
-% \permanent\protected\def\dostopscaling     {\clf_stopscaling\forcecolorhack}
-
-\permanent\protected\def\dostartscaling#1#2{\clf_startscaling rx #1 ry #2\relax}
-\permanent\protected\def\dostopscaling     {\clf_stopscaling}
-
-% mirroring
-
-\permanent\protected\def\dostartmirroring{\clf_startmirroring}
-\permanent\protected\def\dostopmirroring {\clf_stopmirroring}
-
-% transform
-
-\permanent\protected\def\dotransformnextbox#1#2#3#4#5#6%
-  {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}}
-
-\permanent\protected\def\dodotransformnextbox#1#2#3#4#5#6%
-  {\hpack
-     {\kern #5\onebasepoint
-      \raise#6\onebasepoint
-      \hpack
-        {\clf_startmatrix rx #1 sx #2 sy #3 ry #4\relax
-         \box\nextbox
-         \clf_stopmatrix}}}
-
-%D \macros
-%D   {dostartclipping,dostopclipping}
-%D
-%D Clipping is implemented in such a way that an arbitrary code can be fed.
-%D
-%D \starttyping
-%D \dostartclipping {pathname} {width} {height}
-%D \dostopclipping
-%D \stoptyping
-
-\mutable\let\MPclippath\empty
-
-% \permanent\protected\def\dostartclipping#1#2#3% we can move this to lua and only set a box here
-%   {\forcecolorhack
-%    \meta_grab_clip_path{#1}{#2}{#3}%
-%    \clf_startclipping{\MPclippath}%
-%    \glet\MPclippath\empty}
-
-\permanent\protected\def\dostartclipping#1#2#3% we can move this to lua and only set a box here
-  {\meta_grab_clip_path{#1}{#2}{#3}%
-   \clf_startclipping{\MPclippath}%
-   \glet\MPclippath\empty}
-
-\permanent\protected\def\dostopclipping
-  {\clf_stopclipping}
-
-%D This wrapper is needed when you use code that messes with e.g. local color
-%D directives, invisible for the rest of the machinery. It's only needed in very
-%D special cases, like around the above scaler directives:
-
-\permanent\protected\edef\hcontainer{\hpack \s!direction\directionlefttoright \s!container\space}
-\permanent\protected\edef\vcontainer{\vpack \s!direction\directionlefttoright \s!container\space}
-\permanent\protected\edef\tcontainer{\tpack \s!direction\directionlefttoright \s!container\space}
-
-\protect \endinput
diff --git a/tex/context/base/mkxl/back-imp-lua.lmt b/tex/context/base/mkxl/back-imp-lua.lmt
new file mode 100644
index 000000000..5bb23973c
--- /dev/null
+++ b/tex/context/base/mkxl/back-imp-lua.lmt
@@ -0,0 +1,378 @@
+if not modules then modules = { } end modules ['back-imp-lua'] = {
+    version   = 1.001,
+    optimize  = true,
+    comment   = "companion to back-imp-lua.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+-- we can remap fonts
+
+local fontproperties    = fonts.hashes.properties
+local fontparameters    = fonts.hashes.parameters
+local fontshapes        = fonts.hashes.shapes
+
+local starttiming       = statistics.starttiming
+local stoptiming        = statistics.stoptiming
+
+local bpfactor          = number.dimenfactors.bp
+local texgetbox         = tex.getbox
+
+local rulecodes         = nodes.rulecodes
+local normalrule_code   = rulecodes.normal
+----- boxrule_code      = rulecodes.box
+----- imagerule_code    = rulecodes.image
+----- emptyrule_code    = rulecodes.empty
+----- userrule_code     = rulecodes.user
+----- overrule_code     = rulecodes.over
+----- underrule_code    = rulecodes.under
+----- fractionrule_code = rulecodes.fraction
+----- radicalrule_code  = rulecodes.radical
+local outlinerule_code  = rulecodes.outline
+
+-- todo : per instance
+
+local pages     = { }
+local fonts     = { }
+local names     = { }
+local mapping   = { }
+local used      = { }
+local shapes    = { }
+local glyphs    = { }
+local buffer    = { }
+local metadata  = nil
+local b         = 0
+local converter = nil
+
+local compact   = false -- true
+local shapestoo = true
+
+local x, y, d, f, c, w, h, t, r, o
+
+local function reset()
+    buffer = { }
+    b      = 0
+    t      = nil
+    x      = nil
+    y      = nil
+    d      = nil
+    f      = nil
+    c      = nil
+    w      = nil
+    h      = nil
+    r      = nil
+    o      = nil
+end
+
+local function result()
+    return {
+        metadata = metadata,
+        fonts    = fonts,
+        pages    = pages,
+        shapes   = shapes,
+    }
+end
+
+-- actions
+
+local function outputfilename(driver)
+    return tex.jobname .. "-output.lua"
+end
+
+local function save() -- might become a driver function that already is plugged into stopactions
+    local filename = outputfilename()
+    drivers.report("saving result in %a",filename)
+    starttiming(drivers)
+    local data = result()
+    if data then
+        io.savedata(filename,table.serialize(data))
+    end
+    stoptiming(drivers)
+end
+
+local function prepare(driver)
+    converter = drivers.converters.lmtx
+ -- if not environment.initex then
+        backends.initialize("lua")
+ -- end
+    luatex.registerstopactions(1,function()
+        save()
+    end)
+end
+
+local function initialize(driver,details)
+    reset()
+end
+
+local function finalize(driver,details)
+    local n = details.pagenumber
+    local b = details.boundingbox
+    pages[n] = {
+        number      = n,
+        content     = buffer,
+        boundingbox = {
+            b[1] * bpfactor,
+            b[2] * bpfactor,
+            b[3] * bpfactor,
+            b[4] * bpfactor,
+        },
+    }
+    if not metadata then
+        -- this has to happen while we're still running tex because we do
+        -- prerolls
+        local identity = interactions.general.getidentity()
+        local jobname  = environment.jobname or tex.jobname or "unknown"
+        metadata = {
+            unit     = "bp",
+            jobname  = jobname,
+            title    = identity.title,
+            subject  = identity.subject,
+            author   = identity.author,
+            keywords = identity.keywords,
+            time     = os.date("%Y-%m-%d %H:%M"),
+            engine   = environment.luatexengine .. " " .. environment.luatexversion,
+            context  = environment.version,
+        }
+    end
+end
+
+local function wrapup(driver)
+end
+
+local function cleanup(driver)
+    reset()
+end
+
+local function convert(driver,boxnumber,pagenumber)
+    converter(driver,texgetbox(boxnumber),"page",pagenumber)
+end
+
+-- flushers
+
+local function updatefontstate(id)
+    if not mapping[id] then
+        local fn = #fonts + 1
+        mapping[id] = fn
+        local properties = fontproperties[id]
+        local parameters = fontparameters[id]
+        local filename   = file.basename(properties.filename)
+        local fontname   = properties.fullname or properties.fontname
+        if shapestoo then
+            if not names[fontname] then
+                local sn = #shapes+1
+                names[fontname] = sn
+                shapes[sn] = { }
+                glyphs[sn] = fontshapes[id].glyphs
+            end
+        end
+        fonts[fn] = {
+            filename = filename,
+            name     = fontname,
+            size     = parameters.size * bpfactor,
+            shapes   = shapestoo and names[fontname] or nil,
+        }
+    end
+end
+
+local function flushcharacter(current, pos_h, pos_v, pos_r, font, char)
+    local fnt = mapping[font]
+    b = b + 1
+    buffer[b] = {
+        t = "glyph" ~= t and "glyph" or nil,
+        f = font    ~= f and fnt or nil,
+        c = char    ~= c and char or nil,
+        x = pos_h   ~= x and (pos_h * bpfactor) or nil,
+        y = pos_v   ~= y and (pos_v * bpfactor) or nil,
+        d = pos_r   ~= d and (pos_r == 1 and "r2l" or "l2r") or nil,
+    }
+    t = "glyph"
+    f = font
+    c = char
+    x = pos_h
+    y = pos_v
+    d = pos_r
+    if shapestoo then
+        -- can be sped up if needed
+        local sn = fonts[fnt].shapes
+        local shp = shapes[sn]
+        if not shp[char] then
+            shp[char] = glyphs[sn][char]
+        end
+    end
+end
+
+local function flush_rule(current, pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o)
+    b = b + 1
+    buffer[b] = {
+        t = "rule" ~= t and "rule" or nil,
+        r = rule_s ~= r and rule_s or nil,
+        o = rule_s == "outline" and rule_o ~= o and (rule_o * bpfactor) or nil,
+        w = size_h ~= w and (size_h * bpfactor) or nil,
+        h = size_v ~= h and (size_v * bpfactor) or nil,
+        x = pos_h  ~= x and (pos_h  * bpfactor) or nil,
+        y = pos_v  ~= y and (pos_v  * bpfactor) or nil,
+        d = pos_r  ~= d and (pos_r == 1 and "r2l" or "l2r") or nil,
+    }
+    t = "rule"
+    w = size_h
+    h = size_v
+    x = pos_h
+    y = pos_v
+    d = pos_r
+end
+
+local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v, subtype)
+    local rule_s, rule_o
+    if subtype == normalrule_code then
+        rule_s = normal_rule_code
+    elseif subtype == outlinerule_code then
+        rule_s = outline_rule_code
+        rule_o = getdata(current)
+    else
+        return
+    end
+    return flush_rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o)
+end
+
+local function flushsimplerule(pos_h, pos_v, pos_r, size_h, size_v)
+    return flush_rule(false,pos_h,pos_v,pos_r,size_h,size_v,normalrule_code,nil)
+end
+
+local function flushspecialrule(pos_h, pos_v, pos_r, w, h, d, l, outline)
+    return flush_rule(false,pos_h,pos_v-d,pos_r,w,h+d,outline and outlinerule_code or normalrule_code)
+end
+
+-- file stuff too
+-- todo: default flushers
+-- also color (via hash)
+
+-- installer
+
+drivers.install {
+    name    = "lua",
+    actions = {
+        prepare         = prepare,
+        initialize      = initialize,
+        finalize        = finalize,
+        wrapup          = wrapup,
+        cleanup         = cleanup,
+        convert         = convert,
+        outputfilename  = outputfilename,
+    },
+    flushers = {
+        updatefontstate = updatefontstate,
+        character       = flushcharacter,
+        rule            = flushrule,
+        simplerule      = flushsimplerule,
+        specialrule     = flushspecialrule,
+    }
+}
+
+-- actions
+
+local function outputfilename(driver)
+    return tex.jobname .. "-output.json"
+end
+
+local function save() -- might become a driver function that already is plugged into stopactions
+    local filename = outputfilename()
+    drivers.report("saving result in %a",filename)
+    starttiming(drivers)
+    local data = result()
+    if data then
+        if not utilities.json then
+            require("util-jsn")
+        end
+        io.savedata(filename,utilities.json.tostring(data,not compact))
+    end
+    stoptiming(drivers)
+end
+
+local function prepare(driver)
+    converter = drivers.converters.lmtx
+    luatex.registerstopactions(1,function()
+        save()
+    end)
+end
+
+-- installer
+
+drivers.install {
+    name    = "json",
+    actions = {
+        prepare         = prepare,
+        wrapup          = wrapup,
+        cleanup         = cleanup,
+        --
+        initialize      = initialize,
+        convert         = convert,
+        finalize        = finalize,
+        --
+        outputfilename  = outputfilename,
+    },
+    flushers = {
+        updatefontstate = updatefontstate,
+        character       = flushcharacter,
+        rule            = flushrule,
+        simplerule      = flushsimplerule,
+        specialrule     = flushspecialrule,
+        setstate        = function() end,
+    }
+}
+
+-- actions
+
+local function outputfilename(driver)
+    return tex.jobname .. "-output.js"
+end
+
+local function save() -- might become a driver function that already is plugged into stopactions
+    local filename = outputfilename()
+    drivers.report("saving result in %a",filename)
+    starttiming(drivers)
+    local data = result()
+    if data then
+        if not utilities.json then
+            require("util-jsn")
+        end
+        io.savedata(filename,
+            "const JSON_CONTEXT = JSON.parse ( `" ..
+            utilities.json.tostring(data,not compact) ..
+            "` ) ;\n"
+        )
+    end
+    stoptiming(drivers)
+end
+
+local function prepare(driver)
+    converter = drivers.converters.lmtx
+ -- if not environment.initex then
+        backends.initialize("js")
+ -- end
+    luatex.registerstopactions(1,function()
+        save()
+    end)
+end
+
+-- installer
+
+drivers.install {
+    name    = "js",
+    actions = {
+        prepare         = prepare,
+        initialize      = initialize,
+        finalize        = finalize,
+        wrapup          = wrapup,
+        cleanup         = cleanup,
+        convert         = convert,
+        outputfilename  = outputfilename,
+    },
+    flushers = {
+        updatefontstate = updatefontstate,
+        character       = flushcharacter,
+        rule            = flushrule,
+        simplerule      = flushsimplerule,
+        specialrule     = flushspecialrule,
+    }
+}
diff --git a/tex/context/base/mkxl/back-imp-lua.mkxl b/tex/context/base/mkxl/back-imp-lua.mkxl
new file mode 100644
index 000000000..db26657ef
--- /dev/null
+++ b/tex/context/base/mkxl/back-imp-lua.mkxl
@@ -0,0 +1,16 @@
+%D \module
+%D   [       file=back-imp-lua,
+%D        version=2018.07.26,
+%D          title=\CONTEXT\ Backend Macros,
+%D       subtitle=\LUA,
+%D         author=Hans Hagen,
+%D           date=\currentdate,
+%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{back-imp-lua}{autosuffix,optimize}
+
+\endinput
diff --git a/tex/context/base/mkxl/back-imp-mps.lmt b/tex/context/base/mkxl/back-imp-mps.lmt
new file mode 100644
index 000000000..05d7c4a63
--- /dev/null
+++ b/tex/context/base/mkxl/back-imp-mps.lmt
@@ -0,0 +1,215 @@
+if not modules then modules = { } end modules ['back-imp-mps'] = {
+    version   = 1.001,
+    optimize  = true,
+    comment   = "companion to back-imp-mps.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+local fontproperties    = fonts.hashes.properties
+local fontparameters    = fonts.hashes.parameters
+
+local starttiming       = statistics.starttiming
+local stoptiming        = statistics.stoptiming
+
+local bpfactor          = number.dimenfactors.bp
+local texgetbox         = tex.getbox
+local formatters        = string.formatters
+
+local rulecodes         = nodes.rulecodes
+local normalrule_code   = rulecodes.normal
+----- boxrule_code      = rulecodes.box
+----- imagerule_code    = rulecodes.image
+----- emptyrule_code    = rulecodes.empty
+----- userrule_code     = rulecodes.user
+----- overrule_code     = rulecodes.over
+----- underrule_code    = rulecodes.under
+----- fractionrule_code = rulecodes.fraction
+----- radicalrule_code  = rulecodes.radical
+local outlinerule_code  = rulecodes.outline
+
+local fonts     = { }
+local pages     = { }
+local buffer    = { }
+local b         = 0
+local converter = nil
+
+local function reset()
+    buffer = { }
+    b      = 0
+end
+
+-- todo: high efficient helpers:
+
+local f_font    = formatters[ "\\definefont[%s][file:%s*none @ %sbp]\n" ]
+
+local f_glyph   = formatters[ [[draw textext.drt("\%s\char%i\relax") shifted (%N,%N);]] ]
+local f_rule    = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
+local f_outline = formatters[ [[draw unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
+
+-- actions
+
+local function outputfilename(driver)
+    return tex.jobname .. "-output.tex"
+end
+
+local function save() -- might become a driver function that already is plugged into stopactions
+    starttiming(drivers)
+    if #pages > 0 then
+        local filename = outputfilename()
+        drivers.report("saving result in %a",filename)
+        reset()
+        b = b + 1
+        buffer[b] = "\\starttext\n"
+        for k, v in table.sortedhash(fonts) do
+            b = b + 1
+            buffer[b] = f_font(v.name,v.filename,v.size)
+        end
+        for i=1,#pages do
+            b = b + 1
+            buffer[b] = pages[i]
+        end
+        b = b + 1
+        buffer[b] = "\\stoptext\n"
+        io.savedata(filename,table.concat(buffer,"",1,b))
+    end
+    stoptiming(drivers)
+end
+
+local function prepare(driver)
+    converter = drivers.converters.lmtx
+ -- if not environment.initex then
+        backends.initialize("mps")
+ -- end
+    luatex.registerstopactions(1,function()
+        save()
+    end)
+end
+
+local function initialize(driver,details)
+    reset()
+    b = b + 1
+    buffer[b] = "\n\\startMPpage"
+end
+
+local function finalize(driver,details)
+    b = b + 1
+    buffer[b] = "\\stopMPpage\n"
+    pages[details.pagenumber] = table.concat(buffer,"\n",1,b)
+end
+
+local function wrapup(driver)
+end
+
+local function cleanup(driver)
+    reset()
+end
+
+local function convert(driver,boxnumber,pagenumber)
+    converter(driver,texgetbox(boxnumber),"page",pagenumber)
+end
+
+-- flushers
+
+local last
+
+local function updatefontstate(id)
+    if fonts[id] then
+        last = fonts[id].name
+    else
+        last = "MPSfont" .. converters.Characters(id)
+        fonts[id] = {
+            filename = file.basename(fontproperties[id].filename),
+            size     = fontparameters[id].size * bpfactor,
+            name     = last,
+        }
+    end
+end
+
+local function flushcharacter(current, pos_h, pos_v, pos_r, font, char)
+    b = b + 1
+    buffer[b] = f_glyph(last,char,pos_h*bpfactor,pos_v*bpfactor)
+end
+
+local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v, subtype)
+    if subtype == normalrule_code then
+        b = b + 1
+        buffer[b] = f_rule(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor)
+    elseif subtype == outlinerule_code then
+        b = b + 1
+        buffer[b] = f_outline(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor)
+    end
+end
+
+local function flushsimplerule(pos_h, pos_v, pos_r, size_h, size_v)
+    flushrule(false,pos_h,pos_v,pos_r,size_h,size_v,normalrule_code)
+end
+
+local function flushspecialrule(pos_h, pos_v, pos_r, w, h, d, l, outline)
+    flushrule(false,pos_h,pos_v-d,pos_r,w,h+d,outline and outlinerule_code or normalrule_code)
+end
+
+-- installer
+
+drivers.install {
+    name    = "mps",
+    actions = {
+        prepare         = prepare,
+        initialize      = initialize,
+        finalize        = finalize,
+        wrapup          = wrapup,
+        cleanup         = cleanup,
+        convert         = convert,
+        outputfilename  = outputfilename,
+    },
+    flushers = {
+        updatefontstate = updatefontstate,
+        character       = flushcharacter,
+        rule            = flushrule,
+        simplerule      = flushsimplerule,
+        specialrule     = flushspecialrule,
+    }
+}
+
+-- extras
+
+-- if not mp then
+--     return
+-- end
+--
+-- local mpprint    = mp.print
+-- local formatters = string.formatters
+--
+-- local f_glyph = formatters[ [[draw textext.drt("\setfontid%i\relax\char%i\relax") shifted (%N,%N);]] ]
+-- local f_rule  = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
+--
+-- local current = nil
+-- local size    = 0
+--
+-- function mp.place_buffermake(box)
+--     drivers.convert("mps",box)
+--     current = drivers.action("mps","fetch")
+--     size    = #current
+-- end
+--
+-- function mp.place_buffersize()
+--     mpprint(size)
+-- end
+--
+-- function mp.place_bufferslot(i)
+--     if i > 0 and i <= size then
+--         local b = buffer[i]
+--         local t = b[1]
+--         if t == "glyph" then
+--             mpprint(f_glyph(b[2],b[3],b[4]*bpfactor,b[5]*bpfactor))
+--         elseif t == "rule" then
+--             mpprint(f_rule(b[2]*bpfactor,b[3]*bpfactor,b[4]*bpfactor,b[5]*bpfactor))
+--         end
+--     end
+-- end
+--
+-- function mp.place_bufferwipe()
+--     current = nil
+--     size    = 0
+-- end
diff --git a/tex/context/base/mkxl/back-imp-mps.mkxl b/tex/context/base/mkxl/back-imp-mps.mkxl
new file mode 100644
index 000000000..45dde7e36
--- /dev/null
+++ b/tex/context/base/mkxl/back-imp-mps.mkxl
@@ -0,0 +1,16 @@
+%D \module
+%D   [       file=back-imp-mps,
+%D        version=2018.07.26,
+%D          title=\CONTEXT\ Backend Macros,
+%D       subtitle=\METAPOST,
+%D         author=Hans Hagen,
+%D           date=\currentdate,
+%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{back-imp-mps}{autosuffix,optimize}
+
+\endinput
diff --git a/tex/context/base/mkxl/back-imp-pdf.lmt b/tex/context/base/mkxl/back-imp-pdf.lmt
new file mode 100644
index 000000000..a57427e66
--- /dev/null
+++ b/tex/context/base/mkxl/back-imp-pdf.lmt
@@ -0,0 +1,49 @@
+if not modules then modules = { } end modules ['back-imp-pdf'] = {
+    version   = 1.001,
+    comment   = "companion to back-imp-pdf.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+-- We hide the pdf table from users so that we can guarantee no interference with
+-- the way we manage resources, info, etc. Users should use the \type {lpdf}
+-- interface instead. For now we have a little for tikz. If really needed some more
+-- can be made accessible but it has to happen in a controlled way then, for
+-- instance by first loading or enabling some compatibility layer so that we can
+-- trace possible interferences.
+
+updaters.register("backends.pdf.latebindings",function()
+    --
+    local dummy  = function() end
+    local report = logs.reporter("backend")
+    --
+    -- For now we keep this for tikz. If really needed some more can be made
+    -- accessible but it has to happen in a controlled way then, for instance
+    -- by first loading or enabling some compatibility layer so that we can
+    -- trace possible interferences.
+    --
+    pdf = {
+        immediateobj = lpdf.immediateobject
+    }
+
+    table.setmetatableindex(pdf,function(t,k)
+        report("calling unavailable pdf.%s function",k)
+        t[k] = dummy
+        return dummy
+    end)
+
+end)
+
+-- The compression setter is defined here because it's probably the only macro
+-- that is used independent of a driver being chosen. It's easier this way than
+-- checking in other ways unless we add some generic compression setting to
+-- all drivers.
+
+interfaces.implement {
+    name      = "setpdfcompression",
+    arguments = { "integer", "integer" },
+    actions   = lpdf.setcompression,
+}
+
+-- The pdf driver itself is installed in lpdf-lmt.lmt!
diff --git a/tex/context/base/mkxl/back-imp-pdf.mkxl b/tex/context/base/mkxl/back-imp-pdf.mkxl
new file mode 100644
index 000000000..a9cffc6cb
--- /dev/null
+++ b/tex/context/base/mkxl/back-imp-pdf.mkxl
@@ -0,0 +1,160 @@
+%D \module
+%D   [       file=back-imp-pdf,
+%D        version=2009.04.15,
+%D          title=\CONTEXT\ Backend Macros,
+%D       subtitle=\PDF,
+%D         author=Hans Hagen,
+%D           date=\currentdate,
+%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D The less there is here, the better. After a decade it is time to remove the \type
+%D {\pdf*} ones completely. For the moment I keep them commented but even that will
+%D go away.
+
+%D Todo: a few delayed binding left:
+
+% ./lpdf-ini.lmt : reserve | immediate | positions | matrix | pos | fontobject
+% ./lpdf-lmt.lmt : fontname | object | boxresources
+% ./lpdf-rul.lmt : mp stuff
+% ./back-res.lmt : boxresources
+
+\writestatus{loading}{ConTeXt Backend Macros / PDF}
+
+% \registerctxluafile{back-imp-pdf}{autosuffix} % some code will move to lpdf-*
+
+\registerctxluafile{lpdf-ini}{autosuffix}
+\registerctxluafile{lpdf-lmt}{autosuffix}
+\registerctxluafile{lpdf-col}{autosuffix}
+\registerctxluafile{lpdf-xmp}{autosuffix}
+\registerctxluafile{lpdf-ano}{autosuffix}
+\registerctxluafile{lpdf-mis}{autosuffix}
+\registerctxluafile{lpdf-ren}{autosuffix}
+\registerctxluafile{lpdf-grp}{autosuffix}
+\registerctxluafile{lpdf-wid}{autosuffix}
+\registerctxluafile{lpdf-fld}{autosuffix}
+\registerctxluafile{lpdf-tag}{autosuffix}
+\registerctxluafile{lpdf-fmt}{autosuffix}
+\registerctxluafile{lpdf-pde}{autosuffix}
+\registerctxluafile{lpdf-img}{autosuffix}
+\registerctxluafile{lpdf-epa}{autosuffix}
+\registerctxluafile{lpdf-emb}{autosuffix}
+\registerctxluafile{lpdf-fnt}{autosuffix}
+\registerctxluafile{lpdf-rul}{autosuffix}
+
+\registerctxluafile{back-imp-pdf}{autosuffix} % some code will move to lpdf-*
+\registerctxluafile{back-imp-pdp}{autosuffix}
+
+% \registerctxluafile{lpdf-u3d}{autosuffix}
+
+\loadmkxlfile{back-imp-u3d}
+
+\unprotect
+
+%D We will minimize the number of calls to \PDF\ specific primitives and delegate
+%D all management and injection of code to the backend.
+%D
+%D Because we do a lot in \LUA\ and don't want interferences, we nil most of the
+%D \PDFTEX\ primitives. Of course one can always use the \type {\pdfvariable},
+%D \type {\pdfextension} and \type {\pdffeedback} primitives but it will probably
+%D have bad side effects. We fake them as primitives which is why they are
+%D defined as untraced.
+
+% \pdfextension % defined in lua
+% \pdffeedback  % idem
+% \pdfvariable  % idem
+% \pdfliteral   % idem
+% \pdfobj       % idem
+% \pdflastobj   % idem
+% \pdfrefobj    % idem
+
+\untraced\permanent\protected\def\pdfrestore  {\pdfextension restore}
+\untraced\permanent\protected\def\pdfsave     {\pdfextension save}
+\untraced\permanent\protected\def\pdfsetmatrix{\pdfextension setmatrix}
+
+\untraced\permanent\def\pdfxform              {\saveboxresource}
+\untraced\permanent\def\pdflastxform          {\lastsavedboxresourceindex}
+\untraced\permanent\def\pdfrefxform           {\useboxresource}
+
+%D This is also needed for tikz:
+
+\ifdefined\pdfsavepos\else
+    \untraced\permanent\def\pdfsavepos {\savepos }
+    \untraced\permanent\def\pdflastxpos{\lastxpos}
+    \untraced\permanent\def\pdflastypos{\lastypos}
+\fi
+
+%D Here are quick and dirty compression flippers, mostly used when testing something
+%D as one can best stick to the defaults that also adapt to specific standards.
+
+\untraced\permanent\protected\def\nopdfcompression        {\clf_setpdfcompression\zerocount\zerocount}
+\untraced\permanent\protected\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree}
+\untraced\permanent\protected\def\maximumpdfcompression   {\clf_setpdfcompression\plusnine \plusnine }
+\untraced\permanent\protected\def\normalpdfcompression    {\clf_setpdfcompression\plusthree\plusthree}
+
+%D PDF/X (maybe combine the two lua calls)
+
+\setupbackend
+  [xmpfile=]
+
+\appendtoks
+    \edef\p_file{\backendparameter{xmpfile}}%
+    \ifempty\p_file\else
+      \clf_setxmpfile{\p_file}%
+    \fi
+\to \everysetupbackend
+
+%D This will change:
+
+\appendtoks
+    \clf_setformat
+         format  {\backendparameter\c!format}%
+         level   {\backendparameter\c!level}%
+         option  {\backendparameter\c!option}%
+         profile {\backendparameter\c!profile}%
+         intent  {\backendparameter\c!intent}%
+         file    {\backendparameter\c!file}%
+    \relax
+\to \everysetupbackend
+
+%D These are the only official methods to add stuff to the resources. If more is
+%D needed for third party low level code, it can be added.
+
+% \pdfbackendsetcatalog       #1#2 % defined in lua
+% \pdfbackendsetinfo          #1#2 % idem
+% \pdfbackendsetname          #1#2 % idem
+%
+% \pdfbackendsetpageattribute #1#2 % idem
+% \pdfbackendsetpagesattribute#1#2 % idem
+% \pdfbackendsetpageresource  #1#2 % idem
+%
+% \pdfbackendsetextgstate     #1#2 % idem
+% \pdfbackendsetcolorspace    #1#2 % idem
+% \pdfbackendsetpattern       #1#2 % idem
+% \pdfbackendsetshade         #1#2 % idem
+%
+% \pdfbackendcurrentresources      %  idem, expandable
+% \pdfcolor                     #1 %  idem, expandable
+
+%D This is a temporary hack that will be removed, improved or somehow can become
+%D default.
+
+\permanent\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]}
+
+%D Just in case one needs this \unknown:
+%D
+%D \starttyping
+%D text \pdfbackendactualtext{Meier}{Müller} text
+%D \stoptyping
+
+\untraced\permanent\protected\def\pdfbackendactualtext#1#2% not interfaced
+  {\clf_startactualtext{#2}%
+   #1%
+   \clf_stopactualtext}
+
+\aliased\let\pdfactualtext\pdfbackendactualtext
+
+\protect \endinput
diff --git a/tex/context/base/mkxl/back-imp-pdp.lmt b/tex/context/base/mkxl/back-imp-pdp.lmt
new file mode 100644
index 000000000..c7acc82a8
--- /dev/null
+++ b/tex/context/base/mkxl/back-imp-pdp.lmt
@@ -0,0 +1,289 @@
+if not modules then modules = { } end modules ['back-imp-pdp'] = {
+    version   = 1.001,
+    comment   = "companion to back-imp-pdf.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+-- This is temporary ... awaiting a better test .. basically we can
+-- always use this: pdf primitives.
+
+local context = context
+local lpdf    = lpdf
+
+local pdfreserveobject = lpdf.reserveobject
+local pdfcompresslevel = lpdf.compresslevel
+local pdfobject        = lpdf.object
+local pdfpagereference = lpdf.pagereference
+local pdfgetxformname  = lpdf.getxformname
+local pdfminorversion  = lpdf.minorversion
+local pdfmajorversion  = lpdf.majorversion
+
+local tokenscanners    = tokens.scanners
+local scanword         = tokenscanners.word
+local scankeyword      = tokenscanners.keyword
+local scanstring       = tokenscanners.string
+local scaninteger      = tokenscanners.integer
+local scanwhd          = tokenscanners.whd
+
+local values           = tokens.values
+local dimension_value  = values.dimension
+local cardinal_value   = values.cardinal
+
+local immediate_code   = tex.flagcodes.immediate
+
+local trace            = false  trackers.register("backend", function(v) trace = v end)
+local report           = logs.reporter("backend")
+
+local nodepool         = nodes.pool
+local newliteral       = nodepool.literal
+local newsave          = nodepool.save
+local newrestore       = nodepool.restore
+local newsetmatrix     = nodepool.setmatrix
+
+local implement        = interfaces.implement
+local constants        = interfaces.constants
+local variables        = interfaces.variables
+
+-- literals
+
+local function pdf_literal()
+    context(newliteral(scanword() or "origin",scanstring()))
+end
+
+-- objects
+
+local lastobjnum = 0
+
+local function pdf_obj(prefix)
+    if scankeyword("reserveobjnum") then
+        lastobjnum = pdfreserveobject()
+        if trace then
+            report("\\pdfobj reserveobjnum: object %i",lastobjnum)
+        end
+    else
+        local immediate    = prefix and (prefix & immediate_code) ~= 0 -- was just "true"
+        local objnum       = scankeyword("useobjnum") and scaninteger() or pdfreserveobject()
+        local uncompress   = scankeyword("uncompressed") or pdfcompresslevel() == 0
+        local streamobject = scankeyword("stream")
+        local attributes   = scankeyword("attr") and scanstring() or nil
+        local fileobject   = scankeyword("file")
+        local content      = scanstring()
+        local object = streamobject and {
+            type          = "stream",
+            objnum        = objnum,
+            immediate     = immediate,
+            attr          = attributes,
+            compresslevel = uncompress and 0 or nil,
+        } or {
+            type          = "raw",
+            objnum        = objnum,
+            immediate     = immediate,
+        }
+        if fileobject then
+            object.file = content
+         -- object.filename = content
+        else
+            object.string = content
+        end
+        pdfobject(object)
+        lastobjnum = objnum
+        if trace then
+            report("\\pdfobj: object %i",lastobjnum)
+        end
+    end
+end
+
+local function pdf_lastobj()
+    if trace then
+        report("\\lastobj: object %i",lastobjnum)
+    end
+    return cardinal_value, lastobjnum
+end
+
+local function pdf_pagereference()
+    return cardinal_value, pdfpagereference()
+end
+
+local function pdf_refobj()
+    local objnum = scaninteger()
+    if trace then
+        report("\\refobj: object %i (todo)",objnum)
+    end
+end
+
+-- annotations
+
+local lastobjnum = 0
+
+local function pdf_annot()
+    if scankeyword("reserveobjnum") then
+        lastobjnum = pdfreserveobject()
+        if trace then
+            report("\\pdfannot reserveobjnum: object %i",lastobjnum)
+        end
+    else
+        local width  = false
+        local height = false
+        local depth  = false
+        local data   = false
+        local object = false
+        local attr   = false
+        --
+        if scankeyword("useobjnum") then
+            object = scancount()
+            report("\\pdfannot useobjectnum is not (yet) supported")
+        end
+        local width, height, depth = scanwhd()
+        if scankeyword("attr") then
+            attr = scanstring()
+        end
+        data = scanstring()
+        context(backends.nodeinjections.annotation(width or 0,height or 0,depth or 0,data or ""))
+    end
+end
+
+local function pdf_dest()
+    local name   = false
+    local zoom   = false
+    local view   = false
+    local width  = false
+    local height = false
+    local depth  = false
+    if scankeyword("num") then
+        report("\\pdfdest num is not (yet) supported")
+    elseif scankeyword("name") then
+        name = scanstring()
+    end
+    if scankeyword("xyz") then
+        view = "xyz"
+        if scankeyword("zoom") then
+            report("\\pdfdest zoom is ignored")
+            zoom = scancount() -- will be divided by 1000 in the backend
+        end
+    elseif scankeyword("fitbh") then
+        view = "fitbh"
+    elseif scankeyword("fitbv") then
+        view = "fitbv"
+    elseif scankeyword("fitb") then
+        view = "fitb"
+    elseif scankeyword("fith") then
+        view = "fith"
+    elseif scankeyword("fitv") then
+        view = "fitv"
+    elseif scankeyword("fitr") then
+        view = "fitr"
+        width, height, depth = scanwhd()
+    elseif scankeyword("fit") then
+        view = "fit"
+    end
+    context(backends.nodeinjections.destination(width or 0,height or 0,depth or 0,{ name or "" },view or "fit"))
+end
+
+-- management
+
+local function pdf_save()
+    context(newsave())
+end
+
+local function pdf_restore()
+    context(newrestore())
+end
+
+local function pdf_setmatrix()
+    context(newsetmatrix(scanstring()))
+end
+
+-- extras
+
+-- extensions: literal dest annot save restore setmatrix obj refobj colorstack
+-- startlink endlink startthread endthread thread outline glyphtounicode fontattr
+-- mapfile mapline includechars catalog info names trailer
+
+local extensions = {
+    literal   = pdf_literal,
+    obj       = pdf_obj,
+    refobj    = pdf_refobj,
+    dest      = pdf_dest,
+    annot     = pdf_annot,
+    save      = pdf_save,
+    restore   = pdf_restore,
+    setmatrix = pdf_setmatrix,
+}
+
+local function pdf_extension()
+    local w = scanword()
+    if w then
+        local e = extensions[w]
+        if e then
+            e()
+        else
+            report("\\pdfextension: unsupported %a",w)
+        end
+    end
+end
+
+-- feedbacks: colorstackinit creationdate fontname fontobjnum fontsize lastannot
+-- lastlink lastobj pageref retval revision version xformname
+
+local feedbacks = {
+    lastobj   = pdf_lastobj,
+    pageref   = pdf_pagereference,
+    xformname = function() context(pdfgetxformname ()) end,
+}
+
+local function pdf_feedback()
+    local w = scanword()
+    if w then
+        local f = feedbacks[w]
+        if f then
+            f()
+        else
+            report("\\pdffeedback: unsupported %a",w)
+        end
+    end
+end
+
+-- variables: (integers:) compresslevel decimaldigits gamma gentounicode
+-- ignoreunknownimages imageaddfilename imageapplygamma imagegamma imagehicolor
+-- imageresolution inclusioncopyfonts inclusionerrorlevel majorversion minorversion
+-- objcompresslevel omitcharset omitcidset pagebox pkfixeddpi pkresolution
+-- recompress suppressoptionalinfo uniqueresname (dimensions:) destmargin horigin
+-- linkmargin threadmargin vorigin xformmargin (tokenlists:) pageattr pageresources
+-- pagesattr pkmode trailerid xformattr xformresources
+
+local variables = {
+    minorversion = function() context(pdfminorversion()) end,
+    majorversion = function() context(pdfmajorversion()) end,
+}
+
+local function pdf_variable()
+    local w = scanword()
+    if w then
+        local f = variables[w]
+        if f then
+            f()
+        else
+            report("\\pdfvariable: unsupported %a",w)
+        end
+    else
+        print("missing variable")
+    end
+end
+
+-- kept (also because tikz needs including the pdftex primitives):
+
+implement { name = "pdfextension", actions = pdf_extension, public = true, untraced = true, protected = true }
+implement { name = "pdffeedback",  actions = pdf_feedback,  public = true, untraced = true } -- expandable / todo : value
+implement { name = "pdfvariable",  actions = pdf_variable,  public = true, untraced = true } -- expandable / todo : value
+implement { name = "pdfliteral",   actions = pdf_literal,   public = true, untraced = true, protected = true }
+implement { name = "pdfobj",       actions = pdf_obj,       public = true, usage = "value", protected = true }
+implement { name = "pdflastobj",   actions = pdf_lastobj,   public = true, usage = "value", protected = true }
+implement { name = "pdfrefobj",    actions = pdf_refobj,    public = true, untraced = true, protected = true }
+
+--------- { name = "pdfannot",     actions = pdf_annot }
+--------- { name = "pdfdest",      actions = pdf_dest }
+--------- { name = "pdfsave",      actions = pdf_save }
+--------- { name = "pdfrestore",   actions = pdf_restore }
+--------- { name = "pdfsetmatrix", actions = pdf_setmatrix }
diff --git a/tex/context/base/mkxl/back-imp-u3d.mkxl b/tex/context/base/mkxl/back-imp-u3d.mkxl
new file mode 100644
index 000000000..e91ef485f
--- /dev/null
+++ b/tex/context/base/mkxl/back-imp-u3d.mkxl
@@ -0,0 +1,160 @@
+%D \module
+%D   [       file=back-imp-u3d,
+%D        version=2009.04.15,
+%D          title=\CONTEXT\ Backend Macros,
+%D       subtitle=U3D Experiment,
+%D         author=Hans Hagen,
+%D           date=\currentdate,
+%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D This is only a placeholder that demonstrates the usage of u3d resources. The
+%D user interface is rather messy an might be improved. The files and setup is
+%D derived from an example by Michael Vidiassov.
+
+\registerctxluafile{lpdf-u3d}{autosuffix}
+
+\endinput
+
+\starttext
+
+\startluaparameterset [u3d:myset:controls:1]
+    view = {
+        name = 'default',
+        bg = {1,1,1},
+        mag = 100,
+        coo = {0,0,0},
+        c2c = {0,0,1},
+        rot = {40,0,60},
+        roo = 6,
+        lights = 'CAD'
+    },
+    js = 'cloudq.js'
+\stopluaparameterset
+
+\startluaparameterset [u3d:myset:controls:2]
+    views = {
+        {
+            name = 'AnglePositioning',
+            bg = {1,1,1},
+            azimuth = 45,
+            altitude = 45,
+            roo = 50,
+            aac = 2.5,
+            lights = 'Artwork'
+        },
+        {
+            name = 'RotationPositioning',
+            bg = {1,1,1},
+            rot = {0,45,45},
+            roo = 50,
+            aac = 2.5,
+            lights = 'Artwork'
+        },
+        {
+            name = 'VectorPositioning',
+            bg = {1,0,0},
+            c2c = {1,1,math.sqrt(2)},
+            roo = 50,
+            aac = 2.5,
+            lights = 'CAD'
+        },
+        {
+            name = 'PositionPositioning',
+            bg = {1,0,0},
+            pos = {1+25,1+25,1+50/math.sqrt(2)},
+            aac = 2.5,
+            lights = 'CAD'
+        },
+        {
+            name = 'ortho',
+            bg = {1,1,1},
+            mag = 300,
+            lights = 'CAD',
+            crossection = {}
+        }
+    },
+    view = {
+        name = 'default',
+        bg = {1,1,1},
+        c2c = {-1,-1,0},
+        roo = 50,
+        aac = 2.5,
+        roll = 45,
+        lights = 'CAD',
+        crossection = {
+            normal = {-1,-1,-1},
+            transparent = true
+        },
+        nodes = {
+            {
+                name = 'xlabel',
+                visible = false
+            },
+            {
+                name = 'ylabel',
+                opacity = 0.5
+            },
+            {
+                name = 'zlabel',
+                rendermode = 'Wireframe'
+            }
+        }
+    }
+\stopluaparameterset
+
+\useexternalfigure
+  [cloudq]
+  [cloudq.u3d]
+  [width=0.7\textwidth,
+   height=.7\textwidth,
+   display=u3d:myset:display:1,
+   controls=u3d:myset:controls:1]
+
+\useexternalfigure
+  [axes]
+  [axes.u3d]
+  [width=0.7\textwidth,
+   height=.7\textwidth,
+   controls=u3d:myset:controls:1]
+
+\startluaparameterset[u3d:myset:display:2]
+    toolbar = true,
+    preview = 'cloudq.png'
+\stopluaparameterset
+
+\startluaparameterset[u3d:myset:display:3]
+    toolbar = true,
+    tree    = false,
+    preview = 'axes.png'
+\stopluaparameterset
+
+\startluaparameterset[u3d:myset:display:4]
+    toolbar = true,
+    tree    = false,
+    view    = {
+        name   = 'view',
+        bg     = {0.1,0.1,0.1},
+        c2c    = {-1,-1,0},
+        roo    = 50,
+        aac    = 2.5,
+        roll   = 45,
+        lights = 'Red'
+    }
+\stopluaparameterset
+
+\startluaparameterset[u3d:myset:display:5]
+    toolbar = true,
+    tree    = false,
+    view    = 'ortho'
+\stopluaparameterset
+
+\placefigure[here]{none}{\externalfigure[cloudq][display=u3d:myset:display:2]}
+\placefigure[here]{none}{\externalfigure[axes]  [display=u3d:myset:display:3]}
+\placefigure[here]{none}{\externalfigure[axes]  [display=u3d:myset:display:4]}
+\placefigure[here]{none}{\externalfigure[axes]  [display=u3d:myset:display:5,width=0.5\textwidth,height=.5\textwidth]}
+
+\stoptext
diff --git a/tex/context/base/mkxl/back-ini.lmt b/tex/context/base/mkxl/back-ini.lmt
index 922705742..fc91fb31c 100644
--- a/tex/context/base/mkxl/back-ini.lmt
+++ b/tex/context/base/mkxl/back-ini.lmt
@@ -53,7 +53,7 @@ local defaults = {
     tables         = tables,
 }
 
-backends.defaults = defaults
+backends.defaults = defaults -- so, when not in the specific namespace we need to register here (to be checked)
 
 backends.nodeinjections = { }  setmetatableindex(backends.nodeinjections, nodeinjections)
 backends.codeinjections = { }  setmetatableindex(backends.codeinjections, codeinjections)
@@ -62,24 +62,42 @@ backends.tables         = { }  setmetatableindex(backends.tables,         tables
 
 backends.current = "unknown"
 
-function backends.install(what)
+local registered = table.setmetatableindex(function(t,k)
+    local v = {
+        name           = k,
+        nodeinjections = { },
+        codeinjections = { },
+        registrations  = { },
+        tables         = { },
+    }
+    t[k] = v
+    return v
+end)
+
+backends.registered = registered
+
+-- The binding feature is mostly there to prevent side effects of overloading
+-- not so much for performance because there are not that many calls.
+
+function backends.initialize(what)
     if type(what) == "string" then
-        local backend = backends[what]
+        local backend = registered[what]
         if backend then
             if trace then
-                if backend.comment then
-                    report("initializing backend %a, %a",what,backend.comment)
-                else
-                    report("initializing backend %a",what)
-                end
+                report("initializing backend %a",what)
             end
-            backends.current = what
             for category, default in next, defaults do
                 local target = backends[category]
                 local plugin = backend [category]
                 setmetatableindex(plugin, default)
                 setmetatableindex(target, plugin)
             end
+            --
+            backends.current = what
+            -- delayed / out-of-order locals: like lpdf.* (a few forward references)
+            updaters.apply("backends." .. what .. ".latebindings")
+            -- delayed / out-of-order locals: backends.[c|n]odeinjections.* (not all, only critical ones)
+            updaters.apply("backends.injections.latebindings")
         elseif trace then
             report("no backend named %a",what)
         end
@@ -88,11 +106,7 @@ end
 
 statistics.register("used backend", function()
     local bc = backends.current
-    if bc ~= "unknown" then
-        return format("%s (%s)",bc,backends[bc].comment or "no comment")
-    else
-        return nil
-    end
+    return bc ~= "unknown" and bc or nil
 end)
 
 -- can best be here
diff --git a/tex/context/base/mkxl/back-lua.lmt b/tex/context/base/mkxl/back-lua.lmt
deleted file mode 100644
index 9204650ea..000000000
--- a/tex/context/base/mkxl/back-lua.lmt
+++ /dev/null
@@ -1,372 +0,0 @@
-if not modules then modules = { } end modules ['back-lua'] = {
-    version   = 1.001,
-    optimize  = true,
-    comment   = "companion to lpdf-ini.mkiv",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
--- we can remap fonts
-
-local fontproperties    = fonts.hashes.properties
-local fontparameters    = fonts.hashes.parameters
-local fontshapes        = fonts.hashes.shapes
-
-local starttiming       = statistics.starttiming
-local stoptiming        = statistics.stoptiming
-
-local bpfactor          = number.dimenfactors.bp
-local texgetbox         = tex.getbox
-
-local rulecodes         = nodes.rulecodes
-local normalrule_code   = rulecodes.normal
------ boxrule_code      = rulecodes.box
------ imagerule_code    = rulecodes.image
------ emptyrule_code    = rulecodes.empty
------ userrule_code     = rulecodes.user
------ overrule_code     = rulecodes.over
------ underrule_code    = rulecodes.under
------ fractionrule_code = rulecodes.fraction
------ radicalrule_code  = rulecodes.radical
-local outlinerule_code  = rulecodes.outline
-
--- todo : per instance
-
-local pages     = { }
-local fonts     = { }
-local names     = { }
-local mapping   = { }
-local used      = { }
-local shapes    = { }
-local glyphs    = { }
-local buffer    = { }
-local metadata  = nil
-local b         = 0
-local converter = nil
-
-local compact   = false -- true
-local shapestoo = true
-
-local x, y, d, f, c, w, h, t, r, o
-
-local function reset()
-    buffer = { }
-    b      = 0
-    t      = nil
-    x      = nil
-    y      = nil
-    d      = nil
-    f      = nil
-    c      = nil
-    w      = nil
-    h      = nil
-    r      = nil
-    o      = nil
-end
-
-local function result()
-    return {
-        metadata = metadata,
-        fonts    = fonts,
-        pages    = pages,
-        shapes   = shapes,
-    }
-end
-
--- actions
-
-local function outputfilename(driver)
-    return tex.jobname .. "-output.lua"
-end
-
-local function save() -- might become a driver function that already is plugged into stopactions
-    local filename = outputfilename()
-    drivers.report("saving result in %a",filename)
-    starttiming(drivers)
-    local data = result()
-    if data then
-        io.savedata(filename,table.serialize(data))
-    end
-    stoptiming(drivers)
-end
-
-local function prepare(driver)
-    converter = drivers.converters.lmtx
-    luatex.registerstopactions(1,function()
-        save()
-    end)
-end
-
-local function initialize(driver,details)
-    reset()
-end
-
-local function finalize(driver,details)
-    local n = details.pagenumber
-    local b = details.boundingbox
-    pages[n] = {
-        number      = n,
-        content     = buffer,
-        boundingbox = {
-            b[1] * bpfactor,
-            b[2] * bpfactor,
-            b[3] * bpfactor,
-            b[4] * bpfactor,
-        },
-    }
-    if not metadata then
-        -- this has to happen while we're still running tex because we do
-        -- prerolls
-        local identity = interactions.general.getidentity()
-        local jobname  = environment.jobname or tex.jobname or "unknown"
-        metadata = {
-            unit     = "bp",
-            jobname  = jobname,
-            title    = identity.title,
-            subject  = identity.subject,
-            author   = identity.author,
-            keywords = identity.keywords,
-            time     = os.date("%Y-%m-%d %H:%M"),
-            engine   = environment.luatexengine .. " " .. environment.luatexversion,
-            context  = environment.version,
-        }
-    end
-end
-
-local function wrapup(driver)
-end
-
-local function cleanup(driver)
-    reset()
-end
-
-local function convert(driver,boxnumber,pagenumber)
-    converter(driver,texgetbox(boxnumber),"page",pagenumber)
-end
-
--- flushers
-
-local function updatefontstate(id)
-    if not mapping[id] then
-        local fn = #fonts + 1
-        mapping[id] = fn
-        local properties = fontproperties[id]
-        local parameters = fontparameters[id]
-        local filename   = file.basename(properties.filename)
-        local fontname   = properties.fullname or properties.fontname
-        if shapestoo then
-            if not names[fontname] then
-                local sn = #shapes+1
-                names[fontname] = sn
-                shapes[sn] = { }
-                glyphs[sn] = fontshapes[id].glyphs
-            end
-        end
-        fonts[fn] = {
-            filename = filename,
-            name     = fontname,
-            size     = parameters.size * bpfactor,
-            shapes   = shapestoo and names[fontname] or nil,
-        }
-    end
-end
-
-local function flushcharacter(current, pos_h, pos_v, pos_r, font, char)
-    local fnt = mapping[font]
-    b = b + 1
-    buffer[b] = {
-        t = "glyph" ~= t and "glyph" or nil,
-        f = font    ~= f and fnt or nil,
-        c = char    ~= c and char or nil,
-        x = pos_h   ~= x and (pos_h * bpfactor) or nil,
-        y = pos_v   ~= y and (pos_v * bpfactor) or nil,
-        d = pos_r   ~= d and (pos_r == 1 and "r2l" or "l2r") or nil,
-    }
-    t = "glyph"
-    f = font
-    c = char
-    x = pos_h
-    y = pos_v
-    d = pos_r
-    if shapestoo then
-        -- can be sped up if needed
-        local sn = fonts[fnt].shapes
-        local shp = shapes[sn]
-        if not shp[char] then
-            shp[char] = glyphs[sn][char]
-        end
-    end
-end
-
-local function flush_rule(current, pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o)
-    b = b + 1
-    buffer[b] = {
-        t = "rule" ~= t and "rule" or nil,
-        r = rule_s ~= r and rule_s or nil,
-        o = rule_s == "outline" and rule_o ~= o and (rule_o * bpfactor) or nil,
-        w = size_h ~= w and (size_h * bpfactor) or nil,
-        h = size_v ~= h and (size_v * bpfactor) or nil,
-        x = pos_h  ~= x and (pos_h  * bpfactor) or nil,
-        y = pos_v  ~= y and (pos_v  * bpfactor) or nil,
-        d = pos_r  ~= d and (pos_r == 1 and "r2l" or "l2r") or nil,
-    }
-    t = "rule"
-    w = size_h
-    h = size_v
-    x = pos_h
-    y = pos_v
-    d = pos_r
-end
-
-local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v, subtype)
-    local rule_s, rule_o
-    if subtype == normalrule_code then
-        rule_s = normal_rule_code
-    elseif subtype == outlinerule_code then
-        rule_s = outline_rule_code
-        rule_o = getdata(current)
-    else
-        return
-    end
-    return flush_rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o)
-end
-
-local function flushsimplerule(pos_h, pos_v, pos_r, size_h, size_v)
-    return flush_rule(false,pos_h,pos_v,pos_r,size_h,size_v,normalrule_code,nil)
-end
-
-local function flushspecialrule(pos_h, pos_v, pos_r, w, h, d, l, outline)
-    return flush_rule(false,pos_h,pos_v-d,pos_r,w,h+d,outline and outlinerule_code or normalrule_code)
-end
-
--- file stuff too
--- todo: default flushers
--- also color (via hash)
-
--- installer
-
-drivers.install {
-    name    = "lua",
-    actions = {
-        prepare         = prepare,
-        initialize      = initialize,
-        finalize        = finalize,
-        wrapup          = wrapup,
-        cleanup         = cleanup,
-        convert         = convert,
-        outputfilename  = outputfilename,
-    },
-    flushers = {
-        updatefontstate = updatefontstate,
-        character       = flushcharacter,
-        rule            = flushrule,
-        simplerule      = flushsimplerule,
-        specialrule     = flushspecialrule,
-    }
-}
-
--- actions
-
-local function outputfilename(driver)
-    return tex.jobname .. "-output.json"
-end
-
-local function save() -- might become a driver function that already is plugged into stopactions
-    local filename = outputfilename()
-    drivers.report("saving result in %a",filename)
-    starttiming(drivers)
-    local data = result()
-    if data then
-        if not utilities.json then
-            require("util-jsn")
-        end
-        io.savedata(filename,utilities.json.tostring(data,not compact))
-    end
-    stoptiming(drivers)
-end
-
-local function prepare(driver)
-    converter = drivers.converters.lmtx
-    luatex.registerstopactions(1,function()
-        save()
-    end)
-end
-
--- installer
-
-drivers.install {
-    name    = "json",
-    actions = {
-        prepare         = prepare,
-        wrapup          = wrapup,
-        cleanup         = cleanup,
-        --
-        initialize      = initialize,
-        convert         = convert,
-        finalize        = finalize,
-        --
-        outputfilename  = outputfilename,
-    },
-    flushers = {
-        updatefontstate = updatefontstate,
-        character       = flushcharacter,
-        rule            = flushrule,
-        simplerule      = flushsimplerule,
-        specialrule     = flushspecialrule,
-        setstate        = function() end,
-    }
-}
-
--- actions
-
-local function outputfilename(driver)
-    return tex.jobname .. "-output.js"
-end
-
-local function save() -- might become a driver function that already is plugged into stopactions
-    local filename = outputfilename()
-    drivers.report("saving result in %a",filename)
-    starttiming(drivers)
-    local data = result()
-    if data then
-        if not utilities.json then
-            require("util-jsn")
-        end
-        io.savedata(filename,
-            "const JSON_CONTEXT = JSON.parse ( `" ..
-            utilities.json.tostring(data,not compact) ..
-            "` ) ;\n"
-        )
-    end
-    stoptiming(drivers)
-end
-
-local function prepare(driver)
-    converter = drivers.converters.lmtx
-    luatex.registerstopactions(1,function()
-        save()
-    end)
-end
-
--- installer
-
-drivers.install {
-    name    = "js",
-    actions = {
-        prepare         = prepare,
-        initialize      = initialize,
-        finalize        = finalize,
-        wrapup          = wrapup,
-        cleanup         = cleanup,
-        convert         = convert,
-        outputfilename  = outputfilename,
-    },
-    flushers = {
-        updatefontstate = updatefontstate,
-        character       = flushcharacter,
-        rule            = flushrule,
-        simplerule      = flushsimplerule,
-        specialrule     = flushspecialrule,
-    }
-}
diff --git a/tex/context/base/mkxl/back-lua.mkxl b/tex/context/base/mkxl/back-lua.mkxl
deleted file mode 100644
index 0fb1bcc88..000000000
--- a/tex/context/base/mkxl/back-lua.mkxl
+++ /dev/null
@@ -1,16 +0,0 @@
-%D \module
-%D   [       file=back-lua,
-%D        version=2018.07.26,
-%D          title=\CONTEXT\ Backend Macros,
-%D       subtitle=\LUA,
-%D         author=Hans Hagen,
-%D           date=\currentdate,
-%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-\registerctxluafile{back-lua}{autosuffix,optimize}
-
-\endinput
diff --git a/tex/context/base/mkxl/back-mps.lmt b/tex/context/base/mkxl/back-mps.lmt
deleted file mode 100644
index 2da19ed87..000000000
--- a/tex/context/base/mkxl/back-mps.lmt
+++ /dev/null
@@ -1,212 +0,0 @@
-if not modules then modules = { } end modules ['back-mps'] = {
-    version   = 1.001,
-    optimize  = true,
-    comment   = "companion to lpdf-ini.mkiv",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-local fontproperties    = fonts.hashes.properties
-local fontparameters    = fonts.hashes.parameters
-
-local starttiming       = statistics.starttiming
-local stoptiming        = statistics.stoptiming
-
-local bpfactor          = number.dimenfactors.bp
-local texgetbox         = tex.getbox
-local formatters        = string.formatters
-
-local rulecodes         = nodes.rulecodes
-local normalrule_code   = rulecodes.normal
------ boxrule_code      = rulecodes.box
------ imagerule_code    = rulecodes.image
------ emptyrule_code    = rulecodes.empty
------ userrule_code     = rulecodes.user
------ overrule_code     = rulecodes.over
------ underrule_code    = rulecodes.under
------ fractionrule_code = rulecodes.fraction
------ radicalrule_code  = rulecodes.radical
-local outlinerule_code  = rulecodes.outline
-
-local fonts     = { }
-local pages     = { }
-local buffer    = { }
-local b         = 0
-local converter = nil
-
-local function reset()
-    buffer = { }
-    b      = 0
-end
-
--- todo: high efficient helpers:
-
-local f_font    = formatters[ "\\definefont[%s][file:%s*none @ %sbp]\n" ]
-
-local f_glyph   = formatters[ [[draw textext.drt("\%s\char%i\relax") shifted (%N,%N);]] ]
-local f_rule    = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
-local f_outline = formatters[ [[draw unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
-
--- actions
-
-local function outputfilename(driver)
-    return tex.jobname .. "-output.tex"
-end
-
-local function save() -- might become a driver function that already is plugged into stopactions
-    starttiming(drivers)
-    if #pages > 0 then
-        local filename = outputfilename()
-        drivers.report("saving result in %a",filename)
-        reset()
-        b = b + 1
-        buffer[b] = "\\starttext\n"
-        for k, v in table.sortedhash(fonts) do
-            b = b + 1
-            buffer[b] = f_font(v.name,v.filename,v.size)
-        end
-        for i=1,#pages do
-            b = b + 1
-            buffer[b] = pages[i]
-        end
-        b = b + 1
-        buffer[b] = "\\stoptext\n"
-        io.savedata(filename,table.concat(buffer,"",1,b))
-    end
-    stoptiming(drivers)
-end
-
-local function prepare(driver)
-    converter = drivers.converters.lmtx
-    luatex.registerstopactions(1,function()
-        save()
-    end)
-end
-
-local function initialize(driver,details)
-    reset()
-    b = b + 1
-    buffer[b] = "\n\\startMPpage"
-end
-
-local function finalize(driver,details)
-    b = b + 1
-    buffer[b] = "\\stopMPpage\n"
-    pages[details.pagenumber] = table.concat(buffer,"\n",1,b)
-end
-
-local function wrapup(driver)
-end
-
-local function cleanup(driver)
-    reset()
-end
-
-local function convert(driver,boxnumber,pagenumber)
-    converter(driver,texgetbox(boxnumber),"page",pagenumber)
-end
-
--- flushers
-
-local last
-
-local function updatefontstate(id)
-    if fonts[id] then
-        last = fonts[id].name
-    else
-        last = "MPSfont" .. converters.Characters(id)
-        fonts[id] = {
-            filename = file.basename(fontproperties[id].filename),
-            size     = fontparameters[id].size * bpfactor,
-            name     = last,
-        }
-    end
-end
-
-local function flushcharacter(current, pos_h, pos_v, pos_r, font, char)
-    b = b + 1
-    buffer[b] = f_glyph(last,char,pos_h*bpfactor,pos_v*bpfactor)
-end
-
-local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v, subtype)
-    if subtype == normalrule_code then
-        b = b + 1
-        buffer[b] = f_rule(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor)
-    elseif subtype == outlinerule_code then
-        b = b + 1
-        buffer[b] = f_outline(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor)
-    end
-end
-
-local function flushsimplerule(pos_h, pos_v, pos_r, size_h, size_v)
-    flushrule(false,pos_h,pos_v,pos_r,size_h,size_v,normalrule_code)
-end
-
-local function flushspecialrule(pos_h, pos_v, pos_r, w, h, d, l, outline)
-    flushrule(false,pos_h,pos_v-d,pos_r,w,h+d,outline and outlinerule_code or normalrule_code)
-end
-
--- installer
-
-drivers.install {
-    name    = "mps",
-    actions = {
-        prepare         = prepare,
-        initialize      = initialize,
-        finalize        = finalize,
-        wrapup          = wrapup,
-        cleanup         = cleanup,
-        convert         = convert,
-        outputfilename  = outputfilename,
-    },
-    flushers = {
-        updatefontstate = updatefontstate,
-        character       = flushcharacter,
-        rule            = flushrule,
-        simplerule      = flushsimplerule,
-        specialrule     = flushspecialrule,
-    }
-}
-
--- extras
-
--- if not mp then
---     return
--- end
---
--- local mpprint    = mp.print
--- local formatters = string.formatters
---
--- local f_glyph = formatters[ [[draw textext.drt("\setfontid%i\relax\char%i\relax") shifted (%N,%N);]] ]
--- local f_rule  = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
---
--- local current = nil
--- local size    = 0
---
--- function mp.place_buffermake(box)
---     drivers.convert("mps",box)
---     current = drivers.action("mps","fetch")
---     size    = #current
--- end
---
--- function mp.place_buffersize()
---     mpprint(size)
--- end
---
--- function mp.place_bufferslot(i)
---     if i > 0 and i <= size then
---         local b = buffer[i]
---         local t = b[1]
---         if t == "glyph" then
---             mpprint(f_glyph(b[2],b[3],b[4]*bpfactor,b[5]*bpfactor))
---         elseif t == "rule" then
---             mpprint(f_rule(b[2]*bpfactor,b[3]*bpfactor,b[4]*bpfactor,b[5]*bpfactor))
---         end
---     end
--- end
---
--- function mp.place_bufferwipe()
---     current = nil
---     size    = 0
--- end
diff --git a/tex/context/base/mkxl/back-mps.mkxl b/tex/context/base/mkxl/back-mps.mkxl
deleted file mode 100644
index d4d428d42..000000000
--- a/tex/context/base/mkxl/back-mps.mkxl
+++ /dev/null
@@ -1,16 +0,0 @@
-%D \module
-%D   [       file=back-mps,
-%D        version=2018.07.26,
-%D          title=\CONTEXT\ Backend Macros,
-%D       subtitle=\METAPOST,
-%D         author=Hans Hagen,
-%D           date=\currentdate,
-%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-\registerctxluafile{back-mps}{autosuffix,optimize}
-
-\endinput
diff --git a/tex/context/base/mkxl/back-pdf.lmt b/tex/context/base/mkxl/back-pdf.lmt
deleted file mode 100644
index fa564a195..000000000
--- a/tex/context/base/mkxl/back-pdf.lmt
+++ /dev/null
@@ -1,50 +0,0 @@
-if not modules then modules = { } end modules ['back-pdf'] = {
-    version   = 1.001,
-    comment   = "companion to back-pdf.mkiv",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
--- We hide the pdf table from users so that we can guarantee no interference with
--- the way we manage resources, info, etc. Users should use the \type {lpdf}
--- interface instead. If needed I will provide replacement functionality.
-
-local setmetatableindex = table.setmetatableindex
-
-local pdfsetcompression  = lpdf.setcompression
-local pdfimmediateobject = lpdf.immediateobject
-
-interfaces.implement {
-    name      = "setpdfcompression",
-    arguments = { "integer", "integer" },
-    actions   = function(...) pdfsetcompression(...) end,
-}
-
-do
-
-    local dummy  = function() end
-    local report = logs.reporter("backend")
-
-    local function unavailable(t,k)
-        report("calling unavailable pdf.%s function",k)
-        t[k] = dummy
-        return dummy
-    end
-
-    updaters.register("backend.update",function()
-        --
-        -- For now we keep this for tikz. If really needed some more can be made
-        -- accessible but it has to happen in a controlled way then, for instance
-        -- by first loading or enabling some compatibility layer so that we can
-        -- trace possible interferences.
-        --
-        pdf = {
-            immediateobj = pdfimmediateobject
-        }
-        setmetatableindex(pdf,unavailable)
-    end)
-
-end
-
-backends.install("pdf")
diff --git a/tex/context/base/mkxl/back-pdf.mkxl b/tex/context/base/mkxl/back-pdf.mkxl
deleted file mode 100644
index d8b5bd6ee..000000000
--- a/tex/context/base/mkxl/back-pdf.mkxl
+++ /dev/null
@@ -1,161 +0,0 @@
-%D \module
-%D   [       file=back-pdf,
-%D        version=2009.04.15,
-%D          title=\CONTEXT\ Backend Macros,
-%D       subtitle=\PDF,
-%D         author=Hans Hagen,
-%D           date=\currentdate,
-%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-%D The less there is here, the better. After a decade it is time to remove the \type
-%D {\pdf*} ones completely. For the moment I keep them commented but even that will
-%D go away.
-
-%D Todo: a few delayed binding left:
-
-% ./lpdf-ini.lmt : reserve | immediate | positions | matrix | pos | fontobject
-% ./lpdf-lmt.lmt : fontname | object | boxresources
-% ./lpdf-rul.lmt : mp stuff
-% ./back-res.lmt : boxresources
-
-\writestatus{loading}{ConTeXt Backend Macros / PDF}
-
-\registerctxluafile{lpdf-ini}{autosuffix}
-\registerctxluafile{lpdf-lmt}{autosuffix}
-\registerctxluafile{lpdf-col}{autosuffix}
-\registerctxluafile{lpdf-xmp}{autosuffix}
-\registerctxluafile{lpdf-ano}{autosuffix}
-\registerctxluafile{lpdf-res}{autosuffix}
-\registerctxluafile{lpdf-mis}{autosuffix}
-\registerctxluafile{lpdf-ren}{autosuffix}
-\registerctxluafile{lpdf-grp}{autosuffix}
-\registerctxluafile{lpdf-wid}{autosuffix}
-\registerctxluafile{lpdf-fld}{autosuffix}
-%registerctxluafile{lpdf-mov}{autosuffix}
-\registerctxluafile{lpdf-u3d}{autosuffix} % this will become a module
-%registerctxluafile{lpdf-swf}{} % this will become a module
-\registerctxluafile{lpdf-tag}{autosuffix}
-\registerctxluafile{lpdf-fmt}{autosuffix}
-\registerctxluafile{lpdf-pde}{autosuffix}
-\registerctxluafile{lpdf-img}{autosuffix}
-\registerctxluafile{lpdf-epa}{autosuffix}
-\registerctxluafile{lpdf-emb}{autosuffix}
-\registerctxluafile{lpdf-fnt}{autosuffix}
-\registerctxluafile{lpdf-rul}{autosuffix}
-
-\registerctxluafile{back-pdp}{autosuffix}
-\registerctxluafile{back-pdf}{autosuffix} % some code will move to lpdf-*
-
-\loadmkxlfile{back-u3d} % this will become a module
-%loadmkxlfile{back-swf} % this will become a module
-
-\unprotect
-
-%D We will minimize the number of calls to \PDF\ specific primitives and delegate
-%D all management and injection of code to the backend.
-%D
-%D Because we do a lot in \LUA\ and don't want interferences, we nil most of the
-%D \PDFTEX\ primitives. Of course one can always use the \type {\pdfvariable},
-%D \type {\pdfextension} and \type {\pdffeedback} primitives but it will probably
-%D have bad side effects. We fake them as primitives which is why they are
-%D defined as untraced.
-
-% \pdfextension % defined in lua
-% \pdffeedback  % idem
-% \pdfvariable  % idem
-% \pdfliteral   % idem
-% \pdfobj       % idem
-% \pdflastobj   % idem
-% \pdfrefobj    % idem
-
-\untraced\permanent\protected\def\pdfrestore  {\pdfextension restore}
-\untraced\permanent\protected\def\pdfsave     {\pdfextension save}
-\untraced\permanent\protected\def\pdfsetmatrix{\pdfextension setmatrix}
-
-\untraced\permanent\def\pdfxform              {\saveboxresource}
-\untraced\permanent\def\pdflastxform          {\lastsavedboxresourceindex}
-\untraced\permanent\def\pdfrefxform           {\useboxresource}
-
-%D This is also needed for tikz:
-
-\ifdefined\pdfsavepos\else
-    \untraced\permanent\def\pdfsavepos {\savepos }
-    \untraced\permanent\def\pdflastxpos{\lastxpos}
-    \untraced\permanent\def\pdflastypos{\lastypos}
-\fi
-
-%D Here are quick and dirty compression flippers, mostly used when testing something
-%D as one can best stick to the defaults that also adapt to specific standards.
-
-\untraced\permanent\protected\def\nopdfcompression        {\clf_setpdfcompression\zerocount\zerocount}
-\untraced\permanent\protected\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree}
-\untraced\permanent\protected\def\maximumpdfcompression   {\clf_setpdfcompression\plusnine \plusnine }
-\untraced\permanent\protected\def\normalpdfcompression    {\clf_setpdfcompression\plusthree\plusthree}
-
-%D PDF/X (maybe combine the two lua calls)
-
-\setupbackend
-  [xmpfile=]
-
-\appendtoks
-    \edef\p_file{\backendparameter{xmpfile}}%
-    \ifempty\p_file\else
-      \clf_setxmpfile{\p_file}%
-    \fi
-\to \everysetupbackend
-
-%D This will change:
-
-\appendtoks
-    \clf_setformat
-         format  {\backendparameter\c!format}%
-         level   {\backendparameter\c!level}%
-         option  {\backendparameter\c!option}%
-         profile {\backendparameter\c!profile}%
-         intent  {\backendparameter\c!intent}%
-         file    {\backendparameter\c!file}%
-    \relax
-\to \everysetupbackend
-
-%D These are the only official methods to add stuff to the resources. If more is
-%D needed for third party low level code, it can be added.
-
-% \pdfbackendsetcatalog       #1#2 % defined in lua
-% \pdfbackendsetinfo          #1#2 % idem
-% \pdfbackendsetname          #1#2 % idem
-%
-% \pdfbackendsetpageattribute #1#2 % idem
-% \pdfbackendsetpagesattribute#1#2 % idem
-% \pdfbackendsetpageresource  #1#2 % idem
-%
-% \pdfbackendsetextgstate     #1#2 % idem
-% \pdfbackendsetcolorspace    #1#2 % idem
-% \pdfbackendsetpattern       #1#2 % idem
-% \pdfbackendsetshade         #1#2 % idem
-%
-% \pdfbackendcurrentresources      %  idem, expandable
-% \pdfcolor                     #1 %  idem, expandable
-
-%D This is a temporary hack that will be removed, improved or somehow can become
-%D default.
-
-\permanent\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]}
-
-%D Just in case one needs this \unknown:
-%D
-%D \starttyping
-%D text \pdfbackendactualtext{Meier}{Müller} text
-%D \stoptyping
-
-\untraced\permanent\protected\def\pdfbackendactualtext#1#2% not interfaced
-  {\clf_startactualtext{#2}%
-   #1%
-   \clf_stopactualtext}
-
-\aliased\let\pdfactualtext\pdfbackendactualtext
-
-\protect \endinput
diff --git a/tex/context/base/mkxl/back-pdp.lmt b/tex/context/base/mkxl/back-pdp.lmt
deleted file mode 100644
index 5c786d53e..000000000
--- a/tex/context/base/mkxl/back-pdp.lmt
+++ /dev/null
@@ -1,289 +0,0 @@
-if not modules then modules = { } end modules ['back-pdp'] = {
-    version   = 1.001,
-    comment   = "companion to lpdf-ini.mkiv",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
--- This is temporary ... awaiting a better test .. basically we can
--- always use this: pdf primitives.
-
-local context = context
-local lpdf    = lpdf
-
-local pdfreserveobject = lpdf.reserveobject
-local pdfcompresslevel = lpdf.compresslevel
-local pdfobject        = lpdf.object
-local pdfpagereference = lpdf.pagereference
-local pdfgetxformname  = lpdf.getxformname
-local pdfminorversion  = lpdf.minorversion
-local pdfmajorversion  = lpdf.majorversion
-
-local tokenscanners    = tokens.scanners
-local scanword         = tokenscanners.word
-local scankeyword      = tokenscanners.keyword
-local scanstring       = tokenscanners.string
-local scaninteger      = tokenscanners.integer
-local scanwhd          = tokenscanners.whd
-
-local values           = tokens.values
-local dimension_value  = values.dimension
-local cardinal_value   = values.cardinal
-
-local immediate_code   = tex.flagcodes.immediate
-
-local trace            = false  trackers.register("backend", function(v) trace = v end)
-local report           = logs.reporter("backend")
-
-local nodepool         = nodes.pool
-local newliteral       = nodepool.literal
-local newsave          = nodepool.save
-local newrestore       = nodepool.restore
-local newsetmatrix     = nodepool.setmatrix
-
-local implement        = interfaces.implement
-local constants        = interfaces.constants
-local variables        = interfaces.variables
-
--- literals
-
-local function pdf_literal()
-    context(newliteral(scanword() or "origin",scanstring()))
-end
-
--- objects
-
-local lastobjnum = 0
-
-local function pdf_obj(prefix)
-    if scankeyword("reserveobjnum") then
-        lastobjnum = pdfreserveobject()
-        if trace then
-            report("\\pdfobj reserveobjnum: object %i",lastobjnum)
-        end
-    else
-        local immediate    = prefix and (prefix & immediate_code) ~= 0 -- was just "true"
-        local objnum       = scankeyword("useobjnum") and scaninteger() or pdfreserveobject()
-        local uncompress   = scankeyword("uncompressed") or pdfcompresslevel() == 0
-        local streamobject = scankeyword("stream")
-        local attributes   = scankeyword("attr") and scanstring() or nil
-        local fileobject   = scankeyword("file")
-        local content      = scanstring()
-        local object = streamobject and {
-            type          = "stream",
-            objnum        = objnum,
-            immediate     = immediate,
-            attr          = attributes,
-            compresslevel = uncompress and 0 or nil,
-        } or {
-            type          = "raw",
-            objnum        = objnum,
-            immediate     = immediate,
-        }
-        if fileobject then
-            object.file = content
-         -- object.filename = content
-        else
-            object.string = content
-        end
-        pdfobject(object)
-        lastobjnum = objnum
-        if trace then
-            report("\\pdfobj: object %i",lastobjnum)
-        end
-    end
-end
-
-local function pdf_lastobj()
-    if trace then
-        report("\\lastobj: object %i",lastobjnum)
-    end
-    return cardinal_value, lastobjnum
-end
-
-local function pdf_pagereference()
-    return cardinal_value, pdfpagereference()
-end
-
-local function pdf_refobj()
-    local objnum = scaninteger()
-    if trace then
-        report("\\refobj: object %i (todo)",objnum)
-    end
-end
-
--- annotations
-
-local lastobjnum = 0
-
-local function pdf_annot()
-    if scankeyword("reserveobjnum") then
-        lastobjnum = pdfreserveobject()
-        if trace then
-            report("\\pdfannot reserveobjnum: object %i",lastobjnum)
-        end
-    else
-        local width  = false
-        local height = false
-        local depth  = false
-        local data   = false
-        local object = false
-        local attr   = false
-        --
-        if scankeyword("useobjnum") then
-            object = scancount()
-            report("\\pdfannot useobjectnum is not (yet) supported")
-        end
-        local width, height, depth = scanwhd()
-        if scankeyword("attr") then
-            attr = scanstring()
-        end
-        data = scanstring()
-        context(backends.nodeinjections.annotation(width or 0,height or 0,depth or 0,data or ""))
-    end
-end
-
-local function pdf_dest()
-    local name   = false
-    local zoom   = false
-    local view   = false
-    local width  = false
-    local height = false
-    local depth  = false
-    if scankeyword("num") then
-        report("\\pdfdest num is not (yet) supported")
-    elseif scankeyword("name") then
-        name = scanstring()
-    end
-    if scankeyword("xyz") then
-        view = "xyz"
-        if scankeyword("zoom") then
-            report("\\pdfdest zoom is ignored")
-            zoom = scancount() -- will be divided by 1000 in the backend
-        end
-    elseif scankeyword("fitbh") then
-        view = "fitbh"
-    elseif scankeyword("fitbv") then
-        view = "fitbv"
-    elseif scankeyword("fitb") then
-        view = "fitb"
-    elseif scankeyword("fith") then
-        view = "fith"
-    elseif scankeyword("fitv") then
-        view = "fitv"
-    elseif scankeyword("fitr") then
-        view = "fitr"
-        width, height, depth = scanwhd()
-    elseif scankeyword("fit") then
-        view = "fit"
-    end
-    context(backends.nodeinjections.destination(width or 0,height or 0,depth or 0,{ name or "" },view or "fit"))
-end
-
--- management
-
-local function pdf_save()
-    context(newsave())
-end
-
-local function pdf_restore()
-    context(newrestore())
-end
-
-local function pdf_setmatrix()
-    context(newsetmatrix(scanstring()))
-end
-
--- extras
-
--- extensions: literal dest annot save restore setmatrix obj refobj colorstack
--- startlink endlink startthread endthread thread outline glyphtounicode fontattr
--- mapfile mapline includechars catalog info names trailer
-
-local extensions = {
-    literal   = pdf_literal,
-    obj       = pdf_obj,
-    refobj    = pdf_refobj,
-    dest      = pdf_dest,
-    annot     = pdf_annot,
-    save      = pdf_save,
-    restore   = pdf_restore,
-    setmatrix = pdf_setmatrix,
-}
-
-local function pdf_extension()
-    local w = scanword()
-    if w then
-        local e = extensions[w]
-        if e then
-            e()
-        else
-            report("\\pdfextension: unsupported %a",w)
-        end
-    end
-end
-
--- feedbacks: colorstackinit creationdate fontname fontobjnum fontsize lastannot
--- lastlink lastobj pageref retval revision version xformname
-
-local feedbacks = {
-    lastobj   = pdf_lastobj,
-    pageref   = pdf_pagereference,
-    xformname = function() context(pdfgetxformname ()) end,
-}
-
-local function pdf_feedback()
-    local w = scanword()
-    if w then
-        local f = feedbacks[w]
-        if f then
-            f()
-        else
-            report("\\pdffeedback: unsupported %a",w)
-        end
-    end
-end
-
--- variables: (integers:) compresslevel decimaldigits gamma gentounicode
--- ignoreunknownimages imageaddfilename imageapplygamma imagegamma imagehicolor
--- imageresolution inclusioncopyfonts inclusionerrorlevel majorversion minorversion
--- objcompresslevel omitcharset omitcidset pagebox pkfixeddpi pkresolution
--- recompress suppressoptionalinfo uniqueresname (dimensions:) destmargin horigin
--- linkmargin threadmargin vorigin xformmargin (tokenlists:) pageattr pageresources
--- pagesattr pkmode trailerid xformattr xformresources
-
-local variables = {
-    minorversion = function() context(pdfminorversion()) end,
-    majorversion = function() context(pdfmajorversion()) end,
-}
-
-local function pdf_variable()
-    local w = scanword()
-    if w then
-        local f = variables[w]
-        if f then
-            f()
-        else
-            report("\\pdfvariable: unsupported %a",w)
-        end
-    else
-        print("missing variable")
-    end
-end
-
--- kept (also because tikz needs including the pdftex primitives):
-
-implement { name = "pdfextension", actions = pdf_extension, public = true, untraced = true, protected = true }
-implement { name = "pdffeedback",  actions = pdf_feedback,  public = true, untraced = true } -- expandable / todo : value
-implement { name = "pdfvariable",  actions = pdf_variable,  public = true, untraced = true } -- expandable / todo : value
-implement { name = "pdfliteral",   actions = pdf_literal,   public = true, untraced = true, protected = true }
-implement { name = "pdfobj",       actions = pdf_obj,       public = true, usage = "value", protected = true }
-implement { name = "pdflastobj",   actions = pdf_lastobj,   public = true, usage = "value", protected = true }
-implement { name = "pdfrefobj",    actions = pdf_refobj,    public = true, untraced = true, protected = true }
-
---------- { name = "pdfannot",     actions = pdf_annot }
---------- { name = "pdfdest",      actions = pdf_dest }
---------- { name = "pdfsave",      actions = pdf_save }
---------- { name = "pdfrestore",   actions = pdf_restore }
---------- { name = "pdfsetmatrix", actions = pdf_setmatrix }
diff --git a/tex/context/base/mkxl/back-res.lmt b/tex/context/base/mkxl/back-res.lmt
index 3157b37ef..8e5bf3095 100644
--- a/tex/context/base/mkxl/back-res.lmt
+++ b/tex/context/base/mkxl/back-res.lmt
@@ -6,43 +6,49 @@ if not modules then modules = { } end modules ['back-res'] = {
     license   = "see context related readme files"
 }
 
-local context       = context
+local context         = context
 
-local trace         = false  trackers.register("backend", function(v) trace = v end)
-local report        = logs.reporter("backend")
+local trace           = false  trackers.register("backend", function(v) trace = v end)
+local report          = logs.reporter("backend")
 
-local scanners      = tokens.scanners
-local scankeyword   = scanners.keyword
-local scaninteger   = scanners.integer
-local scanstring    = scanners.string
-local scandimension = scanners.dimension
-local scanword      = scanners.word
-local scanwhd       = scanners.whd
+local scanners        = tokens.scanners
+local scankeyword     = scanners.keyword
+local scaninteger     = scanners.integer
+local scanstring      = scanners.string
+local scandimension   = scanners.dimension
+local scanword        = scanners.word
+local scanwhd         = scanners.whd
 
-local implement     = interfaces.implement
-local constants     = interfaces.constants
-local variables     = interfaces.variables
+local implement       = interfaces.implement
+local constants       = interfaces.constants
+local variables       = interfaces.variables
+
+local values          = tokens.values
+----- dimension_value = values.dimension
+local cardinal_value  = values.cardinal
+----- direct_value    = values.direct
 
 -- A box resource has an index. This happens to be an object number due to the pdf
 -- backend but in fact it's an abstraction. This is why we have explicit fetchers.
 -- The internal number (as in \Fm123) is yet another number.
 
-local tex_saveboxresource          = tex.saveboxresource
-local tex_useboxresource           = tex.useboxresource
-local tex_getboxresourcebox        = tex.getboxresourcebox
-local tex_getboxresourcedimensions = tex.getboxresourcedimensions
+-- this will change:
+--
+-- tex.*            : arglist, as in luatex
+-- tex.boxresources : table
+
+local codeinjections = backends.codeinjections
+local nodeinjections = backends.nodeinjections
 
-updaters.register("backend.update",function()
-    tex_saveboxresource          = tex.saveboxresource
-    tex_useboxresource           = tex.useboxresource
-    tex_getboxresourcebox        = tex.getboxresourcebox
-    tex_getboxresourcedimensions = tex.getboxresourcedimensions
-end)
+local savebox = function(...) return codeinjections.saveboxresource(...) end
+local usebox  = function(...) return nodeinjections.useboxresource(...) end
+local getbox  = function(...) return nodeinjections.getboxresourcebox(...) end
+local getwhd  = function(...) return codeinjections.getboxresourcedimensions(...) end
 
-local savebox = function(...) return tex_saveboxresource(...) end
-local usebox  = function(...) return tex_useboxresource(...) end
-local getbox  = function(...) return tex_getboxresourcebox(...) end
-local getwhd  = function(...) return tex_getboxresourcedimensions(...) end
+tex.saveboxresource          = savebox
+tex.useboxresource           = usebox
+tex.getboxresourcebox        = getbox
+tex.getboxresourcedimensions = getwhd
 
 local boxresources = {
     save          = savebox,
@@ -71,9 +77,10 @@ end
 
 local function lastsavedboxresourceindex()
     if trace then
-        report("\\lastsaveboxresource: index %i",lastindex)
+        report("\\lastsaveboxresourceindex: index %i",lastindex)
     end
-    context("%i",lastindex)
+ -- context("%i",lastindex)
+    return cardinal_value, lastindex or 0
 end
 
 local function useboxresource()
@@ -86,9 +93,47 @@ local function useboxresource()
     context(node)
 end
 
-implement { name = "saveboxresource",           actions = saveboxresource }
-implement { name = "lastsavedboxresourceindex", actions = lastsavedboxresourceindex }
-implement { name = "useboxresource",            actions = useboxresource }
+implement {
+    name    = "saveboxresource",
+    actions = saveboxresource,
+}
+implement {
+    name    = "lastsavedboxresourceindex",
+    public  = true,
+    usage   = "value",
+    actions = lastsavedboxresourceindex,
+}
+implement {
+    name    = "useboxresource",
+    actions = useboxresource,
+}
+
+-- used in pack
+
+do
+
+    local nuts                     = nodes.nuts
+    local tonut                    = nodes.tonut
+
+    local setwhd                   = nuts.setwhd
+    local setlist                  = nuts.setlist
+
+    local new_hlist                = nuts.pool.hlist
+
+    function codeinjections.restoreboxresource(index)
+        local hbox = new_hlist()
+        local list, wd, ht, dp = usebox(index)
+        setlist(hbox,tonut(list))
+        setwhd(hbox,wd,ht,dp)
+        return hbox -- so we return a nut !
+    end
+
+    function codeinjections.registerboxresource(n,offset) -- usecollected (arg 3) is a bit of a hack
+        local r = savebox(n,nil,true,true,0,offset or 0) -- direct, todo: accept functions as attr/resources
+        return r
+    end
+
+end
 
 -- image resources
 
@@ -136,11 +181,13 @@ local function saveimageresource()
 end
 
 local function lastsavedimageresourceindex()
-    context("%i",lastindex or 0)
+--     context("%i",lastindex or 0)
+    return cardinal_value, lastindex or 0
 end
 
 local function lastsavedimageresourcepages()
-    context("%i",lastpages or 0) -- todo
+--     context("%i",lastpages or 0) -- todo
+    return cardinal_value, lastpages or 0
 end
 
 local function useimageresource()
@@ -171,7 +218,26 @@ local function useimageresource()
     end
 end
 
-implement { name = "saveimageresource",           actions = saveimageresource }
-implement { name = "lastsavedimageresourceindex", actions = lastsavedimageresourceindex }
-implement { name = "lastsavedimageresourcepages", actions = lastsavedimageresourcepages }
-implement { name = "useimageresource",            actions = useimageresource }
+implement {
+    name    = "saveimageresource",
+    actions = saveimageresource,
+}
+
+implement {
+    name    = "lastsavedimageresourceindex",
+    public  = true,
+    usage   = "value",
+    actions = lastsavedimageresourceindex,
+}
+
+implement {
+    name    = "lastsavedimageresourcepages",
+    public  = true,
+    usage   = "value",
+    actions = lastsavedimageresourcepages,
+}
+
+implement {
+    name    = "useimageresource",
+    actions = useimageresource,
+}
diff --git a/tex/context/base/mkxl/back-res.mkxl b/tex/context/base/mkxl/back-res.mkxl
index 8a18eef99..1febef18d 100644
--- a/tex/context/base/mkxl/back-res.mkxl
+++ b/tex/context/base/mkxl/back-res.mkxl
@@ -23,12 +23,12 @@
 % todo: public implementors (we can update the lua code anyway)
 
 \permanent\protected\def\saveboxresource            {\clf_saveboxresource}
-\permanent\protected\def\lastsavedboxresourceindex  {\numexpr\clf_lastsavedboxresourceindex\relax}
+%permanent\protected\def\lastsavedboxresourceindex  {\numexpr\clf_lastsavedboxresourceindex\relax}
 \permanent\protected\def\useboxresource             {\clf_useboxresource}
 
 \permanent\protected\def\saveimageresource          {\clf_saveimageresource}
-\permanent\protected\def\lastsavedimageresourceindex{\numexpr\clf_lastsavedimageresourceindex\relax}
-\permanent\protected\def\lastsavedimageresourcepages{\numexpr\clf_lastsavedimageresourcepages\relax}
+%permanent\protected\def\lastsavedimageresourceindex{\numexpr\clf_lastsavedimageresourceindex\relax}
+%permanent\protected\def\lastsavedimageresourcepages{\numexpr\clf_lastsavedimageresourcepages\relax}
 \permanent\protected\def\useimageresource           {\clf_useimageresource}
 
 \protect \endinput
diff --git a/tex/context/base/mkxl/back-u3d.mkxl b/tex/context/base/mkxl/back-u3d.mkxl
deleted file mode 100644
index 297dd5545..000000000
--- a/tex/context/base/mkxl/back-u3d.mkxl
+++ /dev/null
@@ -1,158 +0,0 @@
-%D \module
-%D   [       file=back-u3d,
-%D        version=2009.04.15,
-%D          title=\CONTEXT\ Backend Macros,
-%D       subtitle=U3D Experiment,
-%D         author=Hans Hagen,
-%D           date=\currentdate,
-%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-%D This is only a placeholder that demonstrates the usage of u3d resources. The
-%D user interface is rather messy an might be improved. The files and setup is
-%D derived from an example by Michael Vidiassov.
-
-\endinput
-
-\starttext
-
-\startluaparameterset [u3d:myset:controls:1]
-    view = {
-        name = 'default',
-        bg = {1,1,1},
-        mag = 100,
-        coo = {0,0,0},
-        c2c = {0,0,1},
-        rot = {40,0,60},
-        roo = 6,
-        lights = 'CAD'
-    },
-    js = 'cloudq.js'
-\stopluaparameterset
-
-\startluaparameterset [u3d:myset:controls:2]
-    views = {
-        {
-            name = 'AnglePositioning',
-            bg = {1,1,1},
-            azimuth = 45,
-            altitude = 45,
-            roo = 50,
-            aac = 2.5,
-            lights = 'Artwork'
-        },
-        {
-            name = 'RotationPositioning',
-            bg = {1,1,1},
-            rot = {0,45,45},
-            roo = 50,
-            aac = 2.5,
-            lights = 'Artwork'
-        },
-        {
-            name = 'VectorPositioning',
-            bg = {1,0,0},
-            c2c = {1,1,math.sqrt(2)},
-            roo = 50,
-            aac = 2.5,
-            lights = 'CAD'
-        },
-        {
-            name = 'PositionPositioning',
-            bg = {1,0,0},
-            pos = {1+25,1+25,1+50/math.sqrt(2)},
-            aac = 2.5,
-            lights = 'CAD'
-        },
-        {
-            name = 'ortho',
-            bg = {1,1,1},
-            mag = 300,
-            lights = 'CAD',
-            crossection = {}
-        }
-    },
-    view = {
-        name = 'default',
-        bg = {1,1,1},
-        c2c = {-1,-1,0},
-        roo = 50,
-        aac = 2.5,
-        roll = 45,
-        lights = 'CAD',
-        crossection = {
-            normal = {-1,-1,-1},
-            transparent = true
-        },
-        nodes = {
-            {
-                name = 'xlabel',
-                visible = false
-            },
-            {
-                name = 'ylabel',
-                opacity = 0.5
-            },
-            {
-                name = 'zlabel',
-                rendermode = 'Wireframe'
-            }
-        }
-    }
-\stopluaparameterset
-
-\useexternalfigure
-  [cloudq]
-  [cloudq.u3d]
-  [width=0.7\textwidth,
-   height=.7\textwidth,
-   display=u3d:myset:display:1,
-   controls=u3d:myset:controls:1]
-
-\useexternalfigure
-  [axes]
-  [axes.u3d]
-  [width=0.7\textwidth,
-   height=.7\textwidth,
-   controls=u3d:myset:controls:1]
-
-\startluaparameterset[u3d:myset:display:2]
-    toolbar = true,
-    preview = 'cloudq.png'
-\stopluaparameterset
-
-\startluaparameterset[u3d:myset:display:3]
-    toolbar = true,
-    tree    = false,
-    preview = 'axes.png'
-\stopluaparameterset
-
-\startluaparameterset[u3d:myset:display:4]
-    toolbar = true,
-    tree    = false,
-    view    = {
-        name   = 'view',
-        bg     = {0.1,0.1,0.1},
-        c2c    = {-1,-1,0},
-        roo    = 50,
-        aac    = 2.5,
-        roll   = 45,
-        lights = 'Red'
-    }
-\stopluaparameterset
-
-\startluaparameterset[u3d:myset:display:5]
-    toolbar = true,
-    tree    = false,
-    view    = 'ortho'
-\stopluaparameterset
-
-\placefigure[here]{none}{\externalfigure[cloudq][display=u3d:myset:display:2]}
-\placefigure[here]{none}{\externalfigure[axes]  [display=u3d:myset:display:3]}
-\placefigure[here]{none}{\externalfigure[axes]  [display=u3d:myset:display:4]}
-\placefigure[here]{none}{\externalfigure[axes]  [display=u3d:myset:display:5,width=0.5\textwidth,height=.5\textwidth]}
-
-\stoptext
diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl
index e1b48998e..a2edf83a6 100644
--- a/tex/context/base/mkxl/cont-new.mkxl
+++ b/tex/context/base/mkxl/cont-new.mkxl
@@ -13,7 +13,7 @@
 
 % \normalend % uncomment this to get the real base runtime
 
-\newcontextversion{2021.10.15 13:57}
+\newcontextversion{2021.10.18 23:11}
 
 %D This file is loaded at runtime, thereby providing an excellent place for hacks,
 %D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl
index 698a259ef..c227468ae 100644
--- a/tex/context/base/mkxl/context.mkxl
+++ b/tex/context/base/mkxl/context.mkxl
@@ -29,7 +29,7 @@
 %D {YYYY.MM.DD HH:MM} format.
 
 \immutable\edef\contextformat {\jobname}
-\immutable\edef\contextversion{2021.10.15 13:57}
+\immutable\edef\contextversion{2021.10.18 23:11}
 
 %overloadmode 1 % check frozen / warning
 %overloadmode 2 % check frozen / error
@@ -151,6 +151,8 @@
 \loadmkxlfile{layo-ini}
 
 \loadmkxlfile{node-ini}
+\loadmkxlfile{node-ext}
+\loadmkxlfile{node-syn}
 
 % \loadmkxlfile{cldf-bas} % basics / depends on nodes
 
@@ -158,11 +160,10 @@
 \loadmkxlfile{node-mig}
 %loadmkxlfile{node-pag}
 
-\loadmkxlfile{driv-ini}
+\loadmkxlfile{driv-ini} % after node-ini (ext)
 
 \loadmkxlfile{back-ini}
 \loadmkxlfile{back-res}
-\loadmkxlfile{back-ext}
 
 \loadmkxlfile{cldf-bas} % basics / depends on nodes
 
@@ -563,9 +564,10 @@
 \loadmkxlfile{anch-loc} % for now here (after driver)
 
 \loadmkxlfile{back-exp}
-\loadmkxlfile{back-pdf}
-\loadmkxlfile{back-mps}
-\loadmkxlfile{back-lua}
+
+\loadmkxlfile{back-imp-pdf}
+\loadmkxlfile{back-imp-mps}
+\loadmkxlfile{back-imp-lua}
 
 \loadmkxlfile{mlib-pdf}
 \loadmkxlfile{mlib-pps}
diff --git a/tex/context/base/mkxl/core-def.mkxl b/tex/context/base/mkxl/core-def.mkxl
index 96570bc36..839e9b260 100644
--- a/tex/context/base/mkxl/core-def.mkxl
+++ b/tex/context/base/mkxl/core-def.mkxl
@@ -112,6 +112,7 @@
     \syst_files_load
     % for the moment here (before doc env)
     \setupoutput[pdf]%
+%     \setupoutput[lua]%
     %
     \clf_setdocumentcommandline
     \clf_setdocumentctxfile
diff --git a/tex/context/base/mkxl/driv-ini.lmt b/tex/context/base/mkxl/driv-ini.lmt
index 40b351d84..8b6c2e5ff 100644
--- a/tex/context/base/mkxl/driv-ini.lmt
+++ b/tex/context/base/mkxl/driv-ini.lmt
@@ -65,6 +65,14 @@ local installwhatsits  do
 
     local leaderlevel = 0
     local backends    = backends
+    local trace       = true
+
+    local latelua     = backends.latelua
+    local writeout    = backends.writeout
+    local openout     = backends.openout
+    local closeout    = backends.closeout
+
+    trackers.register("backends.whatsits",function(v) trace = v end)
 
     local function pushleaderlevel()
         leaderlevel = leaderlevel + 1
@@ -75,26 +83,26 @@ local installwhatsits  do
     end
 
     local function flushlatelua(current,h,v)
-        -- Here we assume maganement by the lua function so currently we don't
-        -- check for leaderlevel.
-        return backends.latelua(current,h,v)
+        -- Here we assume management by the lua function so currently we don't
+        -- need to check for leaderlevel and it can even be counterproductive.
+        return latelua(current,h,v)
     end
 
     local function flushwriteout(current)
         if leaderlevel == 0 then
-            backends.writeout(current)
+            writeout(current)
         end
     end
 
     local function flushopenout(current)
         if leaderlevel == 0 then
-            backends.openout(current)
+            openout(current)
         end
     end
 
     local function flushcloseout(current)
         if leaderlevel == 0 then
-            backends.closeout(current)
+            closeout(current)
         end
     end
 
@@ -110,8 +118,6 @@ local installwhatsits  do
 
     local whatsitcodes = nodes.whatsitcodes
 
-    local trace = true  trackers.register("backends.whatsits",function(v) trace = v end)
-
     installwhatsits = function(name,flushers)
 
         -- latelua     : specific
@@ -135,54 +141,13 @@ local installwhatsits  do
             return v
         end
 
-     -- flushers.whatsit = setmetatableindex ( {
-     --     [whatsitcodes.literal]        = flushers.literal,
-     --     [whatsitcodes.latelua]        = flushlatelua,
-     --     [whatsitcodes.userdefined]    = flushuserdefined,
-     --     [whatsitcodes.savepos]        = flushsavepos,
-     --     [whatsitcodes.save]           = flushers.save,
-     --     [whatsitcodes.restore]        = flushers.restore,
-     --     [whatsitcodes.setmatrix]      = flushers.setmatrix,
-     --     [whatsitcodes.open]           = flushopenout,
-     --     [whatsitcodes.close]          = flushcloseout,
-     --     [whatsitcodes.write]          = flushwriteout,
-     --     [whatsitcodes.startmatrix]    = flushers.startmatrix,
-     --     [whatsitcodes.stopmatrix]     = flushers.stopmatrix,
-     --     [whatsitcodes.startscaling]   = flushers.startscaling,
-     --     [whatsitcodes.stopscaling]    = flushers.stopscaling,
-     --     [whatsitcodes.startrotation]  = flushers.startrotation,
-     --     [whatsitcodes.stoprotation]   = flushers.stoprotation,
-     --     [whatsitcodes.startmirroring] = flushers.startmirroring,
-     --     [whatsitcodes.stopmirroring]  = flushers.stopmirroring,
-     --     [whatsitcodes.startclipping]  = flushers.startclipping,
-     --     [whatsitcodes.stopclipping]   = flushers.stopclipping,
-     --     [whatsitcodes.setstate]       = flushers.setstate,
-     -- }, checkagain )
-
-     -- -- sparse
-
-     -- flushers.whatsit = setmetatableindex ( {
-     --     [whatsitcodes.latelua]     = flushlatelua,
-     --     [whatsitcodes.userdefined] = flushuserdefined,
-     --     [whatsitcodes.savepos]     = flushsavepos,
-     --     [whatsitcodes.open]        = flushopenout,
-     --     [whatsitcodes.close]       = flushcloseout,
-     --     [whatsitcodes.write]       = flushwriteout,
-     -- }, checkagain )
-
-        -- -- delayed
+        -- delayed
 
         local whatsit ; whatsit = setmetatableindex ( {
             [whatsitcodes.literal]        = flushers.literal        or function(...) return checkagain(whatsit,whatsitcodes.literal       )(...) end,
-            [whatsitcodes.latelua]        = flushlatelua,
-            [whatsitcodes.userdefined]    = flushuserdefined,
-            [whatsitcodes.savepos]        = flushsavepos,
             [whatsitcodes.save]           = flushers.save           or function(...) return checkagain(whatsit,whatsitcodes.save          )(...) end,
             [whatsitcodes.restore]        = flushers.restore        or function(...) return checkagain(whatsit,whatsitcodes.restore       )(...) end,
             [whatsitcodes.setmatrix]      = flushers.setmatrix      or function(...) return checkagain(whatsit,whatsitcodes.setmatrix     )(...) end,
-            [whatsitcodes.open]           = flushopenout,
-            [whatsitcodes.close]          = flushcloseout,
-            [whatsitcodes.write]          = flushwriteout,
             [whatsitcodes.startmatrix]    = flushers.startmatrix    or function(...) return checkagain(whatsit,whatsitcodes.startmatrix   )(...) end,
             [whatsitcodes.stopmatrix]     = flushers.stopmatrix     or function(...) return checkagain(whatsit,whatsitcodes.stopmatrix    )(...) end,
             [whatsitcodes.startscaling]   = flushers.startscaling   or function(...) return checkagain(whatsit,whatsitcodes.startscaling  )(...) end,
@@ -194,6 +159,13 @@ local installwhatsits  do
             [whatsitcodes.startclipping]  = flushers.startclipping  or function(...) return checkagain(whatsit,whatsitcodes.startclipping )(...) end,
             [whatsitcodes.stopclipping]   = flushers.stopclipping   or function(...) return checkagain(whatsit,whatsitcodes.stopclippin   )(...) end,
             [whatsitcodes.setstate]       = flushers.setstate       or function(...) return checkagain(whatsit,whatsitcodes.setstate      )(...) end,
+            --
+            [whatsitcodes.latelua]        = flushlatelua,
+            [whatsitcodes.userdefined]    = flushuserdefined,
+            [whatsitcodes.savepos]        = flushsavepos,
+            [whatsitcodes.open]           = flushopenout,
+            [whatsitcodes.close]          = flushcloseout,
+            [whatsitcodes.write]          = flushwriteout,
         }, checkagain)
 
         flushers.whatsit = whatsit
@@ -271,15 +243,15 @@ function drivers.enable(name)
             cleanup(currentinstance)
             stoptiming(drivers)
         end
-        currentdriver   = name or "default"
+        currentdriver   = name or "none"
         currentinstance = instances[currentdriver]
         if currentinstance then
-            local actions   = currentinstance.actions
-            prepare         = actions.prepare
-            wrapup          = actions.wrapup
-            cleanup         = actions.cleanup
-            convert         = actions.convert
-            outputfilename  = actions.outputfilename
+            local actions  = currentinstance.actions
+            prepare        = actions.prepare
+            wrapup         = actions.wrapup
+            cleanup        = actions.cleanup
+            convert        = actions.convert
+            outputfilename = actions.outputfilename
             --
             if prepare and not prepared[currentdriver] then
                 starttiming(drivers)
@@ -309,42 +281,6 @@ interfaces.implement {
     actions   = drivers.enable,
 }
 
--- The default driver:
-
-do
-
-    local filename = nil
-
-    drivers.install {
-        name     = "default", -- "pdf"
-        actions  = {
-            convert        = drivers.converters.engine,
-            outputfilename = function(driver)
-                if not filename then
-                    filename = addsuffix(tex.jobname,"pdf")
-                end
-                return filename
-            end,
-        },
-        flushers = {
-            -- we always need this entry
-        },
-    }
-
-end
-
--- No driver:
-
-do
-
-    drivers.install {
-        name     = "none",
-        actions  = { },
-        flushers = { },
-    }
-
-end
-
 do
 
     local function prepare(driver)
@@ -366,10 +302,14 @@ do
 
 end
 
---
-
 setmetatableindex(instances,function() return instances.default end)
 
--- for now:
+-- We default to no driver at all:
+
+drivers.install {
+    name     = "none",
+    actions  = { },
+    flushers = { },
+}
 
-drivers.enable("default")
+drivers.enable("none")
diff --git a/tex/context/base/mkxl/font-tex.lmt b/tex/context/base/mkxl/font-tex.lmt
index c1908dc48..1c3c17a79 100644
--- a/tex/context/base/mkxl/font-tex.lmt
+++ b/tex/context/base/mkxl/font-tex.lmt
@@ -34,7 +34,7 @@ local function makeglyphbox(char,spec)
         width  = b.width,
         height = b.height,
         depth  = b.depth,
-        objnum = tex.saveboxresource(b,nil,nil,true),
+        objnum = tex.boxresources.save(b,nil,nil,true),
     }
 end
 
@@ -95,7 +95,7 @@ function fonts.helpers.setboxdirectly(font,unicode,box) -- hash based on wd/ht/d
             height  = box.height or 0,
             depth   = box.depth  or 0,
             unicode = unicode,
-            objnum  = tex.saveboxresource(box,nil,nil,true),
+            objnum  = tex.boxresources.save(box,nil,nil,true),
         }
         local specification = {
             code = newdata
diff --git a/tex/context/base/mkxl/font-vfc.lmt b/tex/context/base/mkxl/font-vfc.lmt
index 93e6fd4e5..c28b8b988 100644
--- a/tex/context/base/mkxl/font-vfc.lmt
+++ b/tex/context/base/mkxl/font-vfc.lmt
@@ -81,10 +81,26 @@ helpers.commands = utilities.storage.allocate {
     dummy = dummy,
 }
 
+local codeinjections = backends.codeinjections
+local vfstartcolor   = codeinjections.vfstartcolor
+local vfstopcolor    = codeinjections.vfstopcolor
+----- vfliteral      = codeinjections.vfliteral
+
 helpers.vfinjectors = {
-    -- backend specific: startcolor, stopcolor etc
+ -- startcolor = function(h,v,packet) codeinjections.vfstartcolor(h,v,packet) end,
+ -- stopcolor  = function(h,v,packet) codeinjections.vfstartcolor(h,v,packet) end,
+ -- literal    = function(h,v,packet) codeinjections.vfliteral   (h,v,packer) end,
+    startcolor = function(h,v,packet) vfstartcolor(h,v,packet) end,
+    stopcolor  = function(h,v,packet) vfstartcolor(h,v,packet) end,
+ -- literal    = function(h,v,packet) vfliteral   (h,v,packer) end,
 }
 
+updaters.register("backends.injections.latebindings",function()
+    vfstartcolor = backends.codeinjections.vfstartcolor
+    vfstopcolor  = backends.codeinjections.vfstopcolor
+ -- vfliteral    = backends.codeinjections.vfliteral
+end)
+
 -- maybe round()
 
 local defaultline = 16384
diff --git a/tex/context/base/mkxl/grph-epd.lmt b/tex/context/base/mkxl/grph-epd.lmt
new file mode 100644
index 000000000..6f9e44f63
--- /dev/null
+++ b/tex/context/base/mkxl/grph-epd.lmt
@@ -0,0 +1,55 @@
+if not modules then modules = { } end modules ['grph-epd'] = {
+    version   = 1.001,
+    comment   = "companion to grph-epd.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+local variables        = interfaces.variables
+local settings_to_hash = utilities.parsers.settings_to_hash
+local codeinjections   = backends.registered.pdf.codeinjections
+
+local trace  = false  trackers.register("figures.merging", function(v) trace = v end)
+
+local report = logs.reporter("backend","merging")
+
+local function mergegoodies(optionlist)
+    local options = settings_to_hash(optionlist)
+    local yes     = options[variables.yes]
+    local all     = options[variables.all]
+    if next(options) then
+        report("% t",table.sortedkeys(options))
+    end
+    if all or yes or options[variables.reference] then
+        codeinjections.mergereferences()
+    end
+    if all or options[variables.comment] then
+        codeinjections.mergecomments()
+    end
+    if all or yes or options[variables.bookmark] then
+        codeinjections.mergebookmarks()
+    end
+    if all or options[variables.field] then
+        codeinjections.mergefields()
+    end
+    if all or options[variables.layer] then
+        codeinjections.mergeviewerlayers()
+    end
+    codeinjections.flushmergelayer()
+end
+
+function figures.mergegoodies(optionlist)
+    -- todo: we can use runlocal instead
+    context.stepwise(function()
+        -- we use stepwise because we might need to define symbols
+        -- for stamps that have no default appearance
+        mergegoodies(optionlist)
+    end)
+end
+
+interfaces.implement {
+    name      = "figure_mergegoodies",
+    actions   = figures.mergegoodies,
+    arguments = "string"
+}
diff --git a/tex/context/base/mkxl/grph-epd.lua b/tex/context/base/mkxl/grph-epd.lua
new file mode 100644
index 000000000..0993270f1
--- /dev/null
+++ b/tex/context/base/mkxl/grph-epd.lua
@@ -0,0 +1,55 @@
+if not modules then modules = { } end modules ['grph-epd'] = {
+    version   = 1.001,
+    comment   = "companion to grph-epd.mkiv",
+    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+    copyright = "PRAGMA ADE / ConTeXt Development Team",
+    license   = "see context related readme files"
+}
+
+local variables = interfaces.variables
+local settings_to_hash = utilities.parsers.settings_to_hash
+local codeinjections = backends.pdf.codeinjections
+
+local trace  = false  trackers.register("figures.merging", function(v) trace = v end)
+
+local report = logs.reporter("backend","merging")
+
+local function mergegoodies(optionlist)
+    local options = settings_to_hash(optionlist)
+    local yes     = options[variables.yes]
+    local all     = options[variables.all]
+    if next(options) then
+        report("% t",table.sortedkeys(options))
+    end
+    if all or yes or options[variables.reference] then
+        codeinjections.mergereferences()
+    end
+    if all or options[variables.comment] then
+        codeinjections.mergecomments()
+    end
+    if all or yes or options[variables.bookmark] then
+        codeinjections.mergebookmarks()
+    end
+    if all or options[variables.field] then
+        codeinjections.mergefields()
+    end
+    if all or options[variables.layer] then
+        codeinjections.mergeviewerlayers()
+    end
+    codeinjections.flushmergelayer()
+end
+
+function figures.mergegoodies(optionlist)
+    -- todo: we can use runlocal instead
+    context.stepwise(function()
+        -- we use stepwise because we might need to define symbols
+        -- for stamps that have no default appearance
+        mergegoodies(optionlist)
+    end)
+end
+
+interfaces.implement {
+    name      = "figure_mergegoodies",
+    actions   = figures.mergegoodies,
+    arguments = "string"
+}
diff --git a/tex/context/base/mkxl/grph-epd.mkxl b/tex/context/base/mkxl/grph-epd.mkxl
index 7ff9b8675..c8e5cd1c8 100644
--- a/tex/context/base/mkxl/grph-epd.mkxl
+++ b/tex/context/base/mkxl/grph-epd.mkxl
@@ -15,7 +15,7 @@
 
 \unprotect
 
-\registerctxluafile{grph-epd}{}
+\registerctxluafile{grph-epd}{autosuffix}
 
 % hm, this one is globally overloaded
 
diff --git a/tex/context/base/mkxl/grph-inc.lmt b/tex/context/base/mkxl/grph-inc.lmt
index e19b48e49..8c4cb62b3 100644
--- a/tex/context/base/mkxl/grph-inc.lmt
+++ b/tex/context/base/mkxl/grph-inc.lmt
@@ -175,8 +175,8 @@ local imagekeys  = {
 }
 
 local imagesizes = {
-    art   = true, bleed = true,  crop = true,
-    media = true, none  = true,  trim = true,
+    art   = true, bleed = true, crop = true,
+    media = true, none  = true, trim = true,
 }
 
 local imagetypes = { [0] =
@@ -191,26 +191,28 @@ images.keys  = imagekeys
 images.types = imagetypes
 images.sizes = imagesizes
 
+local codeinjections = backends.codeinjections
+
 local function createimage(specification)
-    return backends.codeinjections.newimage(specification)
+    return codeinjections.newimage(specification)
 end
 
 local function copyimage(specification)
-    return backends.codeinjections.copyimage(specification)
+    return codeinjections.copyimage(specification)
 end
 
 local function scanimage(specification)
-    return backends.codeinjections.scanimage(specification)
+    return codeinjections.scanimage(specification)
 end
 
 local function embedimage(specification)
-    -- write the image to file
-    return backends.codeinjections.embedimage(specification)
+   -- write the image to file
+    return codeinjections.embedimage(specification)
 end
 
 local function wrapimage(specification)
     -- create an image rule
-    return backends.codeinjections.wrapimage(specification)
+    return codeinjections.wrapimage(specification)
 end
 
 images.create = createimage
@@ -1002,7 +1004,6 @@ local function locate(request) -- name, format, cache
         return foundname
     end
     --
-    --
     local askedformat = request.format
     if not askedformat or askedformat == "" or askedformat == "unknown" then
         askedformat = file.suffix(askedname) or ""
@@ -1315,7 +1316,6 @@ function figures.identify(data)
         for i=1,#list do
             local identifier = list[i]
             local data = identifier(data)
---             if data and (not data.status and data.status.status > 0) then
             if data and (not data.status and data.status.status > 0) then
                 break
             end
diff --git a/tex/context/base/mkxl/grph-rul.lmt b/tex/context/base/mkxl/grph-rul.lmt
index d8da5f760..50a40155e 100644
--- a/tex/context/base/mkxl/grph-rul.lmt
+++ b/tex/context/base/mkxl/grph-rul.lmt
@@ -29,17 +29,14 @@ local a_colormodel     = attributes.private('colormodel')
 local floor            = math.floor
 local getrandom        = utilities.randomizer.get
 
-do
-
-    local function unsupported() end
-
-    ruleactions.mp     = unsupported
-    ruleactions.fill   = unsupported
-    ruleactions.draw   = unsupported
-    ruleactions.stroke = unsupported
-    ruleactions.box    = unsupported
-
-end
+updaters.register("backends.injections.latebindings",function()
+    local codeinjections = backends.codeinjections
+    ruleactions.mp       = codeinjections.ruleactionmp
+    ruleactions.fill     = codeinjections.ruleactionfill
+    ruleactions.draw     = codeinjections.ruleactiondraw
+    ruleactions.stroke   = codeinjections.ruleactionstroke
+    ruleactions.box      = codeinjections.ruleactionbox
+end)
 
 interfaces.implement {
     name      = "frule",
diff --git a/tex/context/base/mkxl/lpdf-ano.lmt b/tex/context/base/mkxl/lpdf-ano.lmt
index 763822707..85fe050a2 100644
--- a/tex/context/base/mkxl/lpdf-ano.lmt
+++ b/tex/context/base/mkxl/lpdf-ano.lmt
@@ -20,8 +20,6 @@ local lpegmatch = lpeg.match
 local formatters = string.formatters
 local sortedkeys, concat = table.sortedkeys, table.concat
 
-local backends, lpdf = backends, lpdf
-
 local trace_references        = false  trackers.register("references.references",   function(v) trace_references   = v end)
 local trace_destinations      = false  trackers.register("references.destinations", function(v) trace_destinations = v end)
 local trace_bookmarks         = false  trackers.register("references.bookmarks",    function(v) trace_bookmarks    = v end)
@@ -45,9 +43,10 @@ local settings_to_array       = utilities.parsers.settings_to_array
 local allocate                = utilities.storage.allocate
 local setmetatableindex       = table.setmetatableindex
 
-local nodeinjections          = backends.pdf.nodeinjections
-local codeinjections          = backends.pdf.codeinjections
-local registrations           = backends.pdf.registrations
+local pdfbackend              = backends.registered.pdf
+local nodeinjections          = pdfbackend.nodeinjections
+local codeinjections          = pdfbackend.codeinjections
+local registrations           = pdfbackend.registrations
 
 local javascriptcode          = interactions.javascripts.code
 
@@ -74,6 +73,7 @@ local getpos                  = jobpositions.getpos
 local gethpos                 = jobpositions.gethpos
 local getvpos                 = jobpositions.getvpos
 
+local lpdf                    = lpdf
 local pdfdictionary           = lpdf.dictionary
 local pdfarray                = lpdf.array
 local pdfreference            = lpdf.reference
diff --git a/tex/context/base/mkxl/lpdf-col.lmt b/tex/context/base/mkxl/lpdf-col.lmt
index ed6a4fa7b..c1499b75e 100644
--- a/tex/context/base/mkxl/lpdf-col.lmt
+++ b/tex/context/base/mkxl/lpdf-col.lmt
@@ -13,18 +13,19 @@ local concat = table.concat
 local round = math.round
 local formatters = string.formatters
 
-local backends, lpdf, nodes = backends, lpdf, nodes
-
 local allocate                = utilities.storage.allocate
 
-local nodeinjections          = backends.pdf.nodeinjections
-local codeinjections          = backends.pdf.codeinjections
-local registrations           = backends.pdf.registrations
+local pdfbackend              = backends.registered.pdf
+local nodeinjections          = pdfbackend.nodeinjections
+local codeinjections          = pdfbackend.codeinjections
+local registrations           = pdfbackend.registrations
 
+local nodes                   = nodes
 local nodepool                = nodes.nuts.pool
 local register                = nodepool.register
 local setstate                = nodepool.setstate
 
+local lpdf                    = lpdf
 local pdfconstant             = lpdf.constant
 local pdfdictionary           = lpdf.dictionary
 local pdfarray                = lpdf.array
@@ -580,7 +581,7 @@ function lpdf.pdfcolor(attribute) -- bonus, for pgf and friends
     return lpdfcolor(1,attribute)
 end
 
-function lpdf.transparency(ct,default) -- kind of overlaps with transparencycode
+local function lpdftransparency(ct,default) -- kind of overlaps with transparencycode
     -- beware, we need this hack because normally transparencies are not
     -- yet registered and therefore the number is not not known ... we
     -- might use the attribute number itself in the future
@@ -596,6 +597,8 @@ function lpdf.transparency(ct,default) -- kind of overlaps with transparencycode
     end
 end
 
+lpdf.transparency = lpdftransparency
+
 function lpdf.colorvalue(model,ca,default)
     local cv = colorsvalue(ca)
     if cv then
@@ -668,11 +671,10 @@ end
 -- by registering we getconversion for free (ok, at the cost of overhead)
 
 local intransparency = false
-local pdfcolor       = lpdf.color
 
 function lpdf.rgbcode(model,r,g,b)
     if colors.supported then
-        return pdfcolor(model,registercolor(nil,'rgb',r,g,b))
+        return lpdfcolor(model,registercolor(nil,'rgb',r,g,b))
     else
         return ""
     end
@@ -680,7 +682,7 @@ end
 
 function lpdf.cmykcode(model,c,m,y,k)
     if colors.supported then
-        return pdfcolor(model,registercolor(nil,'cmyk',c,m,y,k))
+        return lpdfcolor(model,registercolor(nil,'cmyk',c,m,y,k))
     else
         return ""
     end
@@ -688,7 +690,7 @@ end
 
 function lpdf.graycode(model,s)
     if colors.supported then
-        return pdfcolor(model,registercolor(nil,'gray',s))
+        return lpdfcolor(model,registercolor(nil,'gray',s))
     else
         return ""
     end
@@ -696,7 +698,7 @@ end
 
 function lpdf.spotcode(model,n,f,d,p)
     if colors.supported then
-        return pdfcolor(model,registercolor(nil,'spot',n,f,d,p)) -- incorrect
+        return lpdfcolor(model,registercolor(nil,'spot',n,f,d,p)) -- incorrect
     else
         return ""
     end
@@ -722,18 +724,12 @@ end
 
 do
 
-    local pdfprint, pdfcolor, pdftransparency
-
-    updaters.register("backend.update.lpdf",function()
-        pdfprint        = lpdf.print
-        pdfcolor        = lpdf.color
-        pdftransparency = lpdf.transparency
-    end)
+    local lpdfprint = lpdf.print
 
     local c_cache = setmetatableindex(function(t,m)
         -- We inherit the outer transparency.
         local v = setmetatableindex(function(t,c)
-            local p = "q " .. pdfcolor(m,c)
+            local p = "q " .. lpdfcolor(m,c)
             t[c] = p
             return p
         end)
@@ -742,10 +738,10 @@ do
     end)
 
     local t_cache = setmetatableindex(function(t,transparency)
-        local p = pdftransparency(transparency)
+        local p = lpdftransparency(transparency)
         local v = setmetatableindex(function(t,colormodel)
             local v = setmetatableindex(function(t,color)
-                local v = "q " .. pdfcolor(colormodel,color) .. " " .. p
+                local v = "q " .. lpdfcolor(colormodel,color) .. " " .. p
                 t[color] = v
                 return v
             end)
@@ -756,35 +752,29 @@ do
         return v
     end)
 
-    updaters.register("backend.update.lpdf",function()
-
-        local vfinjectors = fonts.helpers.vfinjectors
-
-        vfinjectors.pdf = function(pos_h,pos_v,packet)
-            pdfprint(packet[2],packet[3])
-        end
-
-        vfinjectors.startcolor = function(pos_h,pos_v,packet)
-            local color = type(packet) == "table" and packet[2] or packet
-            if color then
-                local m, c = colortoattributes(color)
-                local t = transparencytoattribute(color)
-                if t and t ~= unsetvalue then
-                    pdfprint("page", t_cache[t][m][c]) -- "q " .. pdfcolor(m,c) .. " " .. pdftransparency(t)
-                else
-                    pdfprint("page", c_cache[m][c])    -- "q " .. pdfcolor(m,c))
-                end
+ -- function codeinjections.vfliteral(pos_h,pos_v,packet)
+ --     lpdfprint(packet[2],packet[3])
+ -- end
+
+    function codeinjections.vfstartcolor(pos_h,pos_v,packet)
+        local color = type(packet) == "table" and packet[2] or packet
+        if color then
+            local m, c = colortoattributes(color)
+            local t = transparencytoattribute(color)
+            if t and t ~= unsetvalue then
+                lpdfprint("page", t_cache[t][m][c]) -- "q " .. lpdfcolor(m,c) .. " " .. lpdftransparency(t)
             else
-                pdfprint("page", "q")
+                lpdfprint("page", c_cache[m][c])    -- "q " .. lpdfcolor(m,c))
             end
+        else
+            lpdfprint("page", "q")
         end
+    end
 
-        vfinjectors.stopcolor = function()
-         -- pdfprint("text", "Q")
-            pdfprint("page", "Q")
-        end
-
-    end)
+    function codeinjections.vfstopcolor()
+     -- lpdfprint("text", "Q")
+        lpdfprint("page", "Q")
+    end
 
 end
 
@@ -792,19 +782,16 @@ end
 
 do
 
-    local color        = lpdf.color
-    local transparency = lpdf.transparency
-
     local fonts = { }
     lpdf.fonts  = fonts
 
     fonts.color_indirect = function(c,t)
         if c and t then
-            return color(1,c) .. " " .. transparency(t)
+            return lpdfcolor(1,c) .. " " .. lpdftransparency(t)
         elseif c then
-            return color(1,c)
+            return lpdfcolor(1,c)
         elseif t then
-            return transparency(t)
+            return lpdftransparency(t)
         else
             return false
         end
diff --git a/tex/context/base/mkxl/lpdf-emb.lmt b/tex/context/base/mkxl/lpdf-emb.lmt
index 926455bb8..9811c0843 100644
--- a/tex/context/base/mkxl/lpdf-emb.lmt
+++ b/tex/context/base/mkxl/lpdf-emb.lmt
@@ -2040,7 +2040,7 @@ local loadstreamdata = fonts.handlers.otf.loadstreamdata
 
 -- we can actually now number upwards (so not use fontid in /F)
 
-local objects = setmetatableindex(function(t,k)
+local objects = setmetatableindex(lpdf.usedfontobjects,function(t,k) -- defined in lpdf-lmt.lmt
     local v
     if type(k) == "number" then
         local h = getstreamhash(k)
@@ -2063,7 +2063,7 @@ end)
 
 local n = 0
 
-local names = setmetatableindex(function(t,k)
+local names = setmetatableindex(lpdf.usedfontnames,function(t,k) -- defined in lpdf-lmt.lmt
     local v
     if type(k) == "number" then
         local h = getstreamhash(k)
diff --git a/tex/context/base/mkxl/lpdf-epa.lmt b/tex/context/base/mkxl/lpdf-epa.lmt
index a88e48a5e..750c008fb 100644
--- a/tex/context/base/mkxl/lpdf-epa.lmt
+++ b/tex/context/base/mkxl/lpdf-epa.lmt
@@ -29,14 +29,16 @@ local report_comment    = logs.reporter("backend","comment")
 local report_field      = logs.reporter("backend","field")
 local report_outline    = logs.reporter("backend","outline")
 
-local lpdf              = lpdf
-local backends          = backends
 local context           = context
 
-local nodeinjections    = backends.pdf.nodeinjections
+local pdfbackend        = backends.registered.pdf
+local nodeinjections    = pdfbackend.nodeinjections
+local codeinjections    = pdfbackend.codeinjections
+----- registrations     = pdfbackend.registrations
 
 local setmacro          = tokens.setters.macro
 
+local lpdf              = lpdf
 local pdfarray          = lpdf.array
 local pdfdictionary     = lpdf.dictionary
 local pdfconstant       = lpdf.constant
@@ -62,7 +64,6 @@ local loadpdffile       = lpdf.epdf.load
 local nameonly          = file.nameonly
 
 local variables         = interfaces.variables
-local codeinjections    = backends.pdf.codeinjections
 ----- urlescaper        = lpegpatterns.urlescaper
 ----- utftohigh         = lpegpatterns.utftohigh
 local escapetex         = characters.filters.utf.private.escape
@@ -77,7 +78,7 @@ local layerspec = {
     "epdfcontent"
 }
 
-local getpos = function() getpos = backends.codeinjections.getpos return getpos() end
+local getpos = function() getpos = codeinjections.getpos return getpos() end
 
 local collected = allocate()
 local tobesaved = allocate()
@@ -1013,7 +1014,7 @@ function codeinjections.mergebookmarks(specification)
     end
     if specification then
         local fullname  = specification.fullname
-        local bookmarks = backends.codeinjections.getbookmarks(fullname)
+        local bookmarks = codeinjections.getbookmarks(fullname)
         local realpage  = tonumber(specification.page) or 1
         for i=1,#bookmarks do
             local b = bookmarks[i]
diff --git a/tex/context/base/mkxl/lpdf-fld.lmt b/tex/context/base/mkxl/lpdf-fld.lmt
index 13ebd6c44..3077b19c0 100644
--- a/tex/context/base/mkxl/lpdf-fld.lmt
+++ b/tex/context/base/mkxl/lpdf-fld.lmt
@@ -62,22 +62,20 @@ local trace_fields = false  trackers.register("backends.fields", function(v) tra
 
 local report_fields = logs.reporter("backend","fields")
 
-local backends, lpdf = backends, lpdf
-
 local variables               = interfaces.variables
 local context                 = context
 
 local references              = structures.references
 local settings_to_array       = utilities.parsers.settings_to_array
 
-local pdfbackend              = backends.pdf
-
+local pdfbackend              = backends.registered.pdf
 local nodeinjections          = pdfbackend.nodeinjections
 local codeinjections          = pdfbackend.codeinjections
 local registrations           = pdfbackend.registrations
 
 local registeredsymbol        = codeinjections.registeredsymbol
 
+local lpdf                    = lpdf
 local pdfstream               = lpdf.stream
 local pdfdictionary           = lpdf.dictionary
 local pdfarray                = lpdf.array
diff --git a/tex/context/base/mkxl/lpdf-fmt.lmt b/tex/context/base/mkxl/lpdf-fmt.lmt
index f83432d48..7ceacc62d 100644
--- a/tex/context/base/mkxl/lpdf-fmt.lmt
+++ b/tex/context/base/mkxl/lpdf-fmt.lmt
@@ -19,15 +19,16 @@ local trace_variables = false  trackers.register("backend.variables", function(v
 
 local report_backend = logs.reporter("backend","profiles")
 
-local backends, lpdf = backends, lpdf
-
-local codeinjections           = backends.pdf.codeinjections
+local pdfbackend               = backends.registered.pdf
+----- nodeinjections           = pdfbackend.nodeinjections
+local codeinjections           = pdfbackend.codeinjections
 
 local variables                = interfaces.variables
 local viewerlayers             = attributes.viewerlayers
 local colors                   = attributes.colors
 local transparencies           = attributes.transparencies
 
+local lpdf                     = lpdf
 local pdfdictionary            = lpdf.dictionary
 local pdfarray                 = lpdf.array
 local pdfconstant              = lpdf.constant
diff --git a/tex/context/base/mkxl/lpdf-grp.lmt b/tex/context/base/mkxl/lpdf-grp.lmt
index e5d04c5a9..7c4001467 100644
--- a/tex/context/base/mkxl/lpdf-grp.lmt
+++ b/tex/context/base/mkxl/lpdf-grp.lmt
@@ -11,17 +11,15 @@ local formatters, gsub = string.formatters, string.gsub
 local concat = table.concat
 local round = math.round
 
-local backends, lpdf = backends, lpdf
-
-local nodeinjections = backends.pdf.nodeinjections
-
 local colors         = attributes.colors
 local basepoints     = number.dimenfactors.bp
 
-local nodeinjections = backends.pdf.nodeinjections
-local codeinjections = backends.pdf.codeinjections
-local registrations  = backends.pdf.registrations
+local pdfbackend     = backends.registered.pdf
+local nodeinjections = pdfbackend.nodeinjections
+local codeinjections = pdfbackend.codeinjections
+local registrations  = pdfbackend.registrations
 
+local lpdf           = lpdf
 local pdfdictionary  = lpdf.dictionary
 local pdfarray       = lpdf.array
 local pdfconstant    = lpdf.constant
@@ -295,4 +293,4 @@ function lpdf.patternstream(n,width,height)
     return f_pattern("Pt" .. n,width*basepoints,height*basepoints)
 end
 
-backends.pdf.codeinjections.registerpattern = lpdf.registerpattern
+codeinjections.registerpattern = lpdf.registerpattern
diff --git a/tex/context/base/mkxl/lpdf-img.lmt b/tex/context/base/mkxl/lpdf-img.lmt
index 8e7427ae6..df658c236 100644
--- a/tex/context/base/mkxl/lpdf-img.lmt
+++ b/tex/context/base/mkxl/lpdf-img.lmt
@@ -59,6 +59,8 @@ local pdfflushstreamobject = lpdf.flushstreamobject
 local pdfmajorversion      = lpdf.majorversion
 local pdfminorversion      = lpdf.minorversion
 
+local codeinjections       = backends.registered.pdf.codeinjections
+
 local createimage          = images.create
 
 local zlibcompress         = xzip.compress
@@ -1363,7 +1365,7 @@ do
         }
     end
 
-    backends.pdf.codeinjections.bitmap = injectors.bitmap
+    codeinjections.bitmap = injectors.bitmap
 
 end
 
@@ -1390,6 +1392,6 @@ end
 --     return true
 -- end
 
-backends.pdf.codeinjections.jpg = lpdf.injectors.jpg
-backends.pdf.codeinjections.jp2 = lpdf.injectors.jp2
-backends.pdf.codeinjections.png = lpdf.injectors.png
+codeinjections.jpg = lpdf.injectors.jpg
+codeinjections.jp2 = lpdf.injectors.jp2
+codeinjections.png = lpdf.injectors.png
diff --git a/tex/context/base/mkxl/lpdf-ini.lmt b/tex/context/base/mkxl/lpdf-ini.lmt
index 1ce7c5adc..7979b80f8 100644
--- a/tex/context/base/mkxl/lpdf-ini.lmt
+++ b/tex/context/base/mkxl/lpdf-ini.lmt
@@ -75,25 +75,14 @@ local context           = context
 
 -- In ConTeXt MkIV we use utf8 exclusively so all strings get mapped onto a hex
 -- encoded utf16 string type between <>. We could probably save some bytes by using
--- strings between () but then we end up with escaped ()\ too.
+-- strings between () but then we end up with escaped ()\ characters too.
 
 pdf                     = type(pdf) == "table" and pdf or { }
 local factor            = number.dimenfactors.bp
 
-local codeinjections    = { }
-local nodeinjections    = { }
-
-local backends          = backends or { }
-
-local pdfbackend        = {
-    comment        = "backend for directly generating pdf output",
-    nodeinjections = nodeinjections,
-    codeinjections = codeinjections,
-    registrations  = { },
-    tables         = { },
-}
-
-backends.pdf = pdfbackend
+local pdfbackend        = backends.registered.pdf
+local codeinjections    = pdfbackend.codeinjections
+local nodeinjections    = pdfbackend.nodeinjections
 
 lpdf       = lpdf or { }
 local lpdf = lpdf
@@ -107,10 +96,29 @@ end)
 local trace_finalizers = false  trackers.register("backend.finalizers", function(v) trace_finalizers = v end)
 local trace_resources  = false  trackers.register("backend.resources",  function(v) trace_resources  = v end)
 
+do
+
+    -- This is for a future feature (still under investigation and consideration). So,
+    -- it is work in progress (and brings a harmless overhead for now).
+
+    local initializers = { }
+
+    function lpdf.registerinitializer(initialize)
+        initializers[#initializers+1] = initialize
+    end
+
+    function lpdf.initialize(f)
+        for i=1,#initializers do
+            initializers[i]()
+        end
+    end
+
+end
+
 local pdfreserveobject
 local pdfimmediateobject
 
-updaters.register("backend.update.lpdf",function()
+updaters.register("backends.pdf.latebindings",function()
     pdfreserveobject   = lpdf.reserveobject
     pdfimmediateobject = lpdf.immediateobject
 end)
@@ -119,7 +127,7 @@ do
 
     local pdfgetmatrix, pdfhasmatrix, pdfgetpos
 
-    updaters.register("backend.update.lpdf",function()
+    updaters.register("backends.pdf.latebindings",function()
         job.positions.registerhandlers {
             getpos  = drivers.getpos,
             getrpos = drivers.getrpos,
@@ -771,6 +779,8 @@ end
 
 resetpageproperties()
 
+lpdf.registerinitializer(resetpageproperties)
+
 local function addtopageresources  (k,v) pageresources  [k] = v end
 local function addtopageattributes (k,v) pageattributes [k] = v end
 local function addtopagesattributes(k,v) pagesattributes[k] = v end
@@ -830,13 +840,12 @@ function lpdf.finalizepage(shipout)
     end
 end
 
+local finalized = false
+
 function lpdf.finalizedocument()
-    if not environment.initex then
+    if not environment.initex and not finalized then
         run(documentfinalizers,"document")
-        function lpdf.finalizedocument()
-         -- report_finalizing("serious error: the document is finalized multiple times")
-            function lpdf.finalizedocument() end
-        end
+        finalized = true
     end
 end
 
@@ -891,7 +900,6 @@ do
     local function flushcatalog()
         if checkcatalog() then
             catalog.Type = nil
---             pdfsetcatalog(catalog())
         end
     end
 
@@ -951,6 +959,12 @@ do
     local d_extgstates, d_colorspaces, d_patterns, d_shades
     local p_extgstates, p_colorspaces, p_patterns, p_shades
 
+    lpdf.registerinitializer(function()
+        r_extgstates = nil ; r_colorspaces = nil ; r_patterns = nil ; r_shades = nil ;
+        d_extgstates = nil ; d_colorspaces = nil ; d_patterns = nil ; d_shades = nil ;
+        p_extgstates = nil ; p_colorspaces = nil ; p_patterns = nil ; p_shades = nil ;
+    end)
+
     local function checkextgstates () if d_extgstates  then addtopageresources("ExtGState", p_extgstates ) end end
     local function checkcolorspaces() if d_colorspaces then addtopageresources("ColorSpace",p_colorspaces) end end
     local function checkpatterns   () if d_patterns    then addtopageresources("Pattern",   p_patterns   ) end end
@@ -969,7 +983,7 @@ do
 
     local pdfgetfontobjectnumber
 
-    updaters.register("backend.update.lpdf",function()
+    updaters.register("backends.pdf.latebindings",function()
         pdfgetfontobjectnumber = lpdf.getfontobjectnumber
     end)
 
@@ -1356,11 +1370,16 @@ end
 
 do
 
-    -- This is obsolete but old viewers might still use it as directive
-    -- for what to send to a postscript printer.
+    -- This is obsolete but old viewers might still use it as directive for what to
+    -- send to a postscript printer.
 
     local a_procset, d_procset
 
+    lpdf.registerinitializer(function()
+        a_procset = nil
+        d_procset = nil
+    end)
+
     function lpdf.procset(dict)
         if not a_procset then
             a_procset = pdfarray {
diff --git a/tex/context/base/mkxl/lpdf-lmt.lmt b/tex/context/base/mkxl/lpdf-lmt.lmt
index e1637228a..fb7b8ac63 100644
--- a/tex/context/base/mkxl/lpdf-lmt.lmt
+++ b/tex/context/base/mkxl/lpdf-lmt.lmt
@@ -42,7 +42,6 @@ local loaddata = io.loaddata
 local bpfactor               = number.dimenfactors.bp
 
 local osuuid                 = os.uuid
-local zlibcompress           = xzip.compress
 local zlibcompresssize       = xzip.compresssize
 
 local nuts                   = nodes.nuts
@@ -66,14 +65,6 @@ local pdfimmediateobject     -- forward reference
 
 local pdfincludeimage        -- forward reference
 
-local pdfgetfontname         -- elsewhere
-local pdfgetfontobjectnumber -- elsewhere
-
-updaters.register("backend.update.lpdf",function()
-    pdfgetfontname         = lpdf.getfontname
-    pdfgetfontobjectnumber = lpdf.getfontobjectnumber
-end)
-
 local pdf_pages      = pdfconstant("Pages")
 local pdf_page       = pdfconstant("Page")
 local pdf_xobject    = pdfconstant("XObject")
@@ -94,6 +85,14 @@ local trace_objects  = false  trackers.register("backend.objects",       functio
 local trace_details  = false  trackers.register("backend.details",       function(v) trace_details = v end)
 local trace_indices  = false  trackers.register("backend.fonts.details", function(v) trace_indices = v end)
 
+-- These two tables used a font id as index and will be metatabled in lpdf-emb.lmt:
+
+local usedfontnames   = { }
+local usedfontobjects = { }
+
+lpdf.usedfontnames    = usedfontnames
+lpdf.usedfontobjects  = usedfontobjects
+
 -- experiment:
 
 local function compressdata(data,size)
@@ -131,7 +130,8 @@ local cmrx, cmry, cmsx, cmsy, cmtx, cmty
 local tmef
 
 local function usefont(t,k) -- a bit redundant hash
-    local v = pdfgetfontname(k)
+ -- local v = pdfgetfontname(k)
+    local v = usedfontnames[k]
     t[k] = v
     return v
 end
@@ -987,6 +987,10 @@ local localconverter = nil -- will be set
 
 local flushimage  do
 
+    local pdfbackend        = backends.registered.pdf
+    local nodeinjections    = pdfbackend.nodeinjections
+    local codeinjections    = pdfbackend.codeinjections
+
     local newimagerule      = nuts.pool.imagerule
     local newboxrule        = nuts.pool.boxrule
 
@@ -1045,13 +1049,19 @@ local flushimage  do
 
     lpdf.getxformname = getxformname
 
-    local function saveboxresource(box,attributes,resources,immediate,kind,margin)
+    local pdfcollectedresources = lpdf.collectedresources
+
+    function codeinjections.saveboxresource(box,attributes,resources,immediate,kind,margin)
         n = n + 1
         local immediate = true
         local margin    = margin or 0 -- or dimension
         local objnum    = pdfreserveobject()
         local list      = tonut(type(box) == "number" and tex.takebox(box) or box)
         --
+        if resources == true then
+            resources = pdfcollectedresources()
+        end
+        --
         local width, height, depth = getwhd(list)
         --
         local l = {
@@ -1078,7 +1088,7 @@ local flushimage  do
         return objnum
     end
 
-    local function useboxresource(index,wd,ht,dp)
+    function nodeinjections.useboxresource(index,wd,ht,dp)
         local l = boxresources[index]
         if l then
             if wd or ht or dp then
@@ -1104,20 +1114,15 @@ local flushimage  do
         end
     end
 
-    local function getboxresourcebox(index)
+    nodeinjections.getboxresourcedimensions = getboxresourcedimensions
+
+    function codeinjections.getboxresourcebox(index)
         local l = boxresources[index]
         if l then
             return l.list
         end
     end
 
-    updaters.register("backend.update.lpdf",function()
-        tex.saveboxresource          = saveboxresource
-        tex.useboxresource           = useboxresource
-        tex.getboxresourcedimensions = getboxresourcedimensions
-        tex.getboxresourcebox        = getboxresourcebox
-    end)
-
     -- a bit of a mess: index is now objnum but that has to change to a proper index
     -- ... an engine inheritance
 
@@ -1475,7 +1480,7 @@ end
 
 --- basics
 
-local wrapup, registerpage  do
+local wrapupdocument, registerpage  do
 
     local pages    = { }
     local maxkids  = 10
@@ -1550,7 +1555,7 @@ local wrapup, registerpage  do
  --     lpdf.setpageorder(t)
  -- end
 
-    wrapup = function(driver)
+    wrapupdocument = function(driver)
 
         -- hook (to reshuffle pages)
         local pagetree = { }
@@ -1730,7 +1735,8 @@ local finalize  do
         if next(usedfonts) then
             fonts = pdfdictionary { }
             for k, v in next, usedfonts do
-                fonts[f_font(v)] = pdfreference(pdfgetfontobjectnumber(k)) -- we can overload for testing
+--                 fonts[f_font(v)] = pdfreference(pdfgetfontobjectnumber(k)) -- we can overload for testing
+                fonts[f_font(v)] = pdfreference(usedfontobjects[k]) -- we can overload for testing
             end
         end
 
@@ -1890,17 +1896,6 @@ local finalize  do
 
 end
 
-updaters.register("backend.update",function()
-    local saveboxresource = tex.boxresources.save
-    --
-    -- also in lpdf-res .. brrr .. needs fixing
-    --
-    backends.codeinjections.registerboxresource = function(n,offset)
-        local r = saveboxresource(n,nil,nil,false,0,offset or 0)
-        return r
-    end
-end)
-
 -- now comes the pdf file handling
 
 local objects       = { }
@@ -2429,7 +2424,6 @@ pdfimmediateobject = function(a,b,c,d)
     end
     -- todo: immediate
     if kind == "stream" then
---         flushstreamobj(data,objnum,attr,compresslevel and compresslevel > 0 or nil,nolength) -- nil == auto
         flushstreamobj(data,objnum,attr,compresslevel,nolength) -- nil == auto
     elseif objectstream and objcompression ~= false then
         addtocache(objnum,data)
@@ -2747,7 +2741,9 @@ do
     -- reimplement what we need in context. This will change completely i.e.
     -- we will drop the low level interface!
 
-    local codeinjections = backends.pdf.codeinjections
+    local pdfbackend     = backends.registered.pdf
+    local nodeinjections = pdfbackend.nodeinjections
+    local codeinjections = pdfbackend.codeinjections
 
     local imagetypes     = images.types -- pdf png jpg jp2 jbig2 stream
     local img_none       = imagetypes.none
@@ -2828,7 +2824,6 @@ do
                 specification.type = kind
                 specification.kind = kind
             end
---             flushstreamobj(stream,objnum,dict,compresslevel and compresslevel > 0 or nil,nolength)
             flushstreamobj(stream,objnum,dict,compresslevel,nolength)
             specification.objnum      = objnum
             specification.rotation    = specification.rotation or 0
@@ -2885,108 +2880,7 @@ do
 
     lpdf.includeimage = pdfincludeimage
 
-end -- )
-
-do
-
-    -- todo: an md5 or sha2 hash can save space
-    -- todo: make a type 3 font instead
-    -- todo: move to lpdf namespace
-
-    local pdfimage
-    local newpdf
-    local openpdf
-    local closepdf
-    local copypage
-
-    updaters.register("backend.update.lpdf",function()
-        pdfimage = lpdf.epdf.image
-        newpdf   = pdfimage.new
-        openpdf  = pdfimage.open
-        closepdf = pdfimage.close
-        copypage = pdfimage.copy
-    end)
-
-    local embedimage = images.embed
-
-    local nofstreams = 0
-    local topdf      = { }
-    local toidx      = { }
-
-    local function storedata_s(pdf)
-        local idx = toidx[pdf]
-        if not idx then
-            nofstreams = nofstreams + 1
-            idx = nofstreams
-            toidx[pdf] = nofstreams
-            topdf[idx] = pdf
-        end
-        return idx
-    end
-
-    local function vfimage_s(id,wd,ht,dp,pos_h,pos_v)
-        local index = topdf[id]
-        if type(index) == "string" then
-            local pdfdoc  = newpdf(index,#index)
-            local image   = copypage(pdfdoc)
-            local bbox    = image.bbox
-            image.width   = bbox[3] - bbox[1]
-            image.height  = bbox[4] - bbox[2]
-            embedimage(image)
-            index = image.index
-            topdf[id] = index
-        end
-        flushimage(index,wd,ht,dp,pos_h,pos_v)
-    end
-
-    local function storedata_n(name,page)
-        local idx = toidx[pdf]
-        if not idx then
-            nofstreams = nofstreams + 1
-            idx = nofstreams
-            toidx[pdf] = nofstreams
-            topdf[idx] = pdf
-        end
-        return idx
-    end
-
-    -- We need to have a way to close such a pdf ... esp for fonts.
-
-    local pdfdocs = { }
-
-    local function vfimage_n(name,page,wd,ht,dp,pos_h,pos_v)
-        local d = pdfdocs[name]
-        if not d then
-            d = { doc = openpdf(name), pages = { } }
-            pdfdocs[name] = d
-        end
-        local index = d.pages[page]
-        if not index then
-            local image  = copypage(d.doc,page)
-            local bbox   = image.bbox
-            image.width  = bbox[3] - bbox[1]
-            image.height = bbox[4] - bbox[2]
-            embedimage(image)
-            index = image.index
-            d.pages[page] = index
-        end
-        flushimage(index,wd,ht,dp,pos_h,pos_v)
-    end
-
-    function lpdf.pdfvfimage(wd,ht,dp,data,name)
-        if type(data) == "number" then
-            return { "lua", function(font,char,pos_h,pos_v)
-                vfimage_n(name,data,wd,ht,dp,pos_h,pos_v)
-            end }
-        else
-            return { "lua", function(font,char,pos_h,pos_v)
-                local id = storedata_s(data)
-                vfimage_s(id,wd,ht,dp,pos_h,pos_v)
-            end }
-        end
-    end
-
-end -- )
+end
 
 -- The driver.
 
@@ -3003,12 +2897,24 @@ do
         return pdfname
     end
 
+-- local outputfilename ; do -- old todo usedname in ^^
+--     local filename = nil
+--     outputfilename = function(driver,usedname)
+--         if usedname and usedname ~= "" then
+--             filename = addsuffix(usedname,"pdf")
+--         elseif not filename or filename == "" then
+--             filename = addsuffix(tex.jobname,"pdf")
+--         end
+--         return filename
+--     end
+-- end
+
     -- todo: prevent twice
 
     local function prepare(driver)
         if not environment.initex then
-            updaters.apply("backend.update.lpdf")
-            updaters.apply("backend.update")
+            --
+            backends.initialize("pdf") -- also does bindings
             --
             pdfname = tex.jobname .. ".pdf"
             openfile(pdfname)
@@ -3017,6 +2923,7 @@ do
                 if pdfname then
                     lpdf.finalizedocument()
                     closefile()
+                    pdfname = nil
                 end
             end)
             --
@@ -3026,7 +2933,7 @@ do
                 end
             end)
             --
-            lpdf.registerdocumentfinalizer(wrapup,nil,"wrapping up")
+            lpdf.registerdocumentfinalizer(wrapupdocument,nil,"wrapping up")
             --
             statistics.register("result saved in file", function()
                 local outputfilename = environment.outputfilename or environment.jobname or tex.jobname or "<unset>"
diff --git a/tex/context/base/mkxl/lpdf-mis.lmt b/tex/context/base/mkxl/lpdf-mis.lmt
index ca018e9f0..2b82f8adc 100644
--- a/tex/context/base/mkxl/lpdf-mis.lmt
+++ b/tex/context/base/mkxl/lpdf-mis.lmt
@@ -20,15 +20,15 @@ local format, gsub, formatters = string.format, string.gsub, string.formatters
 local concat, flattened = table.concat, table.flattened
 local settings_to_array = utilities.parsers.settings_to_array
 
-local backends, lpdf, nodes = backends, lpdf, nodes
-
-local nodeinjections       = backends.pdf.nodeinjections
-local codeinjections       = backends.pdf.codeinjections
-local registrations        = backends.pdf.registrations
+local pdfbackend           = backends.registered.pdf
+local nodeinjections       = pdfbackend.nodeinjections
+local codeinjections       = pdfbackend.codeinjections
+local registrations        = pdfbackend.registrations
 
 local getpagedimensions    = layouts.getpagedimensions
 local getcanvas            = layouts.getcanvas
 
+local nodes                = nodes
 local nuts                 = nodes.nuts
 local copy_node            = nuts.copy
 
@@ -36,6 +36,7 @@ local nodepool             = nuts.pool
 local setstate             = nodepool.setstate
 local register             = nodepool.register
 
+local lpdf                 = lpdf
 local pdfdictionary        = lpdf.dictionary
 local pdfarray             = lpdf.array
 local pdfconstant          = lpdf.constant
diff --git a/tex/context/base/mkxl/lpdf-ren.lmt b/tex/context/base/mkxl/lpdf-ren.lmt
index a50dcdc79..0343ab76a 100644
--- a/tex/context/base/mkxl/lpdf-ren.lmt
+++ b/tex/context/base/mkxl/lpdf-ren.lmt
@@ -14,11 +14,11 @@ local formatters = string.formatters
 local settings_to_array = utilities.parsers.settings_to_array
 local getrandom = utilities.randomizer.get
 
-local backends, lpdf, nodes, node = backends, lpdf, nodes, node
+local pdfbackend          = backends.registered.pdf
+local nodeinjections      = pdfbackend.nodeinjections
+local codeinjections      = pdfbackend.codeinjections
+local registrations       = pdfbackend.registrations
 
-local nodeinjections      = backends.pdf.nodeinjections
-local codeinjections      = backends.pdf.codeinjections
-local registrations       = backends.pdf.registrations
 local viewerlayers        = attributes.viewerlayers
 
 local references          = structures.references
@@ -36,6 +36,7 @@ local v_reset             = variables.reset
 local v_auto              = variables.auto
 local v_random            = variables.random
 
+local lpdf                = lpdf
 local pdfconstant         = lpdf.constant
 local pdfdictionary       = lpdf.dictionary
 local pdfarray            = lpdf.array
@@ -48,7 +49,9 @@ local addtocatalog        = lpdf.addtocatalog
 
 local escaped             = lpdf.escaped
 
+local nodes               = nodes
 local nuts                = nodes.nuts
+
 local copy_node           = nuts.copy
 
 local nodepool            = nuts.pool
diff --git a/tex/context/base/mkxl/lpdf-res.lmt b/tex/context/base/mkxl/lpdf-res.lmt
deleted file mode 100644
index d3c591343..000000000
--- a/tex/context/base/mkxl/lpdf-res.lmt
+++ /dev/null
@@ -1,41 +0,0 @@
-if not modules then modules = { } end modules ['lpdf-res'] = {
-    version   = 1.001,
-    comment   = "companion to lpdf-ini.mkiv",
-    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
-    copyright = "PRAGMA ADE / ConTeXt Development Team",
-    license   = "see context related readme files"
-}
-
-local codeinjections           = backends.codeinjections
-
-local nuts                     = nodes.nuts
-local tonut                    = nodes.tonut
-
-local setwhd                   = nuts.setwhd
-local setlist                  = nuts.setlist
-
-local new_hlist                = nuts.pool.hlist
-
-local boxresources             = tex.boxresources
-local saveboxresource          = boxresources.save
-local useboxresource           = boxresources.use
-local getboxresourcedimensions = boxresources.getdimensions
-
-local pdfcollectedresources    = lpdf.collectedresources
-
-function codeinjections.registerboxresource(n,offset)
-    local r = saveboxresource(n,nil,pdfcollectedresources(),true,0,offset or 0) -- direct, todo: accept functions as attr/resources
-    return r
-end
-
-function codeinjections.restoreboxresource(index)
-    local hbox = new_hlist()
-    local list, wd, ht, dp = useboxresource(index)
-    setlist(hbox,tonut(list))
-    setwhd(hbox,wd,ht,dp)
-    return hbox -- so we return a nut !
-end
-
-function codeinjections.boxresourcedimensions(index)
-    return getboxresourcedimensions(index)
-end
diff --git a/tex/context/base/mkxl/lpdf-rul.lmt b/tex/context/base/mkxl/lpdf-rul.lmt
index baf4509ed..f0676dee9 100644
--- a/tex/context/base/mkxl/lpdf-rul.lmt
+++ b/tex/context/base/mkxl/lpdf-rul.lmt
@@ -33,6 +33,8 @@ local floor            = math.floor
 local getrandom        = utilities.randomizer.get
 local formatters       = string.formatters
 
+local codeinjections   = backends.registered.pdf.codeinjections
+
 -- This is very pdf specific. Maybe move some to lpdf-rul.lua some day.
 
 local pdfprint ; pdfprint = function(...) pdfprint = lpdf.print return pdfprint(...) end
@@ -97,7 +99,7 @@ def RuleColor = %color% enddef ;
 
     local initialized = false ;
 
-    local rule_mp = function(p,h,v,i,n)
+    local function rule_mp(p,h,v,i,n)
         local name = p.name or "fake:rest"
         local code = (predefined[name] or predefined["fake:rest"]) {
             data      = p.data or "",
@@ -129,9 +131,7 @@ def RuleColor = %color% enddef ;
         end
     end
 
-    updaters.register("backend.update.lpdf",function()
-        ruleactions.mp = rule_mp
-    end)
+    codeinjections.ruleactionmp = rule_mp
 
 end
 
@@ -373,12 +373,10 @@ h %s]]
         end
     end
 
-    updaters.register("backend.update.lpdf",function()
-        ruleactions.fill   = rule_any
-        ruleactions.draw   = rule_any
-        ruleactions.stroke = rule_any
-        ruleactions.box    = rule_box
-    end)
+    codeinjections.ruleactionfill   = rule_any
+    codeinjections.ruleactiondraw   = rule_any
+    codeinjections.ruleactionstroke = rule_any
+    codeinjections.ruleactionbox    = rule_box
 
 end
 
diff --git a/tex/context/base/mkxl/lpdf-tag.lmt b/tex/context/base/mkxl/lpdf-tag.lmt
index 5b52f56fd..7aa9edb9b 100644
--- a/tex/context/base/mkxl/lpdf-tag.lmt
+++ b/tex/context/base/mkxl/lpdf-tag.lmt
@@ -18,16 +18,14 @@ local trace_info = false  trackers.register("structures.tags.info", function(v)
 
 local report_tags = logs.reporter("backend","tags")
 
-local backends            = backends
-local lpdf                = lpdf
-local nodes               = nodes
-
-local nodeinjections      = backends.pdf.nodeinjections
-local codeinjections      = backends.pdf.codeinjections
+local pdfbackend          = backends.registered.pdf
+local nodeinjections      = pdfbackend.nodeinjections
+local codeinjections      = pdfbackend.codeinjections
 
 local enableaction        = nodes.tasks.enableaction
 local disableaction       = nodes.tasks.disableaction
 
+local lpdf                = lpdf
 local pdfdictionary       = lpdf.dictionary
 local pdfarray            = lpdf.array
 local pdfboolean          = lpdf.boolean
@@ -45,6 +43,7 @@ local pdfpagereference    = lpdf.pagereference
 
 local texgetcount         = tex.getcount
 
+local nodes               = nodes
 local nodecodes           = nodes.nodecodes
 
 local hlist_code          = nodecodes.hlist
diff --git a/tex/context/base/mkxl/lpdf-u3d.lmt b/tex/context/base/mkxl/lpdf-u3d.lmt
index 54dc8a227..5307818d0 100644
--- a/tex/context/base/mkxl/lpdf-u3d.lmt
+++ b/tex/context/base/mkxl/lpdf-u3d.lmt
@@ -21,10 +21,9 @@ local tonumber = tonumber
 local formatters, find = string.formatters, string.find
 local cos, sin, sqrt, pi, atan2, abs = math.cos, math.sin, math.sqrt, math.pi, math.atan2, math.abs
 
-local backends, lpdf = backends, lpdf
-
-local nodeinjections           = backends.pdf.nodeinjections
+local nodeinjections           = backends.registered.pdf.nodeinjections
 
+local lpdf                     = lpdf
 local pdfconstant              = lpdf.constant
 local pdfboolean               = lpdf.boolean
 local pdfunicode               = lpdf.unicode
diff --git a/tex/context/base/mkxl/lpdf-wid.lmt b/tex/context/base/mkxl/lpdf-wid.lmt
index 2999eb281..3047402bc 100644
--- a/tex/context/base/mkxl/lpdf-wid.lmt
+++ b/tex/context/base/mkxl/lpdf-wid.lmt
@@ -40,9 +40,6 @@ local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys
 local report_media             = logs.reporter("backend","media")
 local report_attachment        = logs.reporter("backend","attachment")
 
-local backends                 = backends
-local lpdf                     = lpdf
-local nodes                    = nodes
 local context                  = context
 
 local texgetcount              = tex.getcount
@@ -50,9 +47,10 @@ local getmacro                 = tokens.getters.macro
 
 local hpacknode                = nodes.hpack
 
-local nodeinjections           = backends.pdf.nodeinjections
-local codeinjections           = backends.pdf.codeinjections
-local registrations            = backends.pdf.registrations
+local pdfbackend               = backends.registered.pdf
+local nodeinjections           = pdfbackend.nodeinjections
+local codeinjections           = pdfbackend.codeinjections
+local registrations            = pdfbackend.registrations
 
 local executers                = structures.references.executers
 local variables                = interfaces.variables
@@ -67,6 +65,8 @@ local v_compress               = variables.compress
 local v_list                   = variables.list
 local v_title                  = variables.title
 
+local lpdf                     = lpdf
+
 local pdfconstant              = lpdf.constant
 local pdfnull                  = lpdf.null
 local pdfdictionary            = lpdf.dictionary
diff --git a/tex/context/base/mkxl/lpdf-xmp.lmt b/tex/context/base/mkxl/lpdf-xmp.lmt
index deeb1e135..a5be8bfe0 100644
--- a/tex/context/base/mkxl/lpdf-xmp.lmt
+++ b/tex/context/base/mkxl/lpdf-xmp.lmt
@@ -19,10 +19,11 @@ local trace_info = false  trackers.register("backend.info", function(v) trace_in
 local report_xmp  = logs.reporter("backend","xmp")
 local report_info = logs.reporter("backend","info")
 
-local backends, lpdf = backends, lpdf
-
-local codeinjections       = backends.pdf.codeinjections -- normally it is registered
+local backends             = backends
+local pdfbackend           = backends.registered.pdf
+local codeinjections       = pdfbackend.codeinjections
 
+local lpdf                 = lpdf
 local pdfdictionary        = lpdf.dictionary
 local pdfconstant          = lpdf.constant
 local pdfreference         = lpdf.reference
diff --git a/tex/context/base/mkxl/mlib-lmt.lmt b/tex/context/base/mkxl/mlib-lmt.lmt
index 7bbccb16b..ba86f0758 100644
--- a/tex/context/base/mkxl/mlib-lmt.lmt
+++ b/tex/context/base/mkxl/mlib-lmt.lmt
@@ -136,7 +136,7 @@ function mp.lmt_svg_include()
 end
 
 registerscript("remaptext", function()
-    local parameters = metapost.scanparameters()
+    local parameters = metapost.scanparameters(true) -- gobble the semi colon (avoid lookahead)
     if parameters and parameters.label then
         metapost.remaptext(parameters)
     end
diff --git a/tex/context/base/mkxl/mlib-scn.lmt b/tex/context/base/mkxl/mlib-scn.lmt
index 33aa74ad2..fcf9e73c3 100644
--- a/tex/context/base/mkxl/mlib-scn.lmt
+++ b/tex/context/base/mkxl/mlib-scn.lmt
@@ -731,8 +731,10 @@ end
 --     return false
 -- end
 
-function metapost.scanparameters()
---     scantoken() -- we scan the semicolon
+function metapost.scanparameters(gobblesemicolon)
+    if gobblesemicolon then
+        scantoken() -- we scan the semicolon
+    end
     return get_parameters()
 end
 
diff --git a/tex/context/base/mkxl/mlib-svg.lmt b/tex/context/base/mkxl/mlib-svg.lmt
index 945cafbab..9dcd6984b 100644
--- a/tex/context/base/mkxl/mlib-svg.lmt
+++ b/tex/context/base/mkxl/mlib-svg.lmt
@@ -1327,6 +1327,26 @@ local handletransform, handleviewbox  do
         )
     )^1
 
+    -- indeed, we need to reverse the order ... not that pretty and counter intuitive too
+
+    local function combined()
+        if noftransforms == 1 then
+            return transforms[1]
+        elseif noftransforms == 2 then
+            return transforms[2] .. transforms[1]
+        elseif noftransforms == 3 then
+            return transforms[3] .. transforms[2] .. transforms[1]
+        else
+            -- the rare case (but anything can happen in svg and it gets worse)
+            local m = noftransforms + 1
+            for i=1,noftransforms//2 do
+                local j = m - i
+                transforms[i], transforms[j] = transforms[j], transforms[i]
+            end
+            return concat(transforms,"",1,noftransforms)
+        end
+    end
+
     handletransform = function(at)
         local t = at.transform
         if t then
@@ -1334,7 +1354,7 @@ local handletransform, handleviewbox  do
             lpegmatch(p_transform,t)
             if noftransforms > 0 then
                 -- currentpicture
-                return s_transform_start, f_transform_stop(concat(transforms,"",1,noftransforms)), t
+                return s_transform_start, f_transform_stop(combined()), t
             end
         end
     end
@@ -1343,7 +1363,7 @@ local handletransform, handleviewbox  do
         if t then
             noftransforms = 0
             lpegmatch(p_transform,t)
-            return noftransforms > 0 and concat(transforms,"",1,noftransforms)
+            return noftransforms > 0 and combined()
         end
     end
 
diff --git a/tex/context/base/mkxl/node-ext.lmt b/tex/context/base/mkxl/node-ext.lmt
index 896dd8f99..fa15b9d19 100644
--- a/tex/context/base/mkxl/node-ext.lmt
+++ b/tex/context/base/mkxl/node-ext.lmt
@@ -619,7 +619,7 @@ do
         end,
     }
 
-    -- why ...
+    -- so we have them defined and can use them at the tex end .. still needed?
 
     local open_command  = get(token.create("openout"))
     local write_command = get(token.create("write"))
diff --git a/tex/context/base/mkxl/node-ext.mkxl b/tex/context/base/mkxl/node-ext.mkxl
new file mode 100644
index 000000000..697bb7d29
--- /dev/null
+++ b/tex/context/base/mkxl/node-ext.mkxl
@@ -0,0 +1,93 @@
+%D \module
+%D   [       file=back-ext,
+%D        version=2019.02.08, % and later, merged file
+%D          title=\CONTEXT\ Backend Macros,
+%D       subtitle=Output,
+%D         author=Hans Hagen,
+%D           date=\currentdate,
+%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{node-ext}{autosuffix}
+
+\unprotect
+
+% \let\normalopenout \openout
+% \let\normalwrite   \write
+% \let\normalcloseout\closeout
+% \let\normallatelua \latelua
+% \let\normalspecial \special
+
+% rotation
+
+% \permanent\protected\def\dostartrotation#1{\forcecolorhack\clf_startrotation#1\relax}
+% \permanent\protected\def\dostoprotation   {\clf_stoprotation\forcecolorhack}
+
+\permanent\protected\def\dostartrotation#1{\clf_startrotation#1\relax}
+\permanent\protected\def\dostoprotation   {\clf_stoprotation}
+
+% scaling
+
+% \permanent\protected\def\dostartscaling#1#2{\forcecolorhack\clf_startscaling rx #1 ry #2\relax}
+% \permanent\protected\def\dostopscaling     {\clf_stopscaling\forcecolorhack}
+
+\permanent\protected\def\dostartscaling#1#2{\clf_startscaling rx #1 ry #2\relax}
+\permanent\protected\def\dostopscaling     {\clf_stopscaling}
+
+% mirroring
+
+\permanent\protected\def\dostartmirroring{\clf_startmirroring}
+\permanent\protected\def\dostopmirroring {\clf_stopmirroring}
+
+% transform
+
+\permanent\protected\def\dotransformnextbox#1#2#3#4#5#6%
+  {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\permanent\protected\def\dodotransformnextbox#1#2#3#4#5#6%
+  {\hpack
+     {\kern #5\onebasepoint
+      \raise#6\onebasepoint
+      \hpack
+        {\clf_startmatrix rx #1 sx #2 sy #3 ry #4\relax
+         \box\nextbox
+         \clf_stopmatrix}}}
+
+%D \macros
+%D   {dostartclipping,dostopclipping}
+%D
+%D Clipping is implemented in such a way that an arbitrary code can be fed.
+%D
+%D \starttyping
+%D \dostartclipping {pathname} {width} {height}
+%D \dostopclipping
+%D \stoptyping
+
+\mutable\let\MPclippath\empty
+
+% \permanent\protected\def\dostartclipping#1#2#3% we can move this to lua and only set a box here
+%   {\forcecolorhack
+%    \meta_grab_clip_path{#1}{#2}{#3}%
+%    \clf_startclipping{\MPclippath}%
+%    \glet\MPclippath\empty}
+
+\permanent\protected\def\dostartclipping#1#2#3% we can move this to lua and only set a box here
+  {\meta_grab_clip_path{#1}{#2}{#3}%
+   \clf_startclipping{\MPclippath}%
+   \glet\MPclippath\empty}
+
+\permanent\protected\def\dostopclipping
+  {\clf_stopclipping}
+
+%D This wrapper is needed when you use code that messes with e.g. local color
+%D directives, invisible for the rest of the machinery. It's only needed in very
+%D special cases, like around the above scaler directives:
+
+\permanent\protected\edef\hcontainer{\hpack \s!direction\directionlefttoright \s!container\space}
+\permanent\protected\edef\vcontainer{\vpack \s!direction\directionlefttoright \s!container\space}
+\permanent\protected\edef\tcontainer{\tpack \s!direction\directionlefttoright \s!container\space}
+
+\protect \endinput
diff --git a/tex/context/base/mkxl/node-ini.mkxl b/tex/context/base/mkxl/node-ini.mkxl
index 09ac085c4..101f55c05 100644
--- a/tex/context/base/mkxl/node-ini.mkxl
+++ b/tex/context/base/mkxl/node-ini.mkxl
@@ -22,7 +22,6 @@
 \registerctxluafile{node-met}{autosuffix}
 \registerctxluafile{node-nut}{autosuffix}
 \registerctxluafile{node-res}{autosuffix}
-\registerctxluafile{node-ext}{autosuffix}
 %registerctxluafile{node-ppt}{} % experimental, not used so probably useless
 \registerctxluafile{node-aux}{autosuffix}
 \registerctxluafile{node-gcm}{autosuffix}
@@ -37,7 +36,6 @@
 \registerctxluafile{node-acc}{autosuffix} % experimental
 %registerctxluafile{node-prp}{} % makes no sense (yet)
 \registerctxluafile{node-scn}{autosuffix}
-\registerctxluafile{node-syn}{autosuffix}
 \registerctxluafile{node-par}{autosuffix}
 \registerctxluafile{node-bwc}{autosuffix} % for a while
 
diff --git a/tex/context/base/mkxl/node-pro.lmt b/tex/context/base/mkxl/node-pro.lmt
index 33f501aab..e09729ace 100644
--- a/tex/context/base/mkxl/node-pro.lmt
+++ b/tex/context/base/mkxl/node-pro.lmt
@@ -51,6 +51,7 @@ do
     local prependaction = tasks.prependaction
     local appendaction  = tasks.appendaction
     local enableaction  = tasks.enableaction
+    local disableaction = tasks.disableaction
 
     trackers.register("nodes.callbacks", function(v)
         if not v then
diff --git a/tex/context/base/mkxl/node-ref.lmt b/tex/context/base/mkxl/node-ref.lmt
index 2a2bf267f..269b2e749 100644
--- a/tex/context/base/mkxl/node-ref.lmt
+++ b/tex/context/base/mkxl/node-ref.lmt
@@ -7,15 +7,11 @@ if not modules then modules = { } end modules ['node-ref'] = {
     license   = "see context related readme files"
 }
 
--- We supported pdf right from the start and in mkii this has resulted in
--- extensive control over the links. Nowadays pdftex provides a lot more
--- control over margins but as mkii supports multiple backends we stuck to
--- our own mechanisms. In mkiv again we implement our own handling. Eventually
--- we will even disable the pdf primitives.
-
--- helper, will end up in luatex
-
--- is grouplevel still used?
+-- We supported pdf right from the start and in mkii this has resulted in extensive
+-- control over the links. Nowadays pdftex provides a lot more control over margins
+-- but as mkii supports multiple backends we stuck to our own mechanisms. In mkiv
+-- again we implement our own handling. Eventually we will even disable the pdf
+-- primitives.
 
 local tonumber = tonumber
 local concat = table.concat
@@ -49,6 +45,16 @@ local report_area          = logs.reporter("backend","areas")
 local texsetcount          = tex.setcount
 ----- texsetattribute      = tex.setattribute
 
+local injectreference      = backends.nodeinjections.reference
+local injectdestination    = backends.nodeinjections.destination
+local prerollreference     = backends.codeinjections.prerollreference
+
+updaters.register("backends.injections.latebindings",function()
+    injectreference   = backends.nodeinjections.reference
+    injectdestination = backends.nodeinjections.destination
+    prerollreference  = backends.codeinjections.prerollreference
+end)
+
 local nuts                 = nodes.nuts
 local nodepool             = nuts.pool
 
@@ -566,7 +572,7 @@ do
                 if depth  < dp then depth  = dp end
             end
          -- logs.report("temp","used: ht=%p dp=%p",height,depth)
-            local annot = nodeinjections.reference(reference,width,height,depth,set,resolved.mesh)
+            local annot = injectreference(reference,width,height,depth,set,resolved.mesh)
             if annot then
                 annot = tonut(annot) -- todo
                 nofreferences = nofreferences + 1
@@ -745,7 +751,7 @@ do
                 end
             end
             nofdestinations = nofdestinations + 1
-            local annot = nodeinjections.destination(width,height,depth,name,view)
+            local annot = injectdestination(width,height,depth,name,view)
             if annot then
                 annot = tonut(annot) -- obsolete soon
                 if result then
diff --git a/tex/context/base/mkxl/node-syn.mkxl b/tex/context/base/mkxl/node-syn.mkxl
new file mode 100644
index 000000000..5dcd624d6
--- /dev/null
+++ b/tex/context/base/mkxl/node-syn.mkxl
@@ -0,0 +1,20 @@
+%D \module
+%D   [       file=node-syn,
+%D        version=2006.08.20, % moved to separate module
+%D          title=\CONTEXT\ Node Macros,
+%D       subtitle=Synctex,
+%D         author=Hans Hagen,
+%D           date=\currentdate,
+%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{node-syn}{autosuffix}
+
+\unprotect
+
+%D There is nothing defined at the \TEX\ end.
+
+\protect \endinput
diff --git a/tex/context/base/mkxl/scrn-ref.mklx b/tex/context/base/mkxl/scrn-ref.mklx
index 63f76a092..d6fc6e127 100644
--- a/tex/context/base/mkxl/scrn-ref.mklx
+++ b/tex/context/base/mkxl/scrn-ref.mklx
@@ -20,11 +20,11 @@
 \appendtoks
     \doifsomething{\interactionparameter\c!calculate}%
         {\clf_setfieldcalculationset{\interactionparameter\c!calculate}}%
-    \doifelse{\interactionparameter\c!click  }\v!yes
+    \doifelse{\interactionparameter\c!click}\v!yes
         \settrue\setfalse\highlighthyperlinks
     \doifelse{\interactionparameter\c!display}\v!new
         \settrue\setfalse\gotonewwindow
-    \doifnot {\interactionparameter\c!page}\v!no
+    \doifnot{\interactionparameter\c!page}\v!no
         \scrn_reference_enable_page_destinations
 \to \everysetupinteraction
 
diff --git a/tex/context/base/mkxl/strc-lst.mklx b/tex/context/base/mkxl/strc-lst.mklx
index 2046be727..e01441875 100644
--- a/tex/context/base/mkxl/strc-lst.mklx
+++ b/tex/context/base/mkxl/strc-lst.mklx
@@ -1538,7 +1538,7 @@
 
 %D A helper:
 
-\def\strc_lists_limitated_text#text%
+\protected\def\strc_lists_limitated_text#text%
   {\edef\p_maxwidth{\listparameter\c!maxwidth}%
    \ifempty\p_maxwidth
      \listparameter\c!textcommand{#text}%
diff --git a/tex/context/interface/mkii/keys-en.xml b/tex/context/interface/mkii/keys-en.xml
index 3496d40b5..88cd1886b 100644
--- a/tex/context/interface/mkii/keys-en.xml
+++ b/tex/context/interface/mkii/keys-en.xml
@@ -82,6 +82,7 @@
 		<cd:variable name='anchor' value='anchor'/>
 		<cd:variable name='and' value='and'/>
 		<cd:variable name='answerarea' value='answerarea'/>
+		<cd:variable name='append' value='append'/>
 		<cd:variable name='appendices' value='appendices'/>
 		<cd:variable name='appendix' value='appendix'/>
 		<cd:variable name='april' value='april'/>
@@ -153,6 +154,7 @@
 		<cd:variable name='commands' value='commands'/>
 		<cd:variable name='comment' value='comment'/>
 		<cd:variable name='component' value='component'/>
+		<cd:variable name='compress' value='compress'/>
 		<cd:variable name='compressseparator' value='compressseparator'/>
 		<cd:variable name='compressstopper' value='compressstopper'/>
 		<cd:variable name='concept' value='concept'/>
@@ -189,6 +191,7 @@
 		<cd:variable name='enumeration' value='enumeration'/>
 		<cd:variable name='environment' value='environment'/>
 		<cd:variable name='even' value='even'/>
+		<cd:variable name='explicit' value='explicit'/>
 		<cd:variable name='export' value='export'/>
 		<cd:variable name='external' value='external'/>
 		<cd:variable name='extremestretch' value='extremestretch'/>
@@ -439,6 +442,7 @@
 		<cd:variable name='postscript' value='postscript'/>
 		<cd:variable name='precedingpage' value='precedingpage'/>
 		<cd:variable name='preference' value='preference'/>
+		<cd:variable name='prepend' value='prepend'/>
 		<cd:variable name='preview' value='preview'/>
 		<cd:variable name='previous' value='previous'/>
 		<cd:variable name='previousevenpage' value='previousevenpage'/>
@@ -1376,6 +1380,7 @@
 		<cd:element name='load' value='load'/>
 		<cd:element name='local' value='local'/>
 		<cd:element name='makeup' value='makeup'/>
+		<cd:element name='namednotation' value='namednotation'/>
 		<cd:element name='namedtyping' value='namedtyping'/>
 		<cd:element name='next' value='next'/>
 		<cd:element name='place' value='place'/>
@@ -1548,6 +1553,7 @@
 		<cd:command name='definereferencelist' value='definereferencelist'/>
 		<cd:command name='defineregister' value='defineregister'/>
 		<cd:command name='definerule' value='definerule'/>
+		<cd:command name='definesavebuffer' value='startsavebuffer'/>
 		<cd:command name='definesection' value='definesection'/>
 		<cd:command name='definesectionblock' value='definesectionblock'/>
 		<cd:command name='definesorting' value='definesorting'/>
@@ -1724,6 +1730,9 @@
 		<cd:command name='moveformula' value='moveformula'/>
 		<cd:command name='moveongrid' value='moveongrid'/>
 		<cd:command name='movesidefloat' value='movesidefloat'/>
+		<cd:command name='namedconstruction' value='namedconstruction'/>
+		<cd:command name='nameddescription' value='nameddescription'/>
+		<cd:command name='namedenumeration' value='namedenumeration'/>
 		<cd:command name='navigating' value='navigating'/>
 		<cd:command name='nodimension' value='nodimension'/>
 		<cd:command name='noheaderandfooterlines' value='noheaderandfooterlines'/>
@@ -2095,6 +2104,13 @@
 		<cd:command name='startmakeup' value='startmakeup'/>
 		<cd:command name='startmarginblock' value='startmarginblock'/>
 		<cd:command name='startmarginrule' value='startmarginrule'/>
+		<cd:command name='startnamedconstruction' value='startnamedconstruction'/>
+		<cd:command name='startnameddescription' value='startnameddescription'/>
+		<cd:command name='startnamedenumeration' value='startnamedenumeration'/>
+		<cd:command name='startnamedmatrix' value='startnamedmatrix'/>
+		<cd:command name='startnamedsection' value='startnamedsection'/>
+		<cd:command name='startnamedsubformulas' value='startnamedsubformulas'/>
+		<cd:command name='startnamedtyping' value='startnamedtyping'/>
 		<cd:command name='startnarrower' value='startnarrower'/>
 		<cd:command name='startopposite' value='startopposite'/>
 		<cd:command name='startoverlay' value='startoverlay'/>
@@ -2138,6 +2154,13 @@
 		<cd:command name='stopmakeup' value='stopmakeup'/>
 		<cd:command name='stopmarginblock' value='stopmarginblock'/>
 		<cd:command name='stopmarginrule' value='stopmarginrule'/>
+		<cd:command name='stopnamedconstruction' value='stopnamedconstruction'/>
+		<cd:command name='stopnameddescription' value='stopnameddescription'/>
+		<cd:command name='stopnamedenumeration' value='stopnamedenumeration'/>
+		<cd:command name='stopnamedmatrix' value='stopnamedmatrix'/>
+		<cd:command name='stopnamedsection' value='stopnamedsection'/>
+		<cd:command name='stopnamedsubformulas' value='stopnamedsubformulas'/>
+		<cd:command name='stopnamedtyping' value='stopnamedtyping'/>
 		<cd:command name='stopnarrower' value='stopnarrower'/>
 		<cd:command name='stopopposite' value='stopopposite'/>
 		<cd:command name='stopoverlay' value='stopoverlay'/>
diff --git a/tex/context/interface/mkii/keys-fr.xml b/tex/context/interface/mkii/keys-fr.xml
index 0149da566..9dd507c6a 100644
--- a/tex/context/interface/mkii/keys-fr.xml
+++ b/tex/context/interface/mkii/keys-fr.xml
@@ -191,6 +191,7 @@
 		<cd:variable name='enumeration' value='énumération'/>
 		<cd:variable name='environment' value='environnement'/>
 		<cd:variable name='even' value='paire'/>
+		<cd:variable name='explicit' value='explicit'/>
 		<cd:variable name='export' value='exporter'/>
 		<cd:variable name='external' value='externe'/>
 		<cd:variable name='extremestretch' value='etirementextreme'/>
diff --git a/tex/context/modules/mkxl/m-openstreetmap.lmt b/tex/context/modules/mkxl/m-openstreetmap.lmt
index 39a1d34d4..c8c6b4234 100644
--- a/tex/context/modules/mkxl/m-openstreetmap.lmt
+++ b/tex/context/modules/mkxl/m-openstreetmap.lmt
@@ -326,6 +326,7 @@ local colors = {
         water            = true,
         wetland          = true,
         wood             = true,
+        fault            = true,
     },
     barrier = {
         chain            = true,
@@ -483,7 +484,7 @@ local forcedlines = {
     historic  = { "citywalls" },
     leisure   = { "track", "slipway" },
     man_made  = { "breakwater", "cutline", "embankment", "groyne", "pipeline" },
-    natural   = { "cliff", "earth_bank", "tree_row", "ridge", "arete" },
+    natural   = { "cliff", "earth_bank", "tree_row", "ridge", "arete", "fault" },
     power     = { "cable", "line", "minor_line" },
     tourism   = { "yes"},
     waterway  = { "canal", "derelict_canal", "ditch", "drain", "river", "stream", "tidal_channel", "wadi", "weir" },
diff --git a/tex/context/modules/mkxl/m-openstreetmap.mkxl b/tex/context/modules/mkxl/m-openstreetmap.mkxl
index 29cf8eada..260734780 100644
--- a/tex/context/modules/mkxl/m-openstreetmap.mkxl
+++ b/tex/context/modules/mkxl/m-openstreetmap.mkxl
@@ -100,31 +100,31 @@
 
 \definecolor[osm:amenity:university]        [osm:university] % what color ... (obscures buildings)
 
-\definecolor[osm-amenity:bank]                   [osm:building:special]
-\definecolor[osm-amenity:bicycle_parking]        [osm:building:special]
-\definecolor[osm-amenity:bicycle_repair_station] [osm:building:special]
-\definecolor[osm-amenity:cafe]                   [osm:building:special]
-\definecolor[osm-amenity:car_wash]               [osm:building:special]
-\definecolor[osm-amenity:childcare]              [osm:building:special]
-\definecolor[osm-amenity:clinic]                 [osm:building:special]
-\definecolor[osm-amenity:clubhouse]              [osm:building:special]
-\definecolor[osm-amenity:college]                [osm:building:special]
-\definecolor[osm-amenity:community_centre]       [osm:building:special]
-\definecolor[osm-amenity:computer_lab]           [osm:building:special]
-\definecolor[osm-amenity:events_venue]           [osm:building:special]
-\definecolor[osm-amenity:fast_food]              [osm:building:special]
-\definecolor[osm-amenity:fire_station]           [osm:building:special]
-\definecolor[osm-amenity:fountain]               [osm:building:special]
-\definecolor[osm-amenity:fuel]                   [osm:building:special]
-\definecolor[osm-amenity:library]                [osm:building:special]
-\definecolor[osm-amenity:mailroom]               [osm:building:special]
-\definecolor[osm-amenity:pharmacy]               [osm:building:special]
-\definecolor[osm-amenity:place_of_worship]       [osm:building:special]
-\definecolor[osm-amenity:post_office]            [osm:building:special]
-\definecolor[osm-amenity:recycling]              [osm:building:special]
-\definecolor[osm-amenity:research_institute]     [osm:building:special]
-\definecolor[osm-amenity:theatre]                [osm:building:special]
-\definecolor[osm-amenity:wellness_centre]        [osm:building:special]
+\definecolor[osm:amenity:bank]                   [osm:building:special]
+\definecolor[osm:amenity:bicycle_parking]        [osm:building:special]
+\definecolor[osm:amenity:bicycle_repair_station] [osm:building:special]
+\definecolor[osm:amenity:cafe]                   [osm:building:special]
+\definecolor[osm:amenity:car_wash]               [osm:building:special]
+\definecolor[osm:amenity:childcare]              [osm:building:special]
+\definecolor[osm:amenity:clinic]                 [osm:building:special]
+\definecolor[osm:amenity:clubhouse]              [osm:building:special]
+\definecolor[osm:amenity:college]                [osm:building:special]
+\definecolor[osm:amenity:community_centre]       [osm:building:special]
+\definecolor[osm:amenity:computer_lab]           [osm:building:special]
+\definecolor[osm:amenity:events_venue]           [osm:building:special]
+\definecolor[osm:amenity:fast_food]              [osm:building:special]
+\definecolor[osm:amenity:fire_station]           [osm:building:special]
+\definecolor[osm:amenity:fountain]               [osm:building:special]
+\definecolor[osm:amenity:fuel]                   [osm:building:special]
+\definecolor[osm:amenity:library]                [osm:building:special]
+\definecolor[osm:amenity:mailroom]               [osm:building:special]
+\definecolor[osm:amenity:pharmacy]               [osm:building:special]
+\definecolor[osm:amenity:place_of_worship]       [osm:building:special]
+\definecolor[osm:amenity:post_office]            [osm:building:special]
+\definecolor[osm:amenity:recycling]              [osm:building:special]
+\definecolor[osm:amenity:research_institute]     [osm:building:special]
+\definecolor[osm:amenity:theatre]                [osm:building:special]
+\definecolor[osm:amenity:wellness_centre]        [osm:building:special]
 
 \definecolor[osm:area:yes]                  [osm:unknown]
 
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 05dfc4b94..c531fcd64 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
 -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
 -- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date  : 2021-10-15 13:57
+-- merge date  : 2021-10-18 23:11
 
 do -- begin closure to overcome local limits and interference
 
-- 
cgit v1.2.3