summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2021-01-24 16:24:42 +0100
committerContext Git Mirror Bot <phg@phi-gamma.net>2021-01-24 16:24:42 +0100
commitc80fc815f3b6db50716f9fe56f86ce068728221f (patch)
treeb8cb7a598c23a4758c48dd88be55ef849c8c76a8
parentdee0d939a50007dbe52f7035d67c01a78289e585 (diff)
downloadcontext-c80fc815f3b6db50716f9fe56f86ce068728221f.tar.gz
2021-01-24 16:05:00
-rw-r--r--metapost/context/base/mpxl/mp-lmtx.mpxl6
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin26122 -> 26124 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin255048 -> 255117 bytes
-rw-r--r--tex/context/base/mkxl/cont-new.mkxl2
-rw-r--r--tex/context/base/mkxl/context.mkxl3
-rw-r--r--tex/context/base/mkxl/font-mpf.lmt5
-rw-r--r--tex/context/base/mkxl/font-ogr.lmt1
-rw-r--r--tex/context/base/mkxl/font-tex.lmt151
-rw-r--r--tex/context/base/mkxl/font-tex.mkxl120
-rw-r--r--tex/context/base/mkxl/lpdf-emb.lmt40
-rw-r--r--tex/context/base/mkxl/strc-flt.mklx7
-rw-r--r--tex/context/modules/mkiv/m-ipsum.mkiv50
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua2
17 files changed, 364 insertions, 31 deletions
diff --git a/metapost/context/base/mpxl/mp-lmtx.mpxl b/metapost/context/base/mpxl/mp-lmtx.mpxl
index cfa169316..57794e544 100644
--- a/metapost/context/base/mpxl/mp-lmtx.mpxl
+++ b/metapost/context/base/mpxl/mp-lmtx.mpxl
@@ -2225,8 +2225,12 @@ newscriptindex mfid_registerglyph ; mfid_registerglyph := scriptindex "registe
vardef registercomposedglyph (expr u) (suffix snippets) =
save llx, lly, urx, ury ;
-snippets[u] := snippets[u] shifted (-xpart llcorner snippets[u], 0) ;
llx := xpart llcorner snippets[u] ;
+ if llx <> 0 :
+ % this should be an option or we need a lsb
+ snippets[u] := snippets[u] shifted (-llx, 0) ;
+ llx := 0;
+ fi ;
lly := ypart llcorner snippets[u] ;
urx := xpart urcorner snippets[u] ;
ury := ypart urcorner snippets[u] ;
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index 25c8ae59e..f0f145664 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.01.22 09:38}
+\newcontextversion{2021.01.24 16:02}
%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 440c698e7..9c05fd446 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.01.22 09:38}
+\edef\contextversion{2021.01.24 16:02}
%D For those who want to use this:
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 1dac6a5e0..27b0a995e 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.01.22 09:38}
+\newcontextversion{2021.01.24 16:02}
%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 a70ed6513..c6ba8b009 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -45,7 +45,7 @@
%D {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2021.01.22 09:38}
+\edef\contextversion{2021.01.24 16:02}
%D Kind of special:
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 5f7b6c7be..43ce46887 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index 17332430e..24aadd25d 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl
index ff33c5c5a..ce21a1b79 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.01.22 09:38}
+\newcontextversion{2021.01.24 16:02}
%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 54247cef5..6ca3eca99 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.01.22 09:38}
+\immutable\edef\contextversion{2021.01.24 16:02}
%overloadmode 1 % check frozen / warning
%overloadmode 2 % check frozen / error
@@ -389,6 +389,7 @@
\loadmklxfile{font-gds}
\loadmklxfile{font-aux}
\loadmklxfile{font-sel}
+\loadmkxlfile{font-tex}
\loadmkxlfile{typo-tal}
\loadmkxlfile{typo-par} % par builders (uses fonts)
diff --git a/tex/context/base/mkxl/font-mpf.lmt b/tex/context/base/mkxl/font-mpf.lmt
index b4dbd2b3b..b8a21788a 100644
--- a/tex/context/base/mkxl/font-mpf.lmt
+++ b/tex/context/base/mkxl/font-mpf.lmt
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['font-ogr'] = {
+if not modules then modules = { } end modules ['font-mpf'] = {
version = 1.001,
comment = "companion to font-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -14,10 +14,7 @@ local metapost = metapost
local metafonts = { }
metapost.metafonts = metafonts
-local fastserialize = table.fastserialize
local sortedhash = table.sortedhash
-local settings_to_hash = utilities.parsers.settings_to_hash
-local settings_to_array = utilities.parsers.settings_to_array
local addcharacters = fonts.constructors.addcharacters
local fontdata = fonts.hashes.identifiers
diff --git a/tex/context/base/mkxl/font-ogr.lmt b/tex/context/base/mkxl/font-ogr.lmt
index 1f37ec901..9c90bce49 100644
--- a/tex/context/base/mkxl/font-ogr.lmt
+++ b/tex/context/base/mkxl/font-ogr.lmt
@@ -253,7 +253,6 @@ do
tfmdata.colrshapes = colrshapes
tfmdata.dropindex = idx
tfmdata.dropslot = slot
- return
end
end
diff --git a/tex/context/base/mkxl/font-tex.lmt b/tex/context/base/mkxl/font-tex.lmt
new file mode 100644
index 000000000..ba356bc29
--- /dev/null
+++ b/tex/context/base/mkxl/font-tex.lmt
@@ -0,0 +1,151 @@
+if not modules then modules = { } end modules ['font-mpf'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local formatters = string.formatters
+local sortedhash = table.sortedhash
+
+local addcharacters = fonts.constructors.addcharacters
+local fontdata = fonts.hashes.identifiers
+
+local otf = fonts.handlers.otf
+local otfregister = otf.features.register
+
+----- getshapes = fonts.dropins.getshapes
+
+local register = fonts.collections.register
+local checkenabled = fonts.collections.checkenabled
+local newprivateslot = fonts.helpers.newprivateslot
+
+local currentfont = font.current
+
+-- hm, seems to gobble the first \char
+
+local makesetups = formatters["box:%s:%S"]
+
+local function makeglyphbox(char,spec)
+ token.expand_macro("makeglyphbox",true,spec.setups or tostring(char))
+ local b = tex.takebox("glyphbox")
+ spec.code = {
+ width = b.width,
+ height = b.height,
+ depth = b.depth,
+ objnum = tex.saveboxresource(b,nil,nil,true),
+ }
+end
+
+local function setboxglyphs(category,fontid,unicode,specification)
+ local box = specification.code
+ if unicode and box then
+ local tfmdata = fontdata[fontid]
+ local characters = tfmdata.characters
+ local newdata = {
+ width = box.width or 0,
+ height = box.height or 0,
+ depth = box.depth or 0,
+ unicode = unicode,
+ }
+ -- pass dimensions to lua
+ characters[unicode] = newdata
+ -- this also adapts newdata (add commands)
+ fonts.dropins.swapone("box",tfmdata,specification,unicode)
+ -- pass dimensions to tex
+ addcharacters(fontid, { characters = { [unicode] = newdata } })
+ return fontid, unicode
+ else
+ logs.report("box glyph", "invalid glyph box for %C",unicode)
+ end
+end
+
+local function setboxglyph(specification)
+ if specification then
+ local name = specification.name
+ if name then
+ local private = newprivateslot(name)
+ local font = currentfont()
+ if not specification.setups then
+ specification.setups = name
+ end
+ -- we can actually delay font if needed
+ register(font,private,function(font,private)
+ makeglyphbox(private,specification)
+ return setboxglyphs(category,font,private,specification)
+ end)
+ checkenabled()
+ end
+ end
+end
+
+local boxes = table.setmetatableindex("table")
+
+function fonts.helpers.registerglyphbox(specification)
+ local category = specification.category
+ local whatever = specification.unicode or specification.name
+ if category and whatever then
+ boxes[category][whatever] = { action = makeglyphbox } -- always
+ end
+end
+
+local function initializebox(tfmdata,kind,value)
+ local boxes = boxes[value]
+ if value then
+ local font = tfmdata.properties.id
+ -- just preregister the list
+ for char, spec in sortedhash(boxes) do
+ spec.setups = makesetups(value,char)
+ if type(char) == "string" then
+ char = newprivateslot(name)
+ end
+ -- check if spec.code
+ register(font,char,function(font,char)
+ local action = spec.action
+ if type(action) == "function" then
+ action(char,spec)
+ end
+ return setboxglyphs(value,font,char,spec)
+ end)
+ end
+ checkenabled()
+ end
+end
+
+fonts.helpers.setboxglyphs = setboxglyphs
+fonts.helpers.setboxglyph = setboxglyph
+
+interfaces.implement {
+ name = "registerboxglyph", -- combine with next one
+ public = true,
+ protected = true,
+ actions = fonts.helpers.registerglyphbox,
+ arguments = { {
+ { "category" },
+ { "unicode", "integer" },
+ { "name" },
+ } },
+}
+
+interfaces.implement {
+ name = "setboxglyph",
+ public = true,
+ protected = true,
+ actions = setboxglyph,
+ arguments = { { "*" } },
+}
+
+fonts.handlers.otf.features.register {
+ name = "box",
+ description = "box glyphs",
+ manipulators = {
+ base = initializebox,
+ node = initializebox,
+ }
+}
+
+-- fonts.helpers.registerboxglyph { category = "demo", unicode = 103 }
+-- fonts.helpers.registerboxglyph { category = "demo", unicode = 104 }
+-- fonts.helpers.registerboxglyph { category = "demo", unicode = 105 }
+-- fonts.helpers.registerboxglyph { category = "demo", unicode = 106 }
diff --git a/tex/context/base/mkxl/font-tex.mkxl b/tex/context/base/mkxl/font-tex.mkxl
new file mode 100644
index 000000000..957b28916
--- /dev/null
+++ b/tex/context/base/mkxl/font-tex.mkxl
@@ -0,0 +1,120 @@
+%D \module
+%D [ file=font-tex,
+%D version=2021.23.01,
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=\TEX\ Glyphs,
+%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.
+
+\writestatus{loading}{ConTeXt Font Macros / TeX Glyphs}
+
+\registerctxluafile{font-tex}{autosuffix}
+
+%D This mechanism turns boxes into glyphs. Of course this assumes that the
+%D backend code supports it. It's an experiment and we can do similar things
+%D with \METAPOST. The interface is not frozen and might change and evolve.
+
+%D \starttyping
+%D \starttext
+%D
+%D \startsetups box:demo:103
+%D \externalfigure[t:/sources/cow-brown.pdf][height=12pt]
+%D \stopsetups
+%D
+%D \startsetups box:demo:104
+%D \externalfigure[t:/sources/cow-black.pdf][height=10pt]
+%D \stopsetups
+%D
+%D \startsetups box:demo:105
+%D \externalfigure[t:/sources/mill.png][height=12pt]
+%D \stopsetups
+%D
+%D \startsetups box:demo:106
+%D \externalfigure[t:/sources/hacker.jpg][height=12pt]
+%D \stopsetups
+%D
+%D \registerboxglyph category {demo} unicode 103 \relax % rather low level for now
+%D \registerboxglyph category {demo} unicode 104 \relax % rather low level for now
+%D \registerboxglyph category {demo} unicode 105 \relax % rather low level for now
+%D \registerboxglyph category {demo} unicode 106 \relax % rather low level for now
+%D
+%D \definefontfeature[whatever][box=demo]
+%D
+%D \definedfont[Serif*whatever]
+%D
+%D % \enabletrackers[fonts.collecting]
+%D
+%D \startTEXpage%[offset=0pt]
+%D %\hbox{g}%
+%D \hbox{\char103}%
+%D \hbox{\char104}%
+%D \stopTEXpage
+%D
+%D \startsetups box:demo:whatever
+%D \startMPcode
+%D picture p ; p := image (draw figure "t:/sources/hacker.jpg" ysized 10pt);
+%D fill boundingbox p enlarged .5pt randomized 2pt withcolor "darkgray" ;
+%D clip p to boundingbox p enlarged -1pt randomized 2pt ;
+%D draw p ;
+%D \stopMPcode
+%D \stopsetups
+%D
+%D % in current font!
+%D
+%D \iffontchar\font\privatecharactercode{demo:whatever}\else
+%D \setboxglyph {
+%D category {demo}
+%D name {demo:whatever}
+%D setups {box:demo:whatever}
+%D }%
+%D \fi
+%D
+%D \startTEXpage[offset=10pt]
+%D \char\privatecharactercode{demo:whatever}%
+%D \stopTEXpage
+%D
+%D \startTEXpage%[offset=0pt]
+%D \ruledhbox{\char103}
+%D \ruledhbox{\char104}
+%D \ruledhbox{\char105}
+%D \ruledhbox{\char106}
+%D \stopTEXpage
+%D
+%D \dorecurse{1000}{
+%D \char 103\relax \space
+%D \char 104\relax \space
+%D \char 105\relax \space
+%D \char 106\relax \space
+%D }
+%D
+%D \page
+%D
+%D \setupalign[verytolerant,flushleft]
+%D
+%D \dorecurse{100}{
+%D #1:
+%D \glyph yoffset -2pt `i\relax
+%D \glyph yoffset -3pt `j\relax\space
+%D }
+%D \stoptext
+%D \stoptyping
+
+\newbox\glyphbox
+
+% somehow makes the first \char disappear
+%
+% \permanent\protected\def\makeglyphbox#1%
+% {\setbox\glyphbox\hbox{\directsetup{#1}}}
+%
+% so we group:
+
+\permanent\protected\def\makeglyphbox#1%
+ {\begingroup
+ \global\setbox\glyphbox\hbox{\directsetup{#1}}%
+ % \writestatus{glyphbox}{#1 => (\the\wd\glyphbox,\the\ht\glyphbox,\the\dp\glyphbox)}%
+ \endgroup}
diff --git a/tex/context/base/mkxl/lpdf-emb.lmt b/tex/context/base/mkxl/lpdf-emb.lmt
index 796b9dfd1..a4fcb1b6b 100644
--- a/tex/context/base/mkxl/lpdf-emb.lmt
+++ b/tex/context/base/mkxl/lpdf-emb.lmt
@@ -1504,12 +1504,16 @@ do
local f_stream = formatters["%.6N 0 d0 %s"]
local f_stream_c = formatters["%.6N 0 0 0 0 0 d1 %s"]
local f_stream_d = formatters["%.6N 0 d0 1 0 0 1 0 %.6N cm %s"]
+ local f_stream_s = formatters["%N 0 0 %N 0 0 cm /%s Do"]
-- A type 3 font has at most 256 characters and Acrobat also wants a zero slot
-- to be filled. We can share a mandate zero slot character. We also need to
-- make sure that we use bytes as index in the page stream as well as in the
-- tounicode vector.
+ -- All this type three magic is a tribute to Don Knuth who uses bitmap fonts in
+ -- his books.
+
local c_notdef = nil
local r_notdef = nil
local w_notdef = nil
@@ -1542,6 +1546,12 @@ do
local used = setmetatableindex("table")
+ function lpdf.registerfontmethod(name,f)
+ if f and not methods[name] then
+ methods[name] = f
+ end
+ end
+
function methods.pdf(filename,details)
local properties = details.properties
local pdfshapes = properties.indexdata[1]
@@ -1601,6 +1611,36 @@ do
end
end
+ -- box inclusion (todo: we can share identical glyphs if needed but the gain
+ -- is minimal especially when we use compact font mode)
+
+ lpdf.registerfontmethod("box",function(filename,details)
+ local properties = details.properties
+ local boxes = properties.indexdata[1]
+ local xforms = pdfdictionary()
+ local nofglyphs = 0
+ local scale = 10 * details.parameters.size/details.parameters.designsize
+ local units = details.parameters.units
+ local function boxtopdf(image,data) -- image == glyph
+ nofglyphs = nofglyphs + 1
+ local scale = units / scale -- e.g. 1000 / 12
+ local width = (data.width or 0) * bpfactor * scale
+ local name = f_glyph(nofglyphs)
+ local stream = f_stream_s(scale,scale,name)
+ image.embedded_name = name
+ image.embedded_stream = stream
+ image.embedded_reference = pdfreference(image.objnum)
+ xforms[name] = image.embedded_reference
+ return f_image_w(width,stream), width
+ end
+ local function wrapup()
+ end
+ local function getresources()
+ return pdfdictionary { XObject = xforms }
+ end
+ return boxes, 1/units, boxtopdf, wrapup, getresources
+ end)
+
-- mps inclusion
local decompress = gzip.decompress
diff --git a/tex/context/base/mkxl/strc-flt.mklx b/tex/context/base/mkxl/strc-flt.mklx
index 58c72c0fc..f5d2b3c97 100644
--- a/tex/context/base/mkxl/strc-flt.mklx
+++ b/tex/context/base/mkxl/strc-flt.mklx
@@ -1576,7 +1576,12 @@
{\bgroup
\strc_floats_set_local_hsize
\ifcase\c_strc_floats_rotation\else
- \swapdimens\hsize\vsize
+ % Swapping fails in overloadmode and is also wrong (as it then is persistent due
+ % to global being inherited).
+ %\swapdimens\hsize\vsize
+ \scratchdimen\hsize
+ \hsize\vsize
+ \vsize\scratchdimen
\fi
\forgetall
\postponenotes
diff --git a/tex/context/modules/mkiv/m-ipsum.mkiv b/tex/context/modules/mkiv/m-ipsum.mkiv
index 7ba78ee2e..7b5074a49 100644
--- a/tex/context/modules/mkiv/m-ipsum.mkiv
+++ b/tex/context/modules/mkiv/m-ipsum.mkiv
@@ -101,6 +101,23 @@ function moduledata.ipsum.direct(settings)
end
end
+interfaces.implement {
+ name = "ipsum",
+ protected = true,
+ actions = moduledata.ipsum.typeset,
+ arguments = { {
+ { "alternative" },
+ { "filename" },
+ { "n" },
+ { "left" },
+ { "right" },
+ { "before" },
+ { "after" },
+ { "inbetween" },
+ { "separator" },
+ } },
+}
+
\stopluacode
\unprotect
@@ -129,26 +146,25 @@ end
\useipsumstyleandcolor\c!style\c!color
% hm, also changes dates
\uselanguageparameter\ipsumparameter
- \ctxlua{moduledata.ipsum.typeset {
- alternative = "\ipsumparameter\c!alternative",
- filename = "\ipsumparameter\c!file",
- n = "\ipsumparameter\c!n",
- left = "\luaescapestring{\ipsumparameter\c!left}",
- right = "\luaescapestring{\ipsumparameter\c!right}",
- before = "\luaescapestring{\ipsumparameter\c!before}",
- after = "\luaescapestring{\ipsumparameter\c!after}",
- inbetween = "\luaescapestring{\ipsumparameter\c!inbetween}",
- }}
+ \clf_ipsum
+ alternative {\ipsumparameter\c!alternative}
+ filename {\ipsumparameter\c!file}
+ n {\ipsumparameter\c!n}
+ left {\ipsumparameter\c!left}
+ right {\ipsumparameter\c!right}
+ before {\ipsumparameter\c!before}
+ after {\ipsumparameter\c!after}
+ inbetween {\ipsumparameter\c!inbetween}
+ \relax
\stopsetups
\def\directipsum#1% only one argument, expanded
- {\ctxlua{moduledata.ipsum.typeset {
- alternative = "\namedipsumparameter{#1}\c!alternative",
- filename = "\namedipsumparameter{#1}\c!file",
- n = "\namedipsumparameter{#1}\c!n",
- separator = "\luaescapestring{\ipsumparameter\c!separator}",
- }}
-}
+ {\clf_ipsum
+ alternative {\namedipsumparameter{#1}\c!alternative}
+ filename {\namedipsumparameter{#1}\c!file}
+ n {\namedipsumparameter{#1}\c!n}
+ separator {\ipsumparameter\c!separator}
+ \relax}
\protect
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 5ad418348..70c8a7ecc 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-01-22 09:38
+-- merge date : 2021-01-24 16:02
do -- begin closure to overcome local limits and interference