summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2021-01-17 22:49:53 +0100
committerContext Git Mirror Bot <phg@phi-gamma.net>2021-01-17 22:49:53 +0100
commit95686a1754b3cf4f1410d6a52aeb86b65033a96c (patch)
treee5a5b9c091e2722d8bc7b20d3ad0952055b70dab /tex
parent980ad5b78d69aa8abfb093c7e6729b0024ce0b49 (diff)
downloadcontext-95686a1754b3cf4f1410d6a52aeb86b65033a96c.tar.gz
2021-01-17 21:42:00
Diffstat (limited to 'tex')
-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/font-imp-math.lua28
-rw-r--r--tex/context/base/mkiv/font-imp-tracing.lua104
-rw-r--r--tex/context/base/mkiv/font-pre.mkiv1
-rw-r--r--tex/context/base/mkiv/good-mth.lua167
-rw-r--r--tex/context/base/mkiv/math-act.lua113
-rw-r--r--tex/context/base/mkiv/mult-fun.lua2
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin26131 -> 26114 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin254409 -> 254915 bytes
-rw-r--r--tex/context/base/mkiv/strc-mar.lua2
-rw-r--r--tex/context/base/mkiv/task-ini.lua1
-rw-r--r--tex/context/base/mkxl/anch-pos.lmt7
-rw-r--r--tex/context/base/mkxl/attr-alt.lmt111
-rw-r--r--tex/context/base/mkxl/attr-alt.mkxl55
-rw-r--r--tex/context/base/mkxl/attr-eff.mkxl4
-rw-r--r--tex/context/base/mkxl/attr-ini.mkxl1
-rw-r--r--tex/context/base/mkxl/back-ext.mkxl (renamed from tex/context/base/mkxl/back-trf.mkxl)14
-rw-r--r--tex/context/base/mkxl/back-ini.lmt30
-rw-r--r--tex/context/base/mkxl/back-out.lmt255
-rw-r--r--tex/context/base/mkxl/back-out.mkxl22
-rw-r--r--tex/context/base/mkxl/back-pdf.mkxl1
-rw-r--r--tex/context/base/mkxl/back-trf.lmt164
-rw-r--r--tex/context/base/mkxl/colo-nod.lmt6
-rw-r--r--tex/context/base/mkxl/cont-new.mkxl2
-rw-r--r--tex/context/base/mkxl/context.mkxl10
-rw-r--r--tex/context/base/mkxl/driv-shp.lmt656
-rw-r--r--tex/context/base/mkxl/font-chk.lmt1
-rw-r--r--tex/context/base/mkxl/font-con.lmt36
-rw-r--r--tex/context/base/mkxl/font-fbk.lmt9
-rw-r--r--tex/context/base/mkxl/font-imp-math.lmt31
-rw-r--r--tex/context/base/mkxl/font-imp-tracing.lmt286
-rw-r--r--tex/context/base/mkxl/font-lib.mklx6
-rw-r--r--tex/context/base/mkxl/font-ogr.lmt69
-rw-r--r--tex/context/base/mkxl/font-pre.mkxl4
-rw-r--r--tex/context/base/mkxl/font-vfc.lmt108
-rw-r--r--tex/context/base/mkxl/good-mth.lmt464
-rw-r--r--tex/context/base/mkxl/layo-ini.lmt115
-rw-r--r--tex/context/base/mkxl/layo-ini.mkxl2
-rw-r--r--tex/context/base/mkxl/lpdf-col.lmt170
-rw-r--r--tex/context/base/mkxl/lpdf-ini.lmt29
-rw-r--r--tex/context/base/mkxl/lpdf-lmt.lmt231
-rw-r--r--tex/context/base/mkxl/lpdf-mis.lmt79
-rw-r--r--tex/context/base/mkxl/lpdf-ren.lmt12
-rw-r--r--tex/context/base/mkxl/lpdf-rul.lmt8
-rw-r--r--tex/context/base/mkxl/lpdf-tag.lmt16
-rw-r--r--tex/context/base/mkxl/lpdf-vfc.lmt42
-rw-r--r--tex/context/base/mkxl/math-act.lmt480
-rw-r--r--tex/context/base/mkxl/math-ali.mkxl2
-rw-r--r--tex/context/base/mkxl/math-ini.mkxl2
-rw-r--r--tex/context/base/mkxl/math-noa.lmt9
-rw-r--r--tex/context/base/mkxl/meta-imp-punk.mkxl272
-rw-r--r--tex/context/base/mkxl/mlib-mpf.lmt7
-rw-r--r--tex/context/base/mkxl/node-ext.lmt650
-rw-r--r--tex/context/base/mkxl/node-fin.lmt76
-rw-r--r--tex/context/base/mkxl/node-ini.lmt46
-rw-r--r--tex/context/base/mkxl/node-ini.mkxl4
-rw-r--r--tex/context/base/mkxl/node-res.lmt41
-rw-r--r--tex/context/base/mkxl/node-syn.lmt782
-rw-r--r--tex/context/base/mkxl/node-tra.lmt2
-rw-r--r--tex/context/base/mkxl/page-lin.lmt2
-rw-r--r--tex/context/base/mkxl/scrn-pag.lmt56
-rw-r--r--tex/context/base/mkxl/scrn-pag.mklx2
-rw-r--r--tex/context/base/mkxl/spac-hor.mkxl35
-rw-r--r--tex/context/base/mkxl/strc-reg.mkxl14
-rw-r--r--tex/context/base/mkxl/trac-vis.lmt48
-rw-r--r--tex/context/base/mkxl/typo-cap.lmt23
-rw-r--r--tex/context/fonts/mkiv/bonum-math.lfg22
-rw-r--r--tex/context/fonts/mkiv/dejavu-math.lfg15
-rw-r--r--tex/context/fonts/mkiv/minion-math.lfg10
-rw-r--r--tex/context/fonts/mkiv/pagella-math.lfg24
-rw-r--r--tex/context/fonts/mkiv/schola-math.lfg16
-rw-r--r--tex/context/fonts/mkiv/termes-math.lfg22
-rw-r--r--tex/context/fonts/mkiv/type-imp-punk.mkxl54
-rw-r--r--tex/context/fonts/mkiv/type-imp-texgyre.mkiv16
-rw-r--r--tex/context/fonts/mkiv/xits-math.lfg1
-rw-r--r--tex/context/modules/mkiv/m-punk.mkiv5
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua2
80 files changed, 4552 insertions, 1670 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index d06fbe463..6c1dca8a2 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.11 16:28}
+\newcontextversion{2021.01.17 21:39}
%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 c36274955..dbe4e4249 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.11 16:28}
+\edef\contextversion{2021.01.17 21:39}
%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 49c850c9b..d8dfa0fa2 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.11 16:28}
+\newcontextversion{2021.01.17 21:39}
%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 93744dfda..8e697e850 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.11 16:28}
+\edef\contextversion{2021.01.17 21:39}
%D Kind of special:
diff --git a/tex/context/base/mkiv/font-imp-math.lua b/tex/context/base/mkiv/font-imp-math.lua
index ed82fcc48..d2294e93c 100644
--- a/tex/context/base/mkiv/font-imp-math.lua
+++ b/tex/context/base/mkiv/font-imp-math.lua
@@ -80,6 +80,34 @@ registerotffeature {
}
}
+function fonts.helpers.mathscriptslots(tfmdata,textcode)
+ local rawdata = tfmdata.shared.rawdata
+ local rawresources = rawdata and rawdata.resources
+ local rawfeatures = rawresources and rawresources.features
+ local basesubstitutions = rawfeatures and rawfeatures.gsub
+ local sequences = basesubstitutions and tfmdata.resources.sequences
+ if sequences then
+ local characters = tfmdata.characters
+ if characters[textcode] then
+ for s=1,#sequences do
+ local sequence = sequences[s]
+ local sfeatures = sequence.features
+ if sfeatures and sfeatures.ssty then
+ local steps = sequence.steps
+ for i=1,#steps do
+ local coverage = steps[i].coverage
+ if coverage then
+ local okay = coverage[textcode]
+ if okay then
+ return okay
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
local function initialize(tfmdata,key,value)
if value then
local rawdata = tfmdata.shared.rawdata
diff --git a/tex/context/base/mkiv/font-imp-tracing.lua b/tex/context/base/mkiv/font-imp-tracing.lua
index 1acf14558..255b4cdf0 100644
--- a/tex/context/base/mkiv/font-imp-tracing.lua
+++ b/tex/context/base/mkiv/font-imp-tracing.lua
@@ -139,107 +139,3 @@ local specification = {
registerotffeature(specification)
registerafmfeature(specification)
-
-local f_m = formatters["%F %F m"]
-local f_l = formatters["%F %F l"]
-local f_b = formatters["[] 0 d 0 J %.6F w"]
-local f_e = formatters["s"]
-
-local function ladder(list,docolor,nocolor,lst,offset,sign,default)
- local l = lst[1]
- local x1 = bp * (offset + l.kern) * sign
- local y1 = bp * l.height
- local t = { f_b(r,r/2), f_m(x1,y1) }
- local n = 2
- local m = #lst
- if default > 0 then
- default = default * bp + r
- else
- default = default * bp - r
- end
- if m == 1 then
- n = n + 1 t[n] = f_l(x1,default)
- else
- for i=1,m do
- local l = lst[i]
- local x2 = bp * (offset + l.kern) * sign
- local y2 = bp * l.height
- if i > 1 and y2 == 0 then
- y2 = default
- end
- n = n + 1 t[n] = f_l(x2,y1)
- n = n + 1 t[n] = f_l(x2,y2)
- x1, y1 = x2, y2
- end
- end
- n = n + 1 t[n] = f_e()
- list[#list+1] = docolor
- list[#list+1] = { "pdf", "origin", concat(t," ") }
- list[#list+1] = nocolor
-end
-
-local function initialize(tfmdata,key,value)
- if value then
- if not backcolors then
- local vfspecials = backends.pdf.tables.vfspecials
- startcolor = vfspecials.startcolor
- stopcolor = vfspecials.stopcolor
- end
- local characters = tfmdata.characters
- local brcolor = startcolor("darkred")
- local trcolor = startcolor("darkgreen")
- local blcolor = startcolor("darkblue")
- local tlcolor = startcolor("darkyellow")
- local black = stopcolor
- for unicode, character in next, characters do
- local mathkern = character.mathkern
- if mathkern then
- -- more efficient would be co collect more in one pdf
- -- directive but this is hardly used so not worth the
- -- effort
- local width = character.width or 0
- local height = character.height or 0
- local depth = character.depth or 0
- local list = { }
- local br = mathkern.bottom_right
- local tr = mathkern.top_right
- local bl = mathkern.bottom_left
- local tl = mathkern.top_left
- if br then
- ladder(list,brcolor,black,br,width,1,height)
- end
- if tr then
- ladder(list,trcolor,black,tr,width,1,-depth)
- end
- if bl then
- ladder(list,blcolor,black,bl,0,-1,height)
- end
- if tl then
- ladder(list,tlcolor,black,tl,0,-1,-depth)
- end
- if #list > 0 then
- local commands = character.commands
- if commands then
- character.commands = appendcommandtable(commands,list)
- else
- list[#list+1] = charcommand[unicode]
- character.commands = list
- end
- end
- end
- end
- end
-end
-
-local specification = {
- name = "staircase",
- description = "show staircase kerns",
- position=1,
- manipulators = {
- base = initialize,
- node = initialize,
- }
-}
-
-registerotffeature(specification)
-registerafmfeature(specification)
diff --git a/tex/context/base/mkiv/font-pre.mkiv b/tex/context/base/mkiv/font-pre.mkiv
index c32690375..445dedd25 100644
--- a/tex/context/base/mkiv/font-pre.mkiv
+++ b/tex/context/base/mkiv/font-pre.mkiv
@@ -405,6 +405,7 @@
mathalternates=yes,
mathitalics=yes, % we pass them
mathdimensions=all,
+ % mathkerns=yes,
% mathgaps=yes,
language=dflt,
script=math]
diff --git a/tex/context/base/mkiv/good-mth.lua b/tex/context/base/mkiv/good-mth.lua
index b85e680cc..3473cc205 100644
--- a/tex/context/base/mkiv/good-mth.lua
+++ b/tex/context/base/mkiv/good-mth.lua
@@ -6,8 +6,9 @@ if not modules then modules = { } end modules ['good-mth'] = {
license = "see context related readme files"
}
-local type, next = type, next
+local type, next, tonumber, unpack = type, next, tonumber, unpack
local ceil = math.ceil
+local match = string.match
local fonts = fonts
@@ -20,6 +21,10 @@ local fontgoodies = fonts.goodies or { }
local fontcharacters = fonts.hashes.characters
+local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end)
+
+local report_math = logs.reporter("mathematics","initializing")
+
local nuts = nodes.nuts
local setlink = nuts.setlink
@@ -33,11 +38,149 @@ local new_vlist = nodepool.vlist
local insert_node_after = nuts.insert_after
+local helpers = fonts.helpers
+local upcommand = helpers.commands.up
+local rightcommand = helpers.commands.right
+local charcommand = helpers.commands.char
+local prependcommands = helpers.prependcommands
+
-- experiment, we have to load the definitions immediately as they precede
-- the definition so they need to be initialized in the typescript
+local function withscriptcode(tfmdata,unicode,data,action)
+ if type(unicode) == "string" then
+ local p, u = match(unicode,"^(.-):(.-)$")
+ if u then
+ u = tonumber(u)
+ if u then
+ local slots = fonts.helpers.mathscriptslots(tfmdata,u)
+ if slots then
+ if p == "*" then
+ action(u,data)
+ for i=1,#slots do
+ action(slots[i],data)
+ end
+ else
+ p = tonumber(p)
+ if p then
+ action(slots[p],data)
+ end
+ end
+ end
+ end
+ end
+ else
+ action(unicode,data)
+ end
+end
+
local function finalize(tfmdata,feature,value)
- mathematics.overloaddimensions(tfmdata,tfmdata,value)
+-- if tfmdata.mathparameters then -- funny, cambria text has this
+ local goodies = tfmdata.goodies
+ if goodies then
+ local virtualized = mathematics.virtualized
+ for i=1,#goodies do
+ local goodie = goodies[i]
+ local mathematics = goodie.mathematics
+ local dimensions = mathematics and mathematics.dimensions
+ if dimensions then
+ if trace_defining then
+ report_math("overloading dimensions in %a @ %p",tfmdata.properties.fullname,tfmdata.parameters.size)
+ end
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local parameters = tfmdata.parameters
+ local factor = parameters.factor
+ local hfactor = parameters.hfactor
+ local vfactor = parameters.vfactor
+ local function overloadone(unicode,data)
+ local character = characters[unicode]
+ if not character then
+ local c = virtualized[unicode]
+ if c then
+ character = characters[c]
+ end
+ end
+ if character then
+ local width = data.width
+ local height = data.height
+ local depth = data.depth
+ if trace_defining and (width or height or depth) then
+ report_math("overloading dimensions of %C, width %p, height %p, depth %p",
+ unicode,width or 0,height or 0,depth or 0)
+ end
+ if width then character.width = width * hfactor end
+ if height then character.height = height * vfactor end
+ if depth then character.depth = depth * vfactor end
+ --
+ local xoffset = data.xoffset
+ local yoffset = data.yoffset
+ if xoffset == "llx" then
+ local d = descriptions[unicode]
+ if d then
+ xoffset = - d.boundingbox[1] * hfactor
+ character.width = character.width + xoffset
+ xoffset = rightcommand[xoffset]
+ else
+ xoffset = nil
+ end
+ elseif xoffset and xoffset ~= 0 then
+ xoffset = rightcommand[xoffset * hfactor]
+ else
+ xoffset = nil
+ end
+ if yoffset and yoffset ~= 0 then
+ yoffset = upcommand[yoffset * vfactor]
+ else
+ yoffset = nil
+ end
+ if xoffset or yoffset then
+ local commands = characters.commands
+ if commands then
+ prependcommands(commands,yoffset,xoffset)
+ else
+ local slot = charcommand[unicode]
+ if xoffset and yoffset then
+ character.commands = { xoffset, yoffset, slot }
+ elseif xoffset then
+ character.commands = { xoffset, slot }
+ else
+ character.commands = { yoffset, slot }
+ end
+ end
+ end
+ elseif trace_defining then
+ report_math("no overloading dimensions of %C, not in font",unicode)
+ end
+ end
+ local function overload(dimensions)
+ for unicode, data in next, dimensions do
+ withscriptcode(tfmdata,unicode,data,overloadone)
+ end
+ end
+ if value == nil then
+ value = { "default" }
+ end
+ if value == "all" or value == true then
+ for name, value in next, dimensions do
+ overload(value)
+ end
+ else
+ if type(value) == "string" then
+ value = utilities.parsers.settings_to_array(value)
+ end
+ if type(value) == "table" then
+ for i=1,#value do
+ local d = dimensions[value[i]]
+ if d then
+ overload(d)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
end
registerotffeature {
@@ -77,10 +220,11 @@ end
fontgoodies.register("mathematics", initialize)
-local enabled = false directives.register("fontgoodies.mathkerning",function(v) enabled = v end)
+-- local enabled = false directives.register("fontgoodies.mathkerning",function(v) enabled = v end)
local function initialize(tfmdata)
- if enabled and tfmdata.mathparameters then -- funny, cambria text has this
+-- if enabled and tfmdata.mathparameters then -- funny, cambria text has this
+ if tfmdata.mathparameters then -- funny, cambria text has this
local goodies = tfmdata.goodies
if goodies then
local characters = tfmdata.characters
@@ -91,12 +235,15 @@ local function initialize(tfmdata)
if mathgoodies then
local kerns = mathgoodies.kerns
if kerns then
- for unicode, specification in next, kerns do
+ local function kernone(unicode,data)
local chardata = characters[unicode]
- if chardata and (not chardata.mathkerns or specification.force) then
- chardata.mathkerns = specification
+ if chardata and (not chardata.mathkerns or data.force) then
+ chardata.mathkerns = data
end
end
+ for unicode, data in next, kerns do
+ withscriptcode(tfmdata,unicode,data,kernone)
+ end
return
end
end
@@ -109,9 +256,9 @@ local function initialize(tfmdata)
end
registerotffeature {
- name = "mathkerns",
- description = "math kerns",
- default = true,
+ name = "mathkerns",
+ description = "math kerns",
+ -- default = true,
initializers = {
base = initialize,
node = initialize,
diff --git a/tex/context/base/mkiv/math-act.lua b/tex/context/base/mkiv/math-act.lua
index 4f38b4195..a5cfa82de 100644
--- a/tex/context/base/mkiv/math-act.lua
+++ b/tex/context/base/mkiv/math-act.lua
@@ -230,115 +230,6 @@ sequencers.appendaction("aftercopyingcharacters", "system","mathematics.tweakaft
local virtualized = mathematics.virtualized
-function mathematics.overloaddimensions(target,original,set)
- local goodies = target.goodies
- if goodies then
- for i=1,#goodies do
- local goodie = goodies[i]
- local mathematics = goodie.mathematics
- local dimensions = mathematics and mathematics.dimensions
- if dimensions then
- if trace_defining then
- report_math("overloading dimensions in %a @ %p",target.properties.fullname,target.parameters.size)
- end
- local characters = target.characters
- local descriptions = target.descriptions
- local parameters = target.parameters
- local factor = parameters.factor
- local hfactor = parameters.hfactor
- local vfactor = parameters.vfactor
-if not CONTEXTLMTXMODE or CONTEXTLMTXMODE == 0 then
- target.type = "virtual"
- target.properties.virtualized = true
-end
- local function overload(dimensions)
- for unicode, data in next, dimensions do
- local character = characters[unicode]
- if not character then
- local c = virtualized[unicode]
- if c then
- character = characters[c]
- end
- end
- if character then
- --
- local width = data.width
- local height = data.height
- local depth = data.depth
- if trace_defining and (width or height or depth) then
- report_math("overloading dimensions of %C, width %p, height %p, depth %p",
- unicode,width or 0,height or 0,depth or 0)
- end
- if width then character.width = width * hfactor end
- if height then character.height = height * vfactor end
- if depth then character.depth = depth * vfactor end
- --
- local xoffset = data.xoffset
- local yoffset = data.yoffset
- if xoffset == "llx" then
- local d = descriptions[unicode]
- if d then
- xoffset = - d.boundingbox[1] * hfactor
- character.width = character.width + xoffset
- xoffset = rightcommand[xoffset]
- else
- xoffset = nil
- end
- elseif xoffset and xoffset ~= 0 then
- xoffset = rightcommand[xoffset * hfactor]
- else
- xoffset = nil
- end
- if yoffset and yoffset ~= 0 then
- yoffset = upcommand[yoffset * vfactor]
- else
- yoffset = nil
- end
- if xoffset or yoffset then
- local commands = characters.commands
- if commands then
- prependcommands(commands,yoffset,xoffset)
- else
- local slot = charcommand[unicode]
- if xoffset and yoffset then
- character.commands = { xoffset, yoffset, slot }
- elseif xoffset then
- character.commands = { xoffset, slot }
- else
- character.commands = { yoffset, slot }
- end
- end
- end
- elseif trace_defining then
- report_math("no overloading dimensions of %C, not in font",unicode)
- end
- end
- end
- if set == nil then
- set = { "default" }
- end
- if set == "all" or set == true then
- for name, set in next, dimensions do
- overload(set)
- end
- else
- if type(set) == "string" then
- set = utilities.parsers.settings_to_array(set)
- end
- if type(set) == "table" then
- for i=1,#set do
- local d = dimensions[set[i]]
- if d then
- overload(d)
- end
- end
- end
- end
- end
- end
- end
-end
-
-- no, it's a feature now (see good-mth):
--
-- sequencers.appendaction("aftercopyingcharacters", "system","mathematics.overloaddimensions")
@@ -711,10 +602,10 @@ function mathematics.finishfallbacks(target,specification,fallbacks)
fonts = { }
target.fonts = fonts
end
-if not CONTEXTLMTXMODE or CONTEXTLMTXMODE == 0 then
+ --
target.type = "virtual"
target.properties.virtualized = true
-end
+ --
if #fonts == 0 then
fonts[1] = { id = 0, size = size } -- self, will be resolved later
end
diff --git a/tex/context/base/mkiv/mult-fun.lua b/tex/context/base/mkiv/mult-fun.lua
index 4d99e8320..4e4a901c0 100644
--- a/tex/context/base/mkiv/mult-fun.lua
+++ b/tex/context/base/mkiv/mult-fun.lua
@@ -187,7 +187,7 @@ return {
--
"inpath", "pointof", "leftof", "rightof",
--
- "utflen", "utfsub",
+ "utfnum", "utflen", "utfsub",
--
"newhash", "disposehash", "inhash", "tohash",
--
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index d55bfa411..605d8e1f1 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 78ade839c..3c5c26cb3 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/mkiv/strc-mar.lua b/tex/context/base/mkiv/strc-mar.lua
index b5fd2667b..f7953c416 100644
--- a/tex/context/base/mkiv/strc-mar.lua
+++ b/tex/context/base/mkiv/strc-mar.lua
@@ -122,7 +122,7 @@ end
local function sweep(head,first,last)
for n, id, subtype in nextnode, head do
-- we need to handle empty heads so we test for latelua
- if id == glyph_code or (id == whatsit_code and subtype == lateluawhatsit_code) then
+ if id == glyph_code or (id == whatsit_code and subtype == lateluawhatsit_code) then -- brrr
local a = getattr(n,a_marks)
if not a then
-- next
diff --git a/tex/context/base/mkiv/task-ini.lua b/tex/context/base/mkiv/task-ini.lua
index c06e32df3..3e78fb2f9 100644
--- a/tex/context/base/mkiv/task-ini.lua
+++ b/tex/context/base/mkiv/task-ini.lua
@@ -95,6 +95,7 @@ appendaction("shipouts", "finishers", "attributes.transparencies.handler",
appendaction("shipouts", "finishers", "attributes.colorintents.handler", nil, "nut", "disabled" )
appendaction("shipouts", "finishers", "attributes.negatives.handler", nil, "nut", "disabled" )
appendaction("shipouts", "finishers", "attributes.effects.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "finishers", "attributes.alternates.handler", nil, "nut", "disabled" )
appendaction("shipouts", "finishers", "attributes.viewerlayers.handler", nil, "nut", "disabled" )
appendaction("shipouts", "wrapup", "nodes.handlers.export", nil, "nut", "disabled" ) -- always last
diff --git a/tex/context/base/mkxl/anch-pos.lmt b/tex/context/base/mkxl/anch-pos.lmt
index e804dbdf6..67d1657f2 100644
--- a/tex/context/base/mkxl/anch-pos.lmt
+++ b/tex/context/base/mkxl/anch-pos.lmt
@@ -1628,6 +1628,9 @@ end)
local newsavepos = nodes.pool.savepos
+jobpositions.lastx = 0
+jobpositions.lasty = 0
+
implement { name = "savepos", actions = function() context(newsavepos()) end }
-implement { name = "lastxpos", actions = function() context(gethpos()) end }
-implement { name = "lastypos", actions = function() context(getvpos()) end }
+implement { name = "lastxpos", actions = function() context(jobpositions.lastx) end }
+implement { name = "lastypos", actions = function() context(jobpositions.lasty) end }
diff --git a/tex/context/base/mkxl/attr-alt.lmt b/tex/context/base/mkxl/attr-alt.lmt
new file mode 100644
index 000000000..9d8592074
--- /dev/null
+++ b/tex/context/base/mkxl/attr-alt.lmt
@@ -0,0 +1,111 @@
+if not modules then modules = { } end modules ['attr-eff'] = {
+ version = 1.001,
+ comment = "companion to attr-eff.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local attributes, nodes, backends, utilities = attributes, nodes, backends, utilities
+local tex = tex
+
+local states = attributes.states
+local enableaction = nodes.tasks.enableaction
+local nodeinjections = backends.nodeinjections
+local texsetattribute = tex.setattribute
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+
+local interfaces = interfaces
+local implement = interfaces.implement
+
+attributes.alternates = attributes.alternates or { }
+local alternates = attributes.alternates
+
+local a_alternate = attributes.private('alternate')
+
+alternates.data = allocate()
+alternates.values = alternates.values or { }
+alternates.registered = alternates.registered or { }
+alternates.attribute = a_alternate
+
+local data = alternates.data
+local registered = alternates.registered
+local values = alternates.values
+
+storage.register("attributes/alternates/registered", registered, "attributes.alternates.registered")
+storage.register("attributes/alternates/values", values, "attributes.alternates.values")
+
+local function extender(alternates,key)
+ if key == "none" then
+ local d = nodeinjections.stopalternate()
+ alternates.none = d
+ return d
+ end
+end
+
+local function reviver(data,n)
+ local d = values[n] and nodeinjections.startalternate(values[n]) or nodeinjections.stopalternate()
+ data[n] = d
+ return d
+end
+
+setmetatableindex(alternates, extender)
+setmetatableindex(alternates.data, reviver)
+
+alternates.handler = nodes.installattributehandler {
+ name = "alternate",
+ namespace = alternates,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.simple,
+}
+
+local function register(specification)
+ local text = specification.text or "unknown"
+ local n = registered[text]
+ if not n then
+ n = #values + 1
+ values[n] = text
+ registered[text] = n
+ end
+ return n
+end
+
+local enabled = false
+
+local function enable()
+ if not enabled then
+ enableaction("shipouts","attributes.alternates.handler")
+ enabled = true
+ end
+end
+
+alternates.register = register
+alternates.enable = enable
+
+-- interface
+
+implement {
+ name = "setalternate",
+ actions = function(specification)
+ if not enabled then
+ enable()
+ end
+ texsetattribute(a_alternate,register(specification))
+ end,
+ arguments = {
+ {
+ { "text", "string" },
+ }
+ }
+}
+
+implement {
+ name = "resetalternate",
+ actions = function()
+ if enabled then
+ texsetattribute(a_alternate)
+ end
+ end
+}
diff --git a/tex/context/base/mkxl/attr-alt.mkxl b/tex/context/base/mkxl/attr-alt.mkxl
new file mode 100644
index 000000000..3881d929e
--- /dev/null
+++ b/tex/context/base/mkxl/attr-alt.mkxl
@@ -0,0 +1,55 @@
+%D \module
+%D [ file=attr-alt,
+%D version=2007.06.06,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Alternates,
+%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 Attribute Macros / Alternates}
+
+\registerctxluafile{attr-alt}{autosuffix}
+
+%D The main reason for providing this is that we need to make sure we have no
+%D dangling end markers when we cross a page. Public viewers don't seem to support
+%D actual text at all and acrobat has some funny selection issues.
+%D
+%D \starttyping
+%D test
+%D \startalternate[text={A}]
+%D \dorecurse{10}{A }
+%D \startalternate[text={B}]
+%D \dorecurse{10}{B }
+%D \stopalternate
+%D \dorecurse{10}{A }
+%D \stopalternate
+%D test \par
+%D \stoptyping
+%D
+%D \starttyping
+%D test \startalternate[text={e=mc^2}]!$e=mc^2$\stopalternate\par
+%D test \alternate{e=mc^2}{copy:}\nbsp$e=mc^2$\par
+%D \stoptyping
+
+\unprotect
+
+\permanent\protected\def\startalternate[#1]% maybe better/also: [text={...}]
+ {\begingroup
+ \getdummyparameters[\c!text=,#1]%
+ \clf_setalternate text {\dummyparameter\c!text}\relax}
+
+\permanent\protected\def\stopalternate
+ {\endgroup}
+
+\permanent\protected\def\alternate#1%
+ {\groupedcommand{\clf_setalternate text {#1}\relax}{}}
+
+\permanent\protected\def\setalternate #1{\clf_setalternate text {#1}\relax}
+\permanent\protected\def\resetalternate {\clf_resetalternate}
+
+\protect \endinput
diff --git a/tex/context/base/mkxl/attr-eff.mkxl b/tex/context/base/mkxl/attr-eff.mkxl
index 04a0c55ce..42aadf9a2 100644
--- a/tex/context/base/mkxl/attr-eff.mkxl
+++ b/tex/context/base/mkxl/attr-eff.mkxl
@@ -30,8 +30,8 @@
\appendtoks
\edef\p_method{\effectparameter\c!method}%
\ifx\p_method\v!command
- \setuxvalue{\e!start\currenteffect}{\starteffect[#1]}%
- \setuxvalue{\e!stop \currenteffect}{\stopeffect}%
+ \frozen\protected\xdefcsname\e!start\currenteffect\endcsname{\starteffect[#1]}%
+ \frozen\protected\xdefcsname\e!stop \currenteffect\endcsname{\stopeffect}%
\fi
\to \everydefineeffect
diff --git a/tex/context/base/mkxl/attr-ini.mkxl b/tex/context/base/mkxl/attr-ini.mkxl
index de22cd6e2..8cef1ec56 100644
--- a/tex/context/base/mkxl/attr-ini.mkxl
+++ b/tex/context/base/mkxl/attr-ini.mkxl
@@ -130,6 +130,7 @@
\definesystemattribute [ruled] [public]
\definesystemattribute [shifted] [public]
\definesystemattribute [checkedbreak] [public]
+\definesystemattribute [alternate] [public]
\definesystemattribute [vboxtohboxseparator] [public]
\permanent\protected\let\showattributes\clf_showattributes % maybe at lua end
diff --git a/tex/context/base/mkxl/back-trf.mkxl b/tex/context/base/mkxl/back-ext.mkxl
index fcf69ade4..bba33335d 100644
--- a/tex/context/base/mkxl/back-trf.mkxl
+++ b/tex/context/base/mkxl/back-ext.mkxl
@@ -1,8 +1,8 @@
%D \module
-%D [ file=back-trf,
-%D version=2019.02.08, % 2009.04.15,
+%D [ file=back-ext,
+%D version=2019.02.08, % and later, merged file
%D title=\CONTEXT\ Backend Macros,
-%D subtitle=Transformations,
+%D subtitle=Output,
%D author=Hans Hagen,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
@@ -11,9 +11,15 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+% \registerctxluafile{back-ext}{autosuffix}
+
\unprotect
-\registerctxluafile{back-trf}{autosuffix}
+% \let\normalopenout \openout
+% \let\normalwrite \write
+% \let\normalcloseout\closeout
+% \let\normallatelua \latelua
+% \let\normalspecial \special
% rotation
diff --git a/tex/context/base/mkxl/back-ini.lmt b/tex/context/base/mkxl/back-ini.lmt
index ee40c384d..922705742 100644
--- a/tex/context/base/mkxl/back-ini.lmt
+++ b/tex/context/base/mkxl/back-ini.lmt
@@ -95,17 +95,6 @@ statistics.register("used backend", function()
end
end)
-local comment = { "comment", "" }
-
-tables.vfspecials = allocate {
- red = comment,
- green = comment,
- blue = comment,
- black = comment,
- startslant = comment,
- stopslant = comment,
-}
-
-- can best be here
interfaces.implement {
@@ -131,25 +120,6 @@ end)
backends.included = included
--- Also here:
-
-local paper_width = 0
-local paper_height = 0
-
-function codeinjections.setpagedimensions(paperwidth,paperheight)
- if paperwidth then
- paper_width = paperwidth
- end
- if paperheight then
- paper_height = paperheight
- end
- return paper_width, paper_height
-end
-
-function codeinjections.getpagedimensions()
- return paper_width, paper_height
-end
-
-- could also be codeinjections
function backends.getcallbackstate()
diff --git a/tex/context/base/mkxl/back-out.lmt b/tex/context/base/mkxl/back-out.lmt
deleted file mode 100644
index fbcb220dc..000000000
--- a/tex/context/base/mkxl/back-out.lmt
+++ /dev/null
@@ -1,255 +0,0 @@
-if not modules then modules = { } end modules ['back-out'] = {
- version = 1.001,
- comment = "companion to back-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type = type
-local loadstring = loadstring
-
-local context = context
-
--- tokens.scanners.....
-
-local get = token.get_index
-local scanners = tokens.scanners
-local scaninteger = scanners.integer
-local scanstring = scanners.string
-local scankeyword = scanners.keyword
-local scantokenlist = scanners.tokenlist
-
-local serialize = token.serialize
-
-local logwriter = logs.writer
-local openfile = io.open
-local flushio = io.flush
-
-local nuts = nodes.nuts
-local tonode = nuts.tonode
-local copynode = nuts.copy
-local nodepool = nuts.pool
-
-local getdata = nuts.getdata
-
-local whatsit_code = nodes.nodecodes.whatsit
-
-local whatsitcodes = nodes.whatsitcodes
-
-local literalvalues = nodes.literalvalues
-local originliteral_code = literalvalues.origin
-local pageliteral_code = literalvalues.page
-local directliteral_code = literalvalues.direct
-local rawliteral_code = literalvalues.raw
-
-local immediate_code = tex.flagcodes.immediate
-
-local nodeproperties = nodes.properties.data
-
-local channels = { }
-
-local register = nodepool.register
-local newnut = nuts.new
-
-local opennode = register(newnut(whatsit_code,whatsitcodes.open))
-local writenode = register(newnut(whatsit_code,whatsitcodes.write))
-local closenode = register(newnut(whatsit_code,whatsitcodes.close))
-local lateluanode = register(newnut(whatsit_code,whatsitcodes.latelua))
-local literalnode = register(newnut(whatsit_code,whatsitcodes.literal))
-local savenode = register(newnut(whatsit_code,whatsitcodes.save))
-local restorenode = register(newnut(whatsit_code,whatsitcodes.restore))
-local setmatrixnode = register(newnut(whatsit_code,whatsitcodes.setmatrix))
-
-local open_command, write_command, close_command
-
-backends = backends or { }
-
-local function immediately(prefix)
- return prefix and (prefix & immediate_code) ~= 0
-end
-
-local function openout(prefix)
- local channel = scaninteger()
- scankeyword("=") -- hack
- local filename = scanstring()
- if not immediately(prefix) then
- local n = copynode(opennode)
- nodeproperties[n] = { channel = channel, filename = filename } -- action = "open"
- return context(tonode(n))
- elseif not channels[channel] then
- local handle = openfile(filename,"wb") or false
- if handle then
- channels[channel] = handle
- else
- -- error
- end
- end
-end
-
-function backends.openout(n)
- local p = nodeproperties[n]
- if p then
- local handle = openfile(p.filename,"wb") or false
- if handle then
- channels[p.channel] = handle
- else
- -- error
- end
- end
-end
-
-local function write(prefix)
- local channel = scaninteger()
- if not immediately(prefix) then
- local t = scantokenlist()
- local n = copynode(writenode)
- nodeproperties[n] = { channel = channel, data = t } -- action = "write"
- return context(tonode(n))
- else
- local content = scanstring()
- local handle = channels[channel]
- if handle then
- handle:write(content,"\n")
- else
- logwriter(content,"\n")
- end
- end
-end
-
-function backends.writeout(n)
- local p = nodeproperties[n]
- if p then
- local handle = channels[p.channel]
- local content = serialize(p.data)
- if handle then
- handle:write(content,"\n")
- else
- logwriter(content,"\n")
- end
- end
-end
-
-local function closeout(prefix)
- local channel = scaninteger()
- if not immediately(prefix) then
- local n = copynode(closenode)
- nodeproperties[n] = { channel = channel } -- action = "close"
- return context(tonode(n))
- else
- local handle = channels[channel]
- if handle then
- handle:close()
- channels[channel] = false
- flushio()
- else
- -- error
- end
- end
-end
-
-function backends.closeout(n)
- local p = nodeproperties[n]
- if p then
- local channel = p.channel
- local handle = channels[channel]
- if handle then
- handle:close()
- channels[channel] = false
- flushio()
- else
- -- error
- end
- end
-end
-
-local noflatelua = 0
-
-local function latelua()
- local node = copynode(lateluanode)
- local name = "latelua"
- if scankeyword("name") then
- name = scanstring()
- end
- local data = scantokenlist()
- nodeproperties[node] = { name = name, data = data }
- return context(tonode(node))
-end
-
-function backends.latelua(current,pos_h,pos_v) -- todo: pass pos_h and pos_v (more efficient in lmtx)
- local p = nodeproperties[current]
- if p then
- data = p.data
- else
- data = getdata(current)
- end
- noflatelua = noflatelua + 1
- local kind = type(data)
- if kind == "table" then
- data.action(data.specification or data)
- elseif kind == "function" then
- data()
- else
- if kind ~= "string" then
- data = serialize(data)
- end
- if #data ~= "" then
- local code = loadstring(data)
- if code then
- code()
- end
- end
- end
-end
-
-function backends.getcallbackstate()
- return { count = noflatelua }
-end
-
-function nodepool.originliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = originliteral_code } return t end
-function nodepool.pageliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = pageliteral_code } return t end
-function nodepool.directliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = directliteral_code } return t end
-function nodepool.rawliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = rawliteral_code } return t end
-
-local pdfliterals = {
- [originliteral_code] = originliteral_code, [literalvalues[originliteral_code]] = originliteral_code,
- [pageliteral_code] = pageliteral_code, [literalvalues[pageliteral_code]] = pageliteral_code,
- [directliteral_code] = directliteral_code, [literalvalues[directliteral_code]] = directliteral_code,
- [rawliteral_code] = rawliteral_code, [literalvalues[rawliteral_code]] = rawliteral_code,
-}
-
-function nodepool.literal(mode,str)
- local t = copynode(literalnode)
- if str then
- nodeproperties[t] = { data = str, mode = pdfliterals[mode] or pageliteral_code }
- else
- nodeproperties[t] = { data = mode, mode = pageliteral_code }
- end
- return t
-end
-
---- these 3 will move to node-res as they are generic
-
-function nodepool.save()
- return copynode(savenode)
-end
-
-function nodepool.restore()
- return copynode(restorenode)
-end
-
-function nodepool.setmatrix(rx,sx,sy,ry,tx,ty)
- local t = copynode(setmatrixnode)
- nodeproperties[t] = { matrix = { rx, sx, sy, ry, tx, ty } }
- return t
-end
-
-interfaces.implement { name = "openout", actions = openout, public = true, usage = "value" }
-interfaces.implement { name = "write", actions = write, public = true, usage = "value" }
-interfaces.implement { name = "closeout", actions = closeout, public = true, usage = "value" }
-interfaces.implement { name = "latelua", actions = latelua, public = true, protected = true }
-interfaces.implement { name = "special", actions = scanstring, public = true, protected = true }
-
-open_command = get(token.create("openout"))
-write_command = get(token.create("write"))
-close_command = get(token.create("closeout"))
diff --git a/tex/context/base/mkxl/back-out.mkxl b/tex/context/base/mkxl/back-out.mkxl
deleted file mode 100644
index 5cf79b2ea..000000000
--- a/tex/context/base/mkxl/back-out.mkxl
+++ /dev/null
@@ -1,22 +0,0 @@
-%D \module
-%D [ file=back-out,
-%D version=2019.02.08,
-%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-out}{autosuffix}
-
-% \let\normalopenout \openout
-% \let\normalwrite \write
-% \let\normalcloseout\closeout
-% \let\normallatelua \latelua
-% \let\normalspecial \special
-
-\endinput
diff --git a/tex/context/base/mkxl/back-pdf.mkxl b/tex/context/base/mkxl/back-pdf.mkxl
index 66db06ef1..d59c29bc0 100644
--- a/tex/context/base/mkxl/back-pdf.mkxl
+++ b/tex/context/base/mkxl/back-pdf.mkxl
@@ -20,7 +20,6 @@
\registerctxluafile{lpdf-ini}{autosuffix,optimize}
\registerctxluafile{lpdf-lmt}{autosuffix,optimize}
\registerctxluafile{lpdf-col}{autosuffix}
-\registerctxluafile{lpdf-vfc}{autosuffix}
\registerctxluafile{lpdf-xmp}{autosuffix}
\registerctxluafile{lpdf-ano}{autosuffix}
\registerctxluafile{lpdf-res}{autosuffix}
diff --git a/tex/context/base/mkxl/back-trf.lmt b/tex/context/base/mkxl/back-trf.lmt
deleted file mode 100644
index e3ec0bda3..000000000
--- a/tex/context/base/mkxl/back-trf.lmt
+++ /dev/null
@@ -1,164 +0,0 @@
-if not modules then modules = { } end modules ['back-trf'] = {
- version = 1.001,
- comment = "companion to back-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local sind, cosd, abs = math.sind, math.cosd, math.abs
-local insert, remove = table.insert, table.remove
-local unpack = unpack
-
-local context = context
-
-local formatters = string.formatters
-
-local scanners = tokens.scanners
-local scankeyword = scanners.keyword
-local scaninteger = scanners.integer
-local scannumber = scanners.number
-local scanstring = scanners.string
-
-local implement = interfaces.implement
-
-local nodepool = nodes.pool
-local savenode = nodepool.save
-local restorenode = nodepool.restore
-local setmatrixnode = nodepool.setmatrix
-local literalnode = nodepool.literal -- has to become some nodeinjection
-
-local stack = { }
-local restore = true -- false
-
-updaters.register("backend.update",function()
- savenode = nodepool.save -- not needed
- restorenode = nodepool.restore -- not needed
- setmatrixnode = nodepool.setmatrix -- not needed
- literalnode = nodepool.literal -- has to become some nodeinjection
-end)
-
-local function stopsomething()
- local top = remove(stack)
- if top == false then
- -- not wrapped
- elseif top == true then
- context(restorenode())
- elseif top then
- context(setmatrixnode(unpack(top))) -- not really needed anymore
- context(restorenode())
- else
- -- nesting error
- end
-end
-
-local function startrotation()
- local a = scannumber()
- if a == 0 then
- insert(stack,false)
- else
- local s, c = sind(a), cosd(a)
- if abs(s) < 0.000001 then
- s = 0 -- otherwise funny -0.00000
- end
- if abs(c) < 0.000001 then
- c = 0 -- otherwise funny -0.00000
- end
- context(savenode())
- context(setmatrixnode(c,s,-s,c))
- insert(stack,restore and { c, -s, s, c } or true)
- end
-end
-
-implement { name = "startrotation", actions = startrotation }
-implement { name = "stoprotation", actions = stopsomething }
-
-local function startscaling() -- at the tex end we use sx and sy instead of rx and ry
- local rx, ry = 1, 1
- while true do
- if scankeyword("rx") then
- rx = scannumber()
- elseif scankeyword("ry") then
- ry = scannumber()
- -- elseif scankeyword("revert") then
- -- local top = stack[#stack]
- -- if top then
- -- rx = top[1]
- -- ry = top[4]
- -- else
- -- rx = 1
- -- ry = 1
- -- end
- else
- break
- end
- end
- if rx == 1 and ry == 1 then
- insert(stack,false)
- else
- if rx == 0 then
- rx = 0.0001
- end
- if ry == 0 then
- ry = 0.0001
- end
- context(savenode())
- context(setmatrixnode(rx,0,0,ry))
- insert(stack,restore and { 1/rx, 0, 0, 1/ry } or true)
- end
-end
-
-implement { name = "startscaling", actions = startscaling }
-implement { name = "stopscaling", actions = stopsomething }
-
-local function startmatrix() -- rx sx sy ry -- tx, ty
- local rx, sx, sy, ry = 1, 0, 0, 1
- while true do
- if scankeyword("rx") then rx = scannumber()
- elseif scankeyword("ry") then ry = scannumber()
- elseif scankeyword("sx") then sx = scannumber()
- elseif scankeyword("sy") then sy = scannumber()
- else break end
- end
- if rx == 1 and sx == 0 and sy == 0 and ry == 1 then
- insert(stack,false)
- else
- context(savenode())
- context(setmatrixnode(rx,sx,sy,ry))
- insert(stack,store and { -rx, -sx, -sy, -ry } or true)
- end
-end
-
-implement { name = "startmatrix", actions = startmatrix }
-implement { name = "stopmatrix", actions = stopsomething }
-
-local function startmirroring()
- context(setmatrixnode(-1,0,0,1))
-end
-
-implement { name = "startmirroring", actions = startmirroring }
-implement { name = "stopmirroring", actions = startmirroring } -- not: stopsomething
-
--- this could also run on top of pack-rul ... todo
-
--- local function startclipping()
--- -- context(savenode())
--- context(literalnode("origin",formatters["q 0 w %s W n"](scanstring())))
--- end
---
--- local function stopclipping()
--- -- context(restorenode())
--- context(literalnode("Q"))
--- end
-
-local function startclipping()
- context(savenode())
- context(literalnode("origin",formatters["0 w %s W n"](scanstring())))
-end
-
-local function stopclipping()
- context(restorenode())
-end
-
-implement { name = "startclipping", actions = startclipping }
-implement { name = "stopclipping", actions = stopclipping }
diff --git a/tex/context/base/mkxl/colo-nod.lmt b/tex/context/base/mkxl/colo-nod.lmt
index d65f5978c..67487fee5 100644
--- a/tex/context/base/mkxl/colo-nod.lmt
+++ b/tex/context/base/mkxl/colo-nod.lmt
@@ -12,9 +12,9 @@ local setattrs = nuts.setattrs
local privateattributes = attributes.private
+local a_colormodel = privateattributes('colormodel')
local a_color = privateattributes('color')
local a_transparency = privateattributes('transparency')
-local a_colormodel = privateattributes('colormodel')
local colors = { }
nuts.colors = colors
@@ -26,9 +26,9 @@ function colors.set(n,ma,ca,ta) -- we could also do layers here
ma = 1
end
if ta then
- setattrs(n,a_colorspace,ma,a_color,ca,a_transparency,ta)
+ setattrs(n,a_colormodel,ma,a_color,ca,a_transparency,ta)
else
- setattrs(n,a_colorspace,ma,a_color,ca)
+ setattrs(n,a_colormodel,ma,a_color,ca)
end
end
elseif ta then
diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl
index 31dbd327a..8f1882ce5 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.11 16:28}
+\newcontextversion{2021.01.17 21:39}
%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 751712225..54b1bb730 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.11 16:28}
+\immutable\edef\contextversion{2021.01.17 21:39}
%overloadmode 1 % check frozen / warning
%overloadmode 2 % check frozen / error
@@ -159,7 +159,7 @@
\loadmkxlfile{node-ini}
-\loadmkxlfile{cldf-bas} % basics / depends on nodes
+% \loadmkxlfile{cldf-bas} % basics / depends on nodes
\loadmkxlfile{node-fin}
\loadmkxlfile{node-mig}
@@ -169,13 +169,15 @@
\loadmkxlfile{back-ini}
\loadmkxlfile{back-res}
-\loadmkxlfile{back-trf}
-\loadmkxlfile{back-out}
+\loadmkxlfile{back-ext}
+
+\loadmkxlfile{cldf-bas} % basics / depends on nodes
\loadmkxlfile{attr-col}
\loadmkxlfile{attr-lay}
\loadmkxlfile{attr-neg}
\loadmkxlfile{attr-eff}
+\loadmkxlfile{attr-alt}
\loadmkxlfile{attr-mkr}
\loadmkxlfile{trac-tex}
diff --git a/tex/context/base/mkxl/driv-shp.lmt b/tex/context/base/mkxl/driv-shp.lmt
index 9747ba82d..cfa61e30e 100644
--- a/tex/context/base/mkxl/driv-shp.lmt
+++ b/tex/context/base/mkxl/driv-shp.lmt
@@ -99,21 +99,7 @@ local gleaders_code = gluecodes.gleaders
local spaceskip_code = gluecodes.spaceskip
-local saveposwhatsit_code = whatsitcodes.savepos
-local userdefinedwhatsit_code = whatsitcodes.userdefined
-local openwhatsit_code = whatsitcodes.open
-local writewhatsit_code = whatsitcodes.write
-local closewhatsit_code = whatsitcodes.close
-local lateluawhatsit_code = whatsitcodes.latelua
-local literalwhatsit_code = whatsitcodes.literal
-local setmatrixwhatsit_code = whatsitcodes.setmatrix
-local savewhatsit_code = whatsitcodes.save
-local restorewhatsit_code = whatsitcodes.restore
-
-local getpagedimensions getpagedimensions = function()
- getpagedimensions = backends.codeinjections.getpagedimensions
- return getpagedimensions()
-end
+local getpagedimensions = layouts.getpagedimensions
local drivers = drivers
local instances = drivers.instances
@@ -154,11 +140,6 @@ local flushcharacter
local flushfontchar
local flushrule
local flushliteral
-local flushsetmatrix
-local flushsave
-local flushrestore
-local flushspecial
------ flushimage
-- make local
@@ -169,307 +150,323 @@ function drivers.getvpos() return round(pos_v) end
-- characters
-local flush_character
-
-local stack = setmetatableindex("table")
-local level = 0
-local nesting = 0
-local main = 0
-
--- experiment (smaller page stream but might be fragile)
+local flush_character do
-local tospace = false directives.register("backends.spaces", function(v) tospace = v end)
+ local stack = setmetatableindex("table")
+ local level = 0
+ local nesting = 0
+ local main = 0
--- todo: cache streams
+ -- experiment (smaller page stream but might be fragile)
-local default = 16384 * number.dimenfactors.bp -- 65536 // 4
+ local tospace = false directives.register("backends.spaces", function(v) tospace = v end)
-local startcolor = function() end
-local stopcolor = function() end
+ -- todo: cache streams
-updaters.register("backend.update",function()
- startcolor = fonts.vfcommands.startcolor
- stopcolor = fonts.vfcommands.stopcolor
-end)
+ local default = 16384 * number.dimenfactors.bp -- 65536 // 4
-local function flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy)
+ local vfinjectors = fonts.helpers.vfinjectors
- if nesting > 100 then
- return
- elseif nesting == 0 then
- main = font
- end
+ local function flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy)
- nesting = nesting + 1
+ if nesting > 100 then
+ return
+ elseif nesting == 0 then
+ main = font
+ end
- local saved_h = pos_h
- local saved_v = pos_v
- local saved_r = pos_r
- pos_r = lefttoright_code
+ nesting = nesting + 1
- local data = fontdata[font]
- local fnt = font
- local fonts = data.fonts
- local siz = (data.parameters.factor or 1)/65536
+ local saved_h = pos_h
+ local saved_v = pos_v
+ local saved_r = pos_r
+ pos_r = lefttoright_code
--- siz = siz * data.parameters.size / 1000
+ local data = fontdata[font]
+ local fnt = font
+ local fonts = data.fonts
+ local siz = (data.parameters.factor or 1)/65536
- local function flushchar(font,char,fnt,chr,f,e)
- if fnt then
- local nest = char ~= chr or font ~= fnt
- if fnt == 0 then
- fnt = main
+ local function flushchar(font,char,fnt,chr,f,e)
+ if fnt then
+ local nest = char ~= chr or font ~= fnt
+ if fnt == 0 then
+ fnt = main
+ end
+ return flush_character(current,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e)
+ else
+ return 0
end
--- return flush_character(false,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e)
- return flush_character(current,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e)
- else
- return 0
end
- end
- -- we assume resolved fonts: id mandate but maybe also size
-
- for i=1,#vfcommands do
- local packet = vfcommands[i]
- local command = packet[1]
- if command == "char" then
- local chr = packet[2]
- local f = packet[3]
- local e = packet[4]
- pos_h = pos_h + flushchar(font,char,fnt,chr,f,e)
- elseif command == "slot" then
- local index = packet[2]
- local chr = packet[3]
- local f = packet[4]
- local e = packet[5]
- if index == 0 then
- pos_h = pos_h + flushchar(font,char,font,chr,f,e)
- else
- local okay = fonts and fonts[index]
- if okay then
- local fnt = okay.id
- if fnt then
- pos_h = pos_h + flushchar(font,char,fnt,chr,f,e)
- end
- else
- -- safeguard, we assume the font itself (often index 1)
- pos_h = pos_h + flushchar(font,char,font,chr,f,e)
- end
- end
- elseif command == "use" then
- local index = packet[2]
- if index then
- local fnt
+ -- we assume resolved fonts: id mandate but maybe also size
+
+ -- we could map left, right, up, down -> offset
+ -- we could map char, font, slot to -> slot
+
+ for i=1,#vfcommands do
+ local packet = vfcommands[i]
+ local command = packet[1]
+ if command == "char" then
+ local chr = packet[2]
+ local f = packet[3]
+ local e = packet[4]
+ pos_h = pos_h + flushchar(font,char,fnt,chr,f,e)
+ elseif command == "slot" then
+ local index = packet[2]
+ local chr = packet[3]
+ local f = packet[4]
+ local e = packet[5]
if index == 0 then
- fnt = font
+ pos_h = pos_h + flushchar(font,char,font,chr,f,e)
else
local okay = fonts and fonts[index]
if okay then
- fnt = okay.id
+ local fnt = okay.id
+ if fnt then
+ pos_h = pos_h + flushchar(font,char,fnt,chr,f,e)
+ end
+ else
+ -- safeguard, we assume the font itself (often index 1)
+ pos_h = pos_h + flushchar(font,char,font,chr,f,e)
end
end
- if fnt then
- -- not efficient but ok for now as experiment
- local d = characters[fnt]
- if d then
- for i=3,#packet do
- local chr = packet[i]
- local dat = d[chr]
- if dat then
- flushfontchar(fnt,chr,dat)
+ elseif command == "use" then
+ local index = packet[2]
+ if index then
+ local fnt
+ if index == 0 then
+ fnt = font
+ else
+ local okay = fonts and fonts[index]
+ if okay then
+ fnt = okay.id
+ end
+ end
+ if fnt then
+ -- not efficient but ok for now as experiment
+ local d = characters[fnt]
+ if d then
+ for i=3,#packet do
+ local chr = packet[i]
+ local dat = d[chr]
+ if dat then
+ flushfontchar(fnt,chr,dat)
+ end
end
end
end
end
- end
- elseif command == "right" then
- local h = packet[2] -- already scaled
- if factor ~= 0 and h ~= 0 then
- h = h + h * factor / 1000 -- expansion
- end
- h = h * sx
- pos_h = pos_h + h
- elseif command == "down" then
- local v = packet[2] -- already scaled
- v = v * sy
- pos_v = pos_v - v
- elseif command == "push" then
- level = level + 1
- local s = stack[level]
- s[1] = pos_h
- s[2] = pos_v
- elseif command == "pop" then
- if level > 0 then
- local s = stack[level]
- pos_h = s[1]
- pos_v = s[2]
- level = level - 1
- end
- elseif command == "rule" then
- local size_v = packet[2]
- local size_h = packet[3]
- if size_h > 0 and size_v > 0 then
- if factor ~= 0 then
- size_h = size_h + size_h * factor / 1000
+ elseif command == "right" then
+ local h = packet[2] -- already scaled
+ if h ~= 0 then
+ if factor ~= 0 then
+ h = h + h * factor / 1000 -- expansion
+ end
+ pos_h = pos_h + h * sx
end
- if size_h > 0 then
- size_h = size_h * sx
- size_v = size_v * sy
- flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v)
- pos_h = pos_h + size_h
+ elseif command == "left" then
+ local h = packet[2] -- already scaled
+ if h ~= 0 then
+ if factor ~= 0 then
+ h = h + h * factor / 1000 -- expansion
+ end
+ pos_h = pos_h - h * sx
end
- end
- elseif command == "frame" then
- -- d:width d:height d:depth d:rulethickness b:outline b:advance b:baseline s:color
- local width = packet[2]
- if width > 0 then
- local height = packet[3] or 0
- local depth = packet[4] or 0
- local total = height + depth
- if total > 0 then
+ elseif command == "down" then
+ local v = packet[2] -- already scaled
+ if v and v ~= 0 then
+ pos_v = pos_v - v * sy
+ end
+ elseif command == "up" then
+ local v = packet[2] -- already scaled
+ if v and v ~= 0 then
+ pos_v = pos_v + v * sy
+ end
+ elseif command == "offset" then
+ local h = packet[2] or 0
+ local v = packet[3] or 0
+ if h ~= 0 then
if factor ~= 0 then
- width = width + width * factor / 1000
+ h = h + h * factor / 1000 -- expansion
end
- if width > 0 then
- local line = packet[5] or default
- local outline = not packet[6]
- local advance = not packet[7]
- local baseline = outline and packet[8]
- local color = packet[9]
- if color then
- startcolor(color)
- end
- width = width * sx
- height = height * sy
- depth = depth * sy
- flushspecialrule(pos_h,pos_v,pos_r,width,height,depth,line,outline,baseline)
- if color then
- stopcolor()
+ pos_h = pos_h + h * sx
+ end
+ if v and v ~= 0 then
+ pos_v = pos_v + v * sy
+ end
+ elseif command == "push" then
+ level = level + 1
+ local s = stack[level]
+ s[1] = pos_h
+ s[2] = pos_v
+ elseif command == "pop" then
+ if level > 0 then
+ local s = stack[level]
+ pos_h = s[1]
+ pos_v = s[2]
+ level = level - 1
+ end
+ elseif command == "rule" then
+ local size_v = packet[2]
+ local size_h = packet[3]
+ if size_h > 0 and size_v > 0 then
+ if factor ~= 0 then
+ size_h = size_h + size_h * factor / 1000
+ end
+ if size_h > 0 then
+ size_h = size_h * sx
+ size_v = size_v * sy
+ flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v)
+ pos_h = pos_h + size_h
+ end
+ end
+ elseif command == "frame" then
+ -- d:width d:height d:depth d:rulethickness b:outline b:advance b:baseline s:color
+ local width = packet[2]
+ if width > 0 then
+ local height = packet[3] or 0
+ local depth = packet[4] or 0
+ local total = height + depth
+ if total > 0 then
+ if factor ~= 0 then
+ width = width + width * factor / 1000
end
- if advance then
- pos_h = pos_h + width
+ if width > 0 then
+ local line = packet[5] or default
+ local outline = not packet[6]
+ local advance = not packet[7]
+ local baseline = outline and packet[8]
+ local color = packet[9] -- no longer needed probably
+ if color then
+ vfinjectors.startcolor(pos_h,pos_v,color) -- takes packet or string
+ end
+ width = width * sx
+ height = height * sy
+ depth = depth * sy
+ flushspecialrule(pos_h,pos_v,pos_r,width,height,depth,line,outline,baseline)
+ if color then
+ vfinjectors.stopcolor()
+ end
+ if advance then
+ pos_h = pos_h + width
+ end
end
end
end
+ elseif command == "font" then
+ local index = packet[2]
+ local okay = fonts and fonts[index]
+ if okay then
+ fnt = okay.id or fnt -- or maybe just return
+ end
+ elseif command == "lua" then
+ local code = packet[2]
+ local kind = type(code)
+ if kind ~= "function" then
+ code = loadstring(code)
+ kind = type(code)
+ end
+ if kind == "function" then
+ code(font,char,pos_h,pos_v,sx,sy)
+ end
+ elseif command == "node" then -- obsolete
+ local h = packet[2]
+ hlist_out(h,getlist(h))
+ else
+ local injector = vfinjectors[command]
+ if injector then
+ injector(pos_h,pos_v,packet)
+ end
end
- elseif command == "font" then
- local index = packet[2]
- local okay = fonts and fonts[index]
- if okay then
- fnt = okay.id or fnt -- or maybe just return
- end
- elseif command == "lua" then
- local code = packet[2]
- local kind = type(code)
- if kind ~= "function" then
- code = loadstring(code)
- kind = type(code)
- end
- if kind == "function" then
- code(font,char,pos_h,pos_v,sx,sy)
- end
- elseif command == "node" then
- -- us this really useful?
- local h = packet[2]
- hlist_out(h,getlist(h))
- elseif command == "pdf" then
- -- this will disappear and become a plug
- flushliteral(false,pos_h,pos_v,packet[2],packet[3])
- -- elseif command == "image" then
- -- -- doesn't work because intercepted by engine so we use a different
- -- -- mechanism (for now)
- -- local image = packet[2]
- -- -- to do
- -- elseif command == "pdfmode" then
- -- -- doesn't happen
- -- elseif command == "special" then
- -- -- not supported
- -- elseif command == "nop" then
- -- -- nothing to do|
- -- elseif command == "scale" then
- -- -- not supported
+ -- image : not needed, maybe some day
+ -- pdfmode : not used
+ -- special : makes no sense
+ -- nop : the official ignore
+ -- scale : not supported
end
- end
- pos_h = saved_h
- pos_v = saved_v
- pos_r = saved_r
+ pos_h = saved_h
+ pos_v = saved_v
+ pos_r = saved_r
- nesting = nesting - 1
-end
+ nesting = nesting - 1
+ end
-local onetimemessage -- could be defined later (todo: make plug for this)
+ local onetimemessage -- could be defined later (todo: make plug for this)
-local getxyscales = nuts.getxyscales
+ local getxyscales = nuts.getxyscales
-flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,f,e)
+ flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,f,e)
- if font ~= lastfont then
- lastfont = font
- fontcharacters = characters[font]
- updatefontstate(font)
- end
+ if font ~= lastfont then
+ lastfont = font
+ fontcharacters = characters[font]
+ updatefontstate(font)
+ end
- local data = fontcharacters[char]
- if not data then
- if char > 0 then
- if not onetimemessage then
- onetimemessage = fonts.loggers.onetimemessage
+ local data = fontcharacters[char]
+ if not data then
+ if char > 0 then
+ if not onetimemessage then
+ onetimemessage = fonts.loggers.onetimemessage
+ end
+ onetimemessage(font,char,"missing")
end
- onetimemessage(font,char,"missing")
- end
- return 0, 0, 0
- end
- if vfcommands then
- vfcommands = data.commands
- end
- local width, height, depth, naturalwidth, sx, sy
- if current then
- naturalwidth, height, depth, factor = getwhd(current,true) -- also get corrected width
- sx, sy = getxyscales(current) -- maybe: getwhdfs
- if factor == 0 then
- width = naturalwidth
- else
- -- width = (1.0 + factor/1000000.0) * naturalwidth
- width = naturalwidth + naturalwidth * factor/1000000.0
- -- width = naturalwidth + naturalwidth * 0.000001 * factor
+ return 0, 0, 0
end
- else
- width = data.width or 0
- height = data.height or 0
- depth = data.depth or 0
- naturalwidth = width
- if not factor then
- factor = 0
+ if vfcommands then
+ vfcommands = data.commands
end
- sx = 1
- sy = 1
- end
- if pos_r == righttoleft_code then
- pos_h = pos_h - width -- here ?
- end
- if vfcommands then
- flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy) -- also f ?
- else
- -- kind of messy that we do orientation here and offsets elsewhere
- local orientation = data.orientation
- if orientation and (orientation == 1 or orientation == 3) then
- local x = data.xoffset
- local y = data.yoffset
- if x then
- pos_h = pos_h + x
+ local width, height, depth, naturalwidth, sx, sy
+ if current then
+ naturalwidth, height, depth, factor = getwhd(current,true) -- also get corrected width
+ sx, sy = getxyscales(current) -- maybe: getwhdfs
+ if factor == 0 then
+ width = naturalwidth
+ else
+ -- width = (1.0 + factor/1000000.0) * naturalwidth
+ width = naturalwidth + naturalwidth * factor/1000000.0
+ -- width = naturalwidth + naturalwidth * 0.000001 * factor
end
- if y then
- pos_v = pos_v + y
+ else
+ width = data.width or 0
+ height = data.height or 0
+ depth = data.depth or 0
+ naturalwidth = width
+ if not factor then
+ factor = 0
end
- pushorientation(orientation,pos_h,pos_v)
- flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width)
- poporientation(orientation,pos_h,pos_v)
+ sx = 1
+ sy = 1
+ end
+ if pos_r == righttoleft_code then
+ pos_h = pos_h - width -- here ?
+ end
+ if vfcommands then
+ flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy) -- also f ?
else
- flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width)
+ -- kind of messy that we do orientation here and offsets elsewhere .. this might change
+ local orientation = data.orientation
+ if orientation and (orientation == 1 or orientation == 3) then
+ local x = data.xoffset
+ local y = data.yoffset
+ if x then
+ pos_h = pos_h + x
+ end
+ if y then
+ pos_v = pos_v + y
+ end
+ pushorientation(orientation,pos_h,pos_v)
+ flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width)
+ poporientation(orientation,pos_h,pos_v)
+ else
+ flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width)
+ end
end
+ return width, height, depth
end
- return width, height, depth
+
end
-- end of characters
@@ -536,6 +533,13 @@ local function flushcloseout(current)
end
end
+local function flushsavepos(current,pos_h,pos_v)
+ jobpositions.lastx = pos_h
+ jobpositions.lasty = pos_v
+end
+
+local flushwhatsit
+
local hlist_out, vlist_out do
local function applyanchor(orientation,x,y,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset)
@@ -905,26 +909,7 @@ local hlist_out, vlist_out do
goto synced
end
elseif id == whatsit_code then
- if subtype == literalwhatsit_code then
- flushliteral(current,pos_h,pos_v)
- elseif subtype == lateluawhatsit_code then
- flushlatelua(current,pos_h,pos_v)
- elseif subtype == setmatrixwhatsit_code then
- flushsetmatrix(current,pos_h,pos_v)
- elseif subtype == savewhatsit_code then
- flushsave(current,pos_h,pos_v)
- elseif subtype == restorewhatsit_code then
- flushrestore(current,pos_h,pos_v)
- elseif subtype == saveposwhatsit_code then
- last_position_x = pos_h
- last_position_y = pos_v
- elseif subtype == writewhatsit_code then
- flushwriteout(current)
- elseif subtype == closewhatsit_code then
- flushcloseout(current)
- elseif subtype == openwhatsit_code then
- flushopenout(current)
- end
+ flushwhatsit[subtype](current,pos_h,pos_v)
elseif id == disc_code then
local replace, tail = getreplace(current)
-- actually, we no longer have these select discs in the packaged list ... it's about
@@ -1164,26 +1149,7 @@ local hlist_out, vlist_out do
end
cur_v = cur_v + total
elseif id == whatsit_code then
- if subtype == literalwhatsit_code then
- flushliteral(current,pos_h,pos_v)
- elseif subtype == lateluawhatsit_code then
- flushlatelua(current,pos_h,pos_v)
- elseif subtype == setmatrixwhatsit_code then
- flushsetmatrix(current,pos_h,pos_v)
- elseif subtype == savewhatsit_code then
- flushsave(current,pos_h,pos_v)
- elseif subtype == restorewhatsit_code then
- flushrestore(current,pos_h,pos_v)
- elseif subtype == saveposwhatsit_code then
- last_position_x = pos_h
- last_position_y = pos_v
- elseif subtype == writewhatsit_code then
- flushwriteout(current)
- elseif subtype == closewhatsit_code then
- flushcloseout(current)
- elseif subtype == openwhatsit_code then
- flushopenout(current)
- end
+ flushwhatsit[subtype](current,pos_h,pos_v)
else
-- penalty
goto synced
@@ -1223,22 +1189,47 @@ function drivers.converters.lmtx(driver,box,smode,objnum,specification)
initialize = actions.initialize
finalize = actions.finalize
- updatefontstate = flushers.updatefontstate
-
- pushorientation = flushers.pushorientation
- poporientation = flushers.poporientation
+ -- we need to do this once ...
+
+ if not updatefontstate then
+
+ updatefontstate = flushers.updatefontstate
+
+ pushorientation = flushers.pushorientation
+ poporientation = flushers.poporientation
+
+ flushcharacter = flushers.character
+ flushfontchar = flushers.fontchar
+ flushrule = flushers.rule
+ flushsimplerule = flushers.simplerule
+ flushspecialrule = flushers.specialrule
+ flushliteral = flushers.literal
+
+ flushwhatsit = setmetatableindex ( {
+ [whatsitcodes.literal] = flushliteral,
+ [whatsitcodes.latelua] = flushlatelua,
+ [whatsitcodes.userdefined] = function() end, -- special purpose, handled in callbacks
+ [whatsitcodes.savepos] = flushsavepos, -- only used by generic packages
+ [whatsitcodes.save] = flushers.save,
+ [whatsitcodes.restore] = flushers.restore,
+ [whatsitcodes.setmatrix] = flushers.setmatrix,
+ [whatsitcodes.open] = flushopenout, -- generic
+ [whatsitcodes.close] = flushcloseout, -- generic
+ [whatsitcodes.write] = flushwriteout, -- generic
+ [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,
+ }, function(t, k) report("weird whatsit %a",k) return function() end end)
- flushcharacter = flushers.character
- flushfontchar = flushers.fontchar
- flushrule = flushers.rule
- flushsimplerule = flushers.simplerule
- flushspecialrule = flushers.specialrule
- flushspecial = flushers.special
- flushliteral = flushers.literal
- flushsetmatrix = flushers.setmatrix
- flushsave = flushers.save
- flushrestore = flushers.restore
- -- flushimage = flushers.image
+ end
reset_dir_stack()
reset_state()
@@ -1279,12 +1270,6 @@ function drivers.converters.lmtx(driver,box,smode,objnum,specification)
local pagewidth, pageheight = getpagedimensions()
- -- local h_offset_par = texget("hoffset")
- -- local v_offset_par = texget("voffset")
-
- -- page_h_origin = trueinch
- -- page_v_origin = trueinch
-
pos_r = lefttoright_code
if pagewidth > 0 then
@@ -1307,17 +1292,14 @@ function drivers.converters.lmtx(driver,box,smode,objnum,specification)
page_size_v = total
end
- local refpoint_h = 0 -- + page_h_origin + h_offset_par
- local refpoint_v = page_size_v -- - page_v_origin - v_offset_par
+ local refpoint_h = 0
+ local refpoint_v = page_size_v
pos_h = refpoint_h
pos_v = refpoint_v - height
- -- synced
else
- -- page_h_origin = 0
- -- page_v_origin = 0
page_size_h = width
page_size_v = total
pos_r = getdirection(box)
diff --git a/tex/context/base/mkxl/font-chk.lmt b/tex/context/base/mkxl/font-chk.lmt
index 7141be2c7..8e73d1b3c 100644
--- a/tex/context/base/mkxl/font-chk.lmt
+++ b/tex/context/base/mkxl/font-chk.lmt
@@ -64,7 +64,6 @@ local implement = interfaces.implement
local glyph_code = nodes.nodecodes.glyph
-local new_special = nodes.pool.special -- todo: literal
local hpack_node = node.hpack
local nuts = nodes.nuts
diff --git a/tex/context/base/mkxl/font-con.lmt b/tex/context/base/mkxl/font-con.lmt
index 88e17290a..60e3f0233 100644
--- a/tex/context/base/mkxl/font-con.lmt
+++ b/tex/context/base/mkxl/font-con.lmt
@@ -51,6 +51,8 @@ constructors.designsizes = designsizes
local loadedfonts = allocate()
constructors.loadedfonts = loadedfonts
+----- scalecommands = fonts.helpers.scalecommands
+
--[[ldx--
<p>We need to normalize the scale factor (in scaled points). This has to
do with the fact that <l n='tex'/> uses a negative multiple of 1000 as
@@ -260,6 +262,8 @@ function constructors.scale(tfmdata,specification)
end
target.specification = specification
--
+ local scalecommands = fonts.helpers.scalecommands -- defined later
+ --
local scaledpoints = specification.size
local relativeid = specification.relativeid
--
@@ -774,37 +778,7 @@ function constructors.scale(tfmdata,specification)
end
local vc = character.commands
if vc then
- -- we assume non scaled commands here
- -- tricky .. we need to scale pseudo math glyphs too
- -- which is why we deal with rules too
- local ok = false
- for i=1,#vc do
- local key = vc[i][1]
- if key == "right" or key == "down" or key == "rule" then
- ok = true
- break
- end
- end
- if ok then
- local tt = { }
- for i=1,#vc do
- local ivc = vc[i]
- local key = ivc[1]
- if key == "right" then
- tt[i] = { key, ivc[2]*hdelta }
- elseif key == "down" then
- tt[i] = { key, ivc[2]*vdelta }
- elseif key == "rule" then
- tt[i] = { key, ivc[2]*vdelta, ivc[3]*hdelta }
- else -- not comment
- tt[i] = ivc -- shared since in cache and untouched
- end
- end
- chr.commands = tt
- else
- chr.commands = vc
- end
- -- chr.index = nil
+ chr.commands = scalecommands(vc,hdelta,vdelta)
end
targetcharacters[unicode] = chr
end
diff --git a/tex/context/base/mkxl/font-fbk.lmt b/tex/context/base/mkxl/font-fbk.lmt
index 651bca331..47d284c84 100644
--- a/tex/context/base/mkxl/font-fbk.lmt
+++ b/tex/context/base/mkxl/font-fbk.lmt
@@ -63,13 +63,12 @@ local function composecharacters(tfmdata)
local deltaxheight = scale * (Xdesc.boundingbox[4] - xdesc.boundingbox[4])
local extraxheight = fraction * deltaxheight -- maybe use compose value
local italicfactor = parameters.italicfactor or 0
- local vfspecials = backends.tables.vfspecials --brr
local red, green, blue, black
if trace_visualize then
- red = vfspecials.startcolor("red")
- green = vfspecials.startcolor("green")
- blue = vfspecials.startcolor("blue")
- black = vfspecials.stopcolor
+ red = { "startcolor", "red" }
+ green = { "startcolor", "green" }
+ blue = { "startcolor", "blue" }
+ black = { "stopcolor" }
end
local compose = fonts.goodies.getcompositions(tfmdata)
if compose and trace_visualize then
diff --git a/tex/context/base/mkxl/font-imp-math.lmt b/tex/context/base/mkxl/font-imp-math.lmt
index 079c867e2..277190f24 100644
--- a/tex/context/base/mkxl/font-imp-math.lmt
+++ b/tex/context/base/mkxl/font-imp-math.lmt
@@ -70,6 +70,35 @@ registerotffeature {
-- A quick and dirty and low level implementation but okay for testing:
+function fonts.helpers.mathscriptslots(tfmdata,textcode)
+ local rawdata = tfmdata.shared.rawdata
+ local rawresources = rawdata and rawdata.resources
+ local rawfeatures = rawresources and rawresources.features
+ local basesubstitutions = rawfeatures and rawfeatures.gsub
+ local sequences = basesubstitutions and tfmdata.resources.sequences
+ if sequences then
+ local characters = tfmdata.characters
+ if characters[textcode] then
+ for s=1,#sequences do
+ local sequence = sequences[s]
+ local sfeatures = sequence.features
+ if sfeatures and sfeatures.ssty then
+ local steps = sequence.steps
+ for i=1,#steps do
+ local coverage = steps[i].coverage
+ if coverage then
+ local okay = coverage[textcode]
+ if okay then
+ return okay
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
local function manipulate(tfmdata,key,value)
if texconditionals["c_font_compact"] then
local rawdata = tfmdata.shared.rawdata
@@ -81,7 +110,7 @@ local function manipulate(tfmdata,key,value)
if sequences then
local characters = tfmdata.characters
for s=1,#sequences do
- local sequence = sequences[s]
+ local sequence = sequences[s]
local sfeatures = sequence.features
if sfeatures and sfeatures.ssty then
local steps = sequence.steps
diff --git a/tex/context/base/mkxl/font-imp-tracing.lmt b/tex/context/base/mkxl/font-imp-tracing.lmt
new file mode 100644
index 000000000..59603c9dd
--- /dev/null
+++ b/tex/context/base/mkxl/font-imp-tracing.lmt
@@ -0,0 +1,286 @@
+if not modules then modules = { } end modules ['font-imp-tracing'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local abs = math.abs
+
+local next, type = next, type
+local concat = table.concat
+local formatters = string.formatters
+
+local fonts = fonts
+
+local handlers = fonts.handlers
+local registerotffeature = handlers.otf.features.register
+local registerafmfeature = handlers.afm.features.register
+
+local settings_to_array = utilities.parsers.settings_to_array
+local setmetatableindex = table.setmetatableindex
+
+local helpers = fonts.helpers
+local appendcommandtable = helpers.appendcommandtable
+local prependcommands = helpers.prependcommands
+local charcommand = helpers.commands.char
+
+local variables = interfaces.variables
+
+local v_background = variables.background
+local v_frame = variables.frame
+local v_empty = variables.empty
+local v_none = variables.none
+
+local function initialize(tfmdata,key,value)
+ if value then
+ local vfspecials = fonts.helpers.vfspecials
+ local vfcommands = fonts.helpers.commands
+ local backgrounds = vfspecials.backgrounds
+ local outlines = vfspecials.outlines
+ local characters = tfmdata.characters
+ local rulecache = backgrounds
+ local showchar = true
+ local color = "palegray"
+ if type(value) == "string" then
+ value = settings_to_array(value)
+ for i=1,#value do
+ local v = value[i]
+ if v == v_frame then
+ rulecache = outlines
+ elseif v == v_background then
+ rulecache = backgrounds
+ elseif v == v_empty then
+ showchar = false
+ elseif v == v_none then
+ color = nil
+ else
+ color = v
+ end
+ end
+ end
+ local gray = color and { "startcolor", color } or nil
+ local black = gray and { "stopcolor" } or nil
+ for unicode, character in next, characters do
+ local width = character.width or 0
+ local height = character.height or 0
+ local depth = character.depth or 0
+ local rule = rulecache[height][depth][width]
+ if showchar then
+ local commands = character.commands
+ if commands then
+ if gray then
+ character.commands = prependcommands (
+ commands, gray, rule, black
+ )
+ else
+ character.commands = prependcommands (
+ commands, rule
+ )
+ end
+ else
+ local char = charcommand[unicode]
+ if gray then
+ character.commands = {
+ gray, rule, black, char
+ }
+ else
+ character.commands = {
+ rule, char
+ }
+ end
+ end
+ else
+ if gray then
+ character.commands = {
+ gray, rule, black
+ }
+ else
+ character.commands = {
+ rule
+ }
+ end
+ end
+ end
+ end
+end
+
+local specification = {
+ name = "boundingbox",
+ description = "show boundingbox",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initialize(tfmdata,key,value)
+ if value then
+ local rawdata = tfmdata.shared.rawdata
+ local rawresources = rawdata and rawdata.resources
+ local mathconstants = rawresources.mathconstants
+ if mathconstants then
+ local vfspecials = fonts.helpers.vfspecials
+ local vfcommands = fonts.helpers.commands
+ local backgrounds = vfspecials.backgrounds
+ local outlines = vfspecials.outlines
+ local characters = tfmdata.characters
+ local rulecache = backgrounds
+ local push = vfcommands.push
+ local pop = vfcommands.pop
+ local black = { "stopcolor" }
+ local itcolor = { "startcolor", "trace:0" } -- s / dd (transparent)
+ local brcolor = { "startcolor", "trace:1" } -- r / dr
+ local trcolor = { "startcolor", "trace:2" } -- g / dg
+ local blcolor = { "startcolor", "trace:3" } -- b / db
+ local tlcolor = { "startcolor", "trace:4" } -- y / dy
+ for unicode, character in next, characters do
+ local mathkern = character.mathkern
+ local italic = character.vert_italic or character.italic
+ if mathkern or (italic and italic ~= 0) then
+ local width = character.width or 0
+ local height = character.height or 0
+ local depth = character.depth or 0
+ local list = { }
+ local count = 0
+ if italic and italic ~= 0 then
+ count = count + 1 list[count] = itcolor
+ count = count + 1 list[count] = push
+ count = count + 1 list[count] = { "offset", width + (italic < 0 and -italic or 0), 0 }
+ count = count + 1 list[count] = rulecache[height][depth][abs(-italic)]
+ count = count + 1 list[count] = pop
+ count = count + 1 list[count] = black
+ end
+ if mathkern then
+ local br = mathkern.bottom_right
+ local tr = mathkern.top_right
+ local bl = mathkern.bottom_left
+ local tl = mathkern.top_left
+ if br then
+ local done = false
+ for i=1,#br do
+ local l = br[i]
+ local h = l.height or 0
+ local k = l.kern or 0
+ if k ~= 0 then
+ if h == 0 then
+ h = height + depth -- todo max
+ end
+ if not done then
+ count = count + 1 list[count] = brcolor
+ done = true
+ end
+ count = count + 1 list[count] = push
+ count = count + 1 list[count] = { "offset", width + (k < 0 and k or 0), - depth }
+ count = count + 1 list[count] = rulecache[h][0][abs(k)]
+ count = count + 1 list[count] = pop
+ end
+ end
+ if done then
+ count = count + 1 list[count] = black
+ end
+ end
+ if tr then
+ local done = false
+ for i=1,#tr do
+ local l = tr[i]
+ local h = l.height or 0
+ local k = l.kern or 0
+ if k ~= 0 then
+ if h == 0 then
+ h = height + depth -- todo max
+ end
+ if not done then
+ count = count + 1 list[count] = trcolor
+ done = true
+ end
+ count = count + 1 list[count] = push
+ count = count + 1 list[count] = { "offset", width + (k < 0 and k or 0), height - h }
+ count = count + 1 list[count] = rulecache[h][0][abs(k)]
+ count = count + 1 list[count] = pop
+ end
+ end
+ if done then
+ count = count + 1 list[count] = black
+ end
+ end
+ if bl then
+ local done = false
+ for i=1,#bl do
+ local l = bl[i]
+ local h = l.height or 0
+ local k = l.kern or 0
+ if k ~= 0 then
+ if h == 0 then
+ h = height + depth -- todo max
+ end
+ if not done then
+ count = count + 1 list[count] = blcolor
+ done = true
+ end
+ count = count + 1 list[count] = push
+ count = count + 1 list[count] = { "offset", (k < 0 and k or 0), -depth }
+ count = count + 1 list[count] = rulecache[h][0][abs(k)]
+ count = count + 1 list[count] = pop
+ end
+ end
+ if done then
+ count = count + 1 list[count] = black
+ end
+ end
+ if tl then
+ local done = false
+ for i=1,#tl do
+ local l = tl[i]
+ local h = l.height or 0
+ local k = l.kern or 0
+ if k ~= 0 then
+ if h == 0 then
+ h = height + depth -- todo max
+ end
+ if not done then
+ count = count + 1 list[count] = tlcolor
+ done = true
+ end
+ count = count + 1 list[count] = push
+ count = count + 1 list[count] = { "offset", (k < 0 and k or 0), height - h }
+ count = count + 1 list[count] = rulecache[h][0][abs(k)]
+ count = count + 1 list[count] = pop
+ end
+ end
+ if done then
+ count = count + 1 list[count] = black
+ end
+ end
+ end
+ if count > 0 then
+ local commands = character.commands
+ if commands then
+ character.commands = appendcommandtable(commands,list)
+ else
+ list[#list+1] = charcommand[unicode]
+ character.commands = list
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+local specification = {
+ name = "staircase",
+ description = "show staircase kerns",
+-- position = 1,
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
diff --git a/tex/context/base/mkxl/font-lib.mklx b/tex/context/base/mkxl/font-lib.mklx
index 00bddc2c3..e90973d75 100644
--- a/tex/context/base/mkxl/font-lib.mklx
+++ b/tex/context/base/mkxl/font-lib.mklx
@@ -17,7 +17,7 @@
\registerctxluafile{font-ini}{autosuffix}
\registerctxluafile{font-log}{}
-\registerctxluafile{font-con}{autosuffix}
+\registerctxluafile{font-con}{autosuffix} % kind of early
%registerctxluafile{font-cft}{}
\registerctxluafile{font-enc}{}
\registerctxluafile{font-fmp}{autosuffix}
@@ -88,7 +88,7 @@
\registerctxluafile{good-ini}{}
\registerctxluafile{good-gen}{}
\registerctxluafile{good-ctx}{}
-\registerctxluafile{good-mth}{}
+\registerctxluafile{good-mth}{autosuffix}
\registerctxluafile{font-def}{autosuffix}
\registerctxluafile{font-ctx}{autosuffix} % after def as it overloads
@@ -116,7 +116,7 @@
% not yet, lmtx feature
}
-\registerctxluafile{font-imp-tracing}{} % comes last!
+\registerctxluafile{font-imp-tracing}{autosuffix} % comes last!
\registerctxluafile{font-fbk}{autosuffix}
diff --git a/tex/context/base/mkxl/font-ogr.lmt b/tex/context/base/mkxl/font-ogr.lmt
index df6449ded..a3f8acb3c 100644
--- a/tex/context/base/mkxl/font-ogr.lmt
+++ b/tex/context/base/mkxl/font-ogr.lmt
@@ -242,6 +242,8 @@ do -- this will move to its own module
return false
end
+ -- list of tonumber keywords
+
local function initializemps(tfmdata,kind,value)
if value then
local specification = settings_to_hash_strict(value)
@@ -256,9 +258,20 @@ do -- this will move to its own module
local categories = settings_to_array(category)
local usedshapes = nil
local index = 0
- local spread = tonumber(specification.spread or 0)
+ local spread = tonumber(specification.spread or 0) -- hm
local hascolor = hascolorspec(specification)
- specification.spread = spread -- now a number
+
+ specification.spread = spread -- now a number, maybe also for slant, weight etc
+
+ local preroll = specification.preroll
+ if preroll then
+ metapost.simple(instance,"begingroup;",true,true)
+ metapost.setparameterset("mpsfont",specification)
+ metapost.simple("simplefun",preroll)
+ metapost.setparameterset("mpsfont")
+ metapost.simple(instance,"endgroup;",true,true)
+ end
+
for i=1,#categories do
local category = categories[i]
local mpsshapes = shapes[category]
@@ -291,25 +304,39 @@ do -- this will move to its own module
}
-- todo: deal with extensibles and more properties
for unicode, shape in sortedhash(mpsshapes.glyphs) do
- -- local oldc = characters[unicode]
- -- if oldc then
- index = index + 1 -- todo: somehow we end up with 2 as first entry after 0
- local wd = shape.width or defaultwidth
- local ht = shape.height or defaultheight
- local dp = shape.depth or defaultdepth
- local newc = {
- index = index, -- into usedshapes
- width = scale * (wd + spread),
- height = scale * ht,
- depth = scale * dp,
- unicode = unicode,
- }
- --
- characters [unicode] = newc
- descriptions[unicode] = newc
- --
- usedshapes[unicode] = shape.code or defaultcode
- -- end
+ index = index + 1 -- todo: somehow we end up with 2 as first entry after 0
+ local wd = shape.width or defaultwidth
+ local ht = shape.height or defaultheight
+ local dp = shape.depth or defaultdepth
+ local uc = shape.tounicode
+ if uc then
+ uc = round(uc) -- brrr can be 123.0
+ end
+ local newc = {
+ index = index, -- into usedshapes
+ width = scale * (wd + spread),
+ height = scale * ht,
+ depth = scale * dp,
+ unicode = uc or unicode,
+ }
+ --
+ characters [unicode] = newc
+ descriptions[unicode] = newc
+ usedshapes [unicode] = shape.code or defaultcode
+ --
+ -- This is a way to get/use randomized shapes (see punk example).
+ --
+ if uc and uc ~= unicode then
+ local c = characters[uc]
+ if c then
+ local v = c.variants
+ if v then
+ v[#v + 1] = unicode
+ else
+ c.variants = { unicode }
+ end
+ end
+ end
end
end
end
diff --git a/tex/context/base/mkxl/font-pre.mkxl b/tex/context/base/mkxl/font-pre.mkxl
index fafe20a60..884a6c913 100644
--- a/tex/context/base/mkxl/font-pre.mkxl
+++ b/tex/context/base/mkxl/font-pre.mkxl
@@ -405,7 +405,9 @@
mathalternates=yes,
mathitalics=yes, % we pass them
mathdimensions=all,
-compactmath=yes,
+ % mathkerns=yes,
+ % staircase=yes,
+ compactmath=yes,
% mathgaps=yes,
language=dflt,
script=math]
diff --git a/tex/context/base/mkxl/font-vfc.lmt b/tex/context/base/mkxl/font-vfc.lmt
index e39eca683..9330bdea0 100644
--- a/tex/context/base/mkxl/font-vfc.lmt
+++ b/tex/context/base/mkxl/font-vfc.lmt
@@ -71,13 +71,111 @@ function helpers.appendcommandtable(commands,t)
end
helpers.commands = utilities.storage.allocate {
- char = setmetatableindex(function(t,k) local v = { "slot", 0, k } t[k] = v return v end),
- right = setmetatableindex(function(t,k) local v = { "right", k } t[k] = v return v end),
- left = setmetatableindex(function(t,k) local v = { "right", -k } t[k] = v return v end), -- todo: left
- down = setmetatableindex(function(t,k) local v = { "down", k } t[k] = v return v end),
- up = setmetatableindex(function(t,k) local v = { "down", -k } t[k] = v return v end), -- todo: up
+ char = setmetatableindex(function(t,k) local v = { "slot", 0, k } t[k] = v return v end),
+ right = setmetatableindex(function(t,k) local v = { "right", k } t[k] = v return v end),
+ left = setmetatableindex(function(t,k) local v = { "left", k } t[k] = v return v end),
+ down = setmetatableindex(function(t,k) local v = { "down", k } t[k] = v return v end),
+ up = setmetatableindex(function(t,k) local v = { "up", k } t[k] = v return v end),
push = push,
pop = pop,
dummy = dummy,
}
+helpers.vfinjectors = {
+ -- backend specific: startcolor, stopcolor etc
+}
+
+-- maybe round()
+
+local defaultline = 16384
+
+helpers.vfspecials = {
+
+ backgrounds = setmetatableindex(function(t,h)
+ local v = setmetatableindex(function(t,d)
+ local v = setmetatableindex(function(t,w)
+ local v = { "frame", w, h, d, defaultline, true, true }
+ t[w] = v
+ return v
+ end)
+ t[d] = v
+ return v
+ end)
+ t[h] = v
+ return v
+ end),
+
+ outlines = setmetatableindex(function(t,h)
+ local v = setmetatableindex(function(t,d)
+ local v = setmetatableindex(function(t,w)
+ local v = { "frame", w, h, d, defaultline, false, true }
+ t[w] = v
+ return v
+ end)
+ t[d] = v
+ return v
+ end)
+ t[h] = v
+ return v
+ end),
+
+}
+
+-- In the past we only copied when we had something that got scaled but the problem
+-- is that we then run into issues when we extend a commands in the parent. This
+-- needs checking. When we go to glyph scaling, this can go away.
+--
+-- The alternative is to work with unscaled values and always do scaling at the
+-- TeX end. So, then we need accessors instead of tables and we also need to check
+-- all the context code: where do we access values?
+--
+-- On the other hand, in glyph scale mode we hardly do any scaling so we seldom
+-- call the next one.
+--
+-- What if we use named fields: then we can scale by field name.
+
+local scaled = {
+ right = true,
+ down = true,
+ left = true,
+ right = true,
+ offset = true,
+ rule = true,
+ char = false,
+ font = false,
+ slot = false,
+ use = false,
+ push = false,
+ pop = false,
+ lua = false,
+ -- obsolete
+ node = false,
+ -- additional ones are never scaled (color etc)
+}
+
+function helpers.scalecommands(list,hdelta,vdelta)
+ local n = #list
+ for i=1,n do
+ local key = list[i][1]
+ if scaled[list[i][1]] then
+ local result = { }
+ for i=1,n do
+ local cmd = list[i]
+ local key = ivc[1]
+ if key == "right" or key == "left" then
+ result[i] = { key, cmd[2]*hdelta }
+ elseif key == "down" or key == "up" then
+ result[i] = { key, cmd[2]*vdelta }
+ elseif key == "offset" or key == "rule" then
+ result[i] = { key, cmd[2]*hdelta, cmd[3]*vdelta }
+ -- elseif key == "frame" then
+ -- result[i] = cmd -- already scaled, for now
+ else
+ result[i] = cmd -- shared since in cache and untouched
+ end
+ end
+ return result
+ end
+ end
+ return list
+end
diff --git a/tex/context/base/mkxl/good-mth.lmt b/tex/context/base/mkxl/good-mth.lmt
new file mode 100644
index 000000000..87b6787df
--- /dev/null
+++ b/tex/context/base/mkxl/good-mth.lmt
@@ -0,0 +1,464 @@
+if not modules then modules = { } end modules ['good-mth'] = {
+ version = 1.000,
+ comment = "companion to font-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next, tonumber, unpack = type, next, tonumber, unpack
+local ceil = math.ceil
+local match = string.match
+
+local fonts = fonts
+
+local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end)
+local report_goodies = logs.reporter("fonts","goodies")
+
+local registerotffeature = fonts.handlers.otf.features.register
+
+local fontgoodies = fonts.goodies or { }
+
+local fontcharacters = fonts.hashes.characters
+
+local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end)
+
+local report_math = logs.reporter("mathematics","initializing")
+
+local nuts = nodes.nuts
+
+local setlink = nuts.setlink
+
+local nodepool = nuts.pool
+
+local new_kern = nodepool.kern
+local new_glyph = nodepool.glyph
+local new_hlist = nodepool.hlist
+local new_vlist = nodepool.vlist
+
+local insert_node_after = nuts.insert_after
+
+local helpers = fonts.helpers
+local upcommand = helpers.commands.up
+local rightcommand = helpers.commands.right
+local charcommand = helpers.commands.char
+local prependcommands = helpers.prependcommands
+
+-- experiment, we have to load the definitions immediately as they precede
+-- the definition so they need to be initialized in the typescript
+
+local function withscriptcode(tfmdata,unicode,data,action)
+ if type(unicode) == "string" then
+ local p, u = match(unicode,"^(.-):(.-)$")
+ if u then
+ u = tonumber(u)
+ if u then
+ local slots = fonts.helpers.mathscriptslots(tfmdata,u)
+ if slots then
+ if p == "*" then
+ action(u,data)
+ for i=1,#slots do
+ action(slots[i],data)
+ end
+ else
+ p = tonumber(p)
+ if p then
+ action(slots[p],data)
+ end
+ end
+ end
+ end
+ end
+ else
+ action(unicode,data)
+ end
+end
+
+local function finalize(tfmdata,feature,value)
+-- if tfmdata.mathparameters then -- funny, cambria text has this
+ local goodies = tfmdata.goodies
+ if goodies then
+ local virtualized = mathematics.virtualized
+ for i=1,#goodies do
+ local goodie = goodies[i]
+ local mathematics = goodie.mathematics
+ local dimensions = mathematics and mathematics.dimensions
+ if dimensions then
+ if trace_defining then
+ report_math("overloading dimensions in %a @ %p",tfmdata.properties.fullname,tfmdata.parameters.size)
+ end
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local parameters = tfmdata.parameters
+ local factor = parameters.factor
+ local hfactor = parameters.hfactor
+ local vfactor = parameters.vfactor
+ --
+ tfmdata.type = "virtual"
+ tfmdata.properties.virtualized = true
+ --
+ local function overloadone(unicode,data)
+ local character = characters[unicode]
+ if not character then
+ local c = virtualized[unicode]
+ if c then
+ character = characters[c]
+ end
+ end
+ if character then
+ local width = data.width
+ local height = data.height
+ local depth = data.depth
+ if trace_defining and (width or height or depth) then
+ report_math("overloading dimensions of %C, width %p, height %p, depth %p",
+ unicode,width or 0,height or 0,depth or 0)
+ end
+ if width then character.width = width * hfactor end
+ if height then character.height = height * vfactor end
+ if depth then character.depth = depth * vfactor end
+ --
+ local xoffset = data.xoffset
+ local yoffset = data.yoffset
+ if xoffset == "llx" then
+ local d = descriptions[unicode]
+ if d then
+ xoffset = - d.boundingbox[1] * hfactor
+ character.width = character.width + xoffset
+ xoffset = rightcommand[xoffset]
+ else
+ xoffset = nil
+ end
+ elseif xoffset and xoffset ~= 0 then
+ xoffset = rightcommand[xoffset * hfactor]
+ else
+ xoffset = nil
+ end
+ if yoffset and yoffset ~= 0 then
+ yoffset = upcommand[yoffset * vfactor]
+ else
+ yoffset = nil
+ end
+ if xoffset or yoffset then
+ local commands = characters.commands
+ if commands then
+ prependcommands(commands,yoffset,xoffset)
+ else
+ local slot = charcommand[unicode]
+ if xoffset and yoffset then
+ character.commands = { xoffset, yoffset, slot }
+ elseif xoffset then
+ character.commands = { xoffset, slot }
+ else
+ character.commands = { yoffset, slot }
+ end
+ end
+ end
+ elseif trace_defining then
+ report_math("no overloading dimensions of %C, not in font",unicode)
+ end
+ end
+ local function overload(dimensions)
+ for unicode, data in next, dimensions do
+ withscriptcode(tfmdata,unicode,data,overloadone)
+ end
+ end
+ if value == nil then
+ value = { "default" }
+ end
+ if value == "all" or value == true then
+ for name, value in next, dimensions do
+ overload(value)
+ end
+ else
+ if type(value) == "string" then
+ value = utilities.parsers.settings_to_array(value)
+ end
+ if type(value) == "table" then
+ for i=1,#value do
+ local d = dimensions[value[i]]
+ if d then
+ overload(d)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "mathdimensions",
+ description = "manipulate math dimensions",
+ -- default = true,
+ manipulators = {
+ base = finalize,
+ node = finalize,
+ }
+}
+
+local function initialize(goodies)
+ local mathgoodies = goodies.mathematics
+ if mathgoodies then
+ local virtuals = mathgoodies.virtuals
+ local mapfiles = mathgoodies.mapfiles
+ local maplines = mathgoodies.maplines
+ if virtuals then
+ for name, specification in next, virtuals do
+ -- beware, they are all constructed ... we should be more selective
+ mathematics.makefont(name,specification,goodies)
+ end
+ end
+ if mapfiles then
+ for i=1,#mapfiles do
+ fonts.mappings.loadfile(mapfiles[i]) -- todo: backend function
+ end
+ end
+ if maplines then
+ for i=1,#maplines do
+ fonts.mappings.loadline(maplines[i]) -- todo: backend function
+ end
+ end
+ end
+end
+
+fontgoodies.register("mathematics", initialize)
+
+-- local enabled = false directives.register("fontgoodies.mathkerning",function(v) enabled = v end)
+
+local function initialize(tfmdata)
+-- if enabled and tfmdata.mathparameters then -- funny, cambria text has this
+ if tfmdata.mathparameters then -- funny, cambria text has this
+ local goodies = tfmdata.goodies
+ if goodies then
+ local characters = tfmdata.characters
+ if characters[0x1D44E] then -- 119886
+ -- we have at least an italic a
+ for i=1,#goodies do
+ local mathgoodies = goodies[i].mathematics
+ if mathgoodies then
+ local kerns = mathgoodies.kerns
+ if kerns then
+ local function kernone(unicode,data)
+ local chardata = characters[unicode]
+ if chardata and (not chardata.mathkerns or data.force) then
+ chardata.mathkerns = data
+ end
+ end
+ for unicode, data in next, kerns do
+ withscriptcode(tfmdata,unicode,data,kernone)
+ end
+ return
+ end
+ end
+ end
+ else
+ return -- no proper math font anyway
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "mathkerns",
+ description = "math kerns",
+ -- default = true,
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+-- math italics (not really needed)
+--
+-- it would be nice to have a \noitalics\font option
+
+local function initialize(tfmdata)
+ local goodies = tfmdata.goodies
+ if goodies then
+ local shared = tfmdata.shared
+ for i=1,#goodies do
+ local mathgoodies = goodies[i].mathematics
+ if mathgoodies then
+ local mathitalics = mathgoodies.italics
+ if mathitalics then
+ local properties = tfmdata.properties
+ if properties.setitalics then
+ mathitalics = mathitalics[file.nameonly(properties.name)] or mathitalics
+ if mathitalics then
+ if trace_goodies then
+ report_goodies("loading mathitalics for font %a",properties.name)
+ end
+ local corrections = mathitalics.corrections
+ local defaultfactor = mathitalics.defaultfactor
+ -- properties.mathitalic_defaultfactor = defaultfactor -- we inherit outer one anyway (name will change)
+ if corrections then
+ fontgoodies.registerpostprocessor(tfmdata, function(tfmdata) -- this is another tfmdata (a copy)
+ -- better make a helper so that we have less code being defined
+ local properties = tfmdata.properties
+ local parameters = tfmdata.parameters
+ local characters = tfmdata.characters
+ properties.mathitalic_defaultfactor = defaultfactor
+ properties.mathitalic_defaultvalue = defaultfactor * parameters.quad
+ if trace_goodies then
+ report_goodies("assigning mathitalics for font %a",properties.name)
+ end
+ local quad = parameters.quad
+ local hfactor = parameters.hfactor
+ for k, v in next, corrections do
+ local c = characters[k]
+ if c then
+ if v > -1 and v < 1 then
+ c.italic = v * quad
+ else
+ c.italic = v * hfactor
+ end
+ else
+ report_goodies("invalid mathitalics entry %U for font %a",k,properties.name)
+ end
+ end
+ end)
+ end
+ return -- maybe not as these can accumulate
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "mathitalics",
+ description = "additional math italic corrections",
+ -- default = true,
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+-- fontgoodies.register("mathitalics", initialize)
+
+local function mathradicalaction(n,h,v,font,mchar,echar)
+ local characters = fontcharacters[font]
+ local mchardata = characters[mchar]
+ local echardata = characters[echar]
+ local ewidth = echardata.width
+ local mwidth = mchardata.width
+ local delta = h - ewidth
+ local glyph = new_glyph(font,echar)
+ local head = glyph
+ if delta > 0 then
+ local count = ceil(delta/mwidth)
+ local kern = (delta - count * mwidth) / count
+ for i=1,count do
+ local k = new_kern(kern)
+ local g = new_glyph(font,mchar)
+ setlink(k,head)
+ setlink(g,k)
+ head = g
+ end
+ end
+ local height = mchardata.height
+ local list = new_hlist(head)
+ local kern = new_kern(height-v)
+ list = setlink(kern,list)
+ local list = new_vlist(kern)
+ insert_node_after(n,n,list)
+end
+
+local function mathhruleaction(n,h,v,font,bchar,mchar,echar)
+ local characters = fontcharacters[font]
+ local bchardata = characters[bchar]
+ local mchardata = characters[mchar]
+ local echardata = characters[echar]
+ local bwidth = bchardata.width
+ local mwidth = mchardata.width
+ local ewidth = echardata.width
+ local delta = h - ewidth - bwidth
+ local glyph = new_glyph(font,echar)
+ local head = glyph
+ if delta > 0 then
+ local count = ceil(delta/mwidth)
+ local kern = (delta - count * mwidth) / (count+1)
+ for i=1,count do
+ local k = new_kern(kern)
+ local g = new_glyph(font,mchar)
+ setlink(k,head)
+ setlink(g,k)
+ head = g
+ end
+ local k = new_kern(kern)
+ setlink(k,head)
+ head = k
+ end
+ local g = new_glyph(font,bchar)
+ setlink(g,head)
+ head = g
+ local height = mchardata.height
+ local list = new_hlist(head)
+ local kern = new_kern(height-v)
+ list = setlink(kern,list)
+ local list = new_vlist(kern)
+ insert_node_after(n,n,list)
+end
+
+local function initialize(tfmdata)
+ local goodies = tfmdata.goodies
+ if goodies then
+ local resources = tfmdata.resources
+ local ruledata = { }
+ for i=1,#goodies do
+ local mathematics = goodies[i].mathematics
+ if mathematics then
+ local rules = mathematics.rules
+ if rules then
+ for tag, name in next, rules do
+ ruledata[tag] = name
+ end
+ end
+ end
+ end
+ if next(ruledata) then
+ local characters = tfmdata.characters
+ local unicodes = resources.unicodes
+ if characters and unicodes then
+ local mathruleactions = resources.mathruleactions
+ if not mathruleactions then
+ mathruleactions = { }
+ resources.mathruleactions = mathruleactions
+ end
+ --
+ local mchar = unicodes[ruledata["radical.extender"] or false]
+ local echar = unicodes[ruledata["radical.end"] or false]
+ if mchar and echar then
+ mathruleactions.radicalaction = function(n,h,v,font)
+ mathradicalaction(n,h,v,font,mchar,echar)
+ end
+ end
+ --
+ local bchar = unicodes[ruledata["hrule.begin"] or false]
+ local mchar = unicodes[ruledata["hrule.extender"] or false]
+ local echar = unicodes[ruledata["hrule.end"] or false]
+ if bchar and mchar and echar then
+ mathruleactions.hruleaction = function(n,h,v,font)
+ mathhruleaction(n,h,v,font,bchar,mchar,echar)
+ end
+ end
+ -- not that nice but we need to register it at the tex end
+ -- context.enablemathrules("\\fontclass")
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "mathrules",
+ description = "check math rules",
+ default = true,
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
diff --git a/tex/context/base/mkxl/layo-ini.lmt b/tex/context/base/mkxl/layo-ini.lmt
new file mode 100644
index 000000000..1570075d9
--- /dev/null
+++ b/tex/context/base/mkxl/layo-ini.lmt
@@ -0,0 +1,115 @@
+if not modules then modules = { } end modules ['layo-ini'] = {
+ version = 1.001,
+ comment = "companion to layo-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- We need to share information between the TeX and Lua end about the typographical
+-- model. This happens here. This code might move.
+
+local texgetcount = tex.getcount
+local conditionals = tex.conditionals
+
+layouts = {
+ status = { },
+}
+
+local status = layouts.status
+
+function status.leftorrightpageaction(left,right)
+ if left == nil then
+ left, right = false, true
+ end
+ if not conditionals.layoutisdoublesided then
+ return left, right
+ elseif conditionals.layoutissinglesided then
+ return left, right
+ elseif texgetcount("pagenoshift") % 2 == 0 then
+ if texgetcount("realpageno") % 2 == 0 then
+ return right, left
+ else
+ return left, right
+ end
+ else
+ if texgetcount("realpageno") % 2 == 0 then
+ return left, right
+ else
+ return right, left
+ end
+ end
+end
+
+function status.isleftpage(r)
+ if not conditionals.layoutisdoublesided then
+ return false
+ elseif conditionals.layoutissinglesided then
+ return false
+ elseif texgetcount("pagenoshift") % 2 == 0 then
+ return (r or texgetcount("realpageno")) % 2 == 0
+ else
+ return not (r or texgetcount("realpageno")) % 2 == 0
+ end
+end
+
+-- Instead of making these these driver specific we make them generic. We can even consider
+-- to make these registers at the tex end.
+
+local canvas = {
+ pagespec = "default", -- v_default
+ paperwidth = 0,
+ paperheight = 0,
+ topoffset = 0,
+ leftoffset = 0,
+ height = 0,
+ width = 0,
+ cropoffset = 0,
+ bleedoffset = 0,
+ trimoffset = 0,
+ artoffset = 0,
+ doublesided = false,
+ marked = false,
+ copies = false,
+}
+
+function layouts.setupcanvas(specification)
+ local paperheight = specification.paperheight or canvas.paperheight
+ local paperwidth = specification.paperwidth or canvas.paperwidth
+ local cropoffset = specification.cropoffset or 0
+ local trimoffset = cropoffset - (specification.trimoffset or 0)
+ local bleedoffset = trimoffset - (specification.bleedoffset or 0)
+ local artoffset = bleedoffset - (specification.artoffset or 0)
+ --
+ canvas.paperheight = paperheight
+ canvas.paperwidth = paperwidth
+ canvas.cropoffset = cropoffset
+ canvas.trimoffset = trimoffset
+ canvas.bleedoffset = bleedoffset
+ canvas.artoffset = artoffset
+ --
+ canvas.pagespec = specification.mode or pagespec
+ canvas.topoffset = specification.topoffset or 0
+ canvas.leftoffset = specification.leftoffset or 0
+ canvas.height = specification.height or paperheight
+ canvas.width = specification.width or paperwidth
+ canvas.marked = specification.print
+ --
+ local copies = specification.copies
+ if type(copies) == "number" and copies < 2 then
+ canvas.copies = false
+ end
+ --
+ local doublesided = specification.doublesided
+ if doublesided ~= nil then
+ canvas.doublesided = doublesided
+ end
+end
+
+function layouts.getpagedimensions()
+ return canvas.paperwidth, canvas.paperheight
+end
+
+function layouts.getcanvas()
+ return canvas
+end
diff --git a/tex/context/base/mkxl/layo-ini.mkxl b/tex/context/base/mkxl/layo-ini.mkxl
index 4979989cd..73b7e978e 100644
--- a/tex/context/base/mkxl/layo-ini.mkxl
+++ b/tex/context/base/mkxl/layo-ini.mkxl
@@ -25,6 +25,6 @@
\ifdefined\pagenoshift \else \newcount \pagenoshift \fi
\ifdefined\realpageno \else \newcount \realpageno \fi
-\registerctxluafile{layo-ini}{}
+\registerctxluafile{layo-ini}{autosuffix}
\protect \endinput
diff --git a/tex/context/base/mkxl/lpdf-col.lmt b/tex/context/base/mkxl/lpdf-col.lmt
index 778d250c6..a999cb2c7 100644
--- a/tex/context/base/mkxl/lpdf-col.lmt
+++ b/tex/context/base/mkxl/lpdf-col.lmt
@@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['lpdf-col'] = {
license = "see context related readme files"
}
--- slants also page ?
-
local type, next, tostring, tonumber = type, next, tostring, tonumber
local char, byte, format, gsub, rep, gmatch = string.char, string.byte, string.format, string.gsub, string.rep, string.gmatch
local settings_to_array, settings_to_numbers = utilities.parsers.settings_to_array, utilities.parsers.settings_to_numbers
@@ -25,7 +23,7 @@ local registrations = backends.pdf.registrations
local nodepool = nodes.nuts.pool
local register = nodepool.register
-local pageliteral = nodepool.pageliteral
+local setstate = nodepool.setstate
local pdfconstant = lpdf.constant
local pdfdictionary = lpdf.dictionary
@@ -131,26 +129,26 @@ lpdf.registerpagefinalizer(addpagegroup,3,"pagegroup")
-- color injection
function nodeinjections.rgbcolor(r,g,b)
- return register(pageliteral(f_rgb(r,g,b,r,g,b)))
+ return register(setstate(f_rgb(r,g,b,r,g,b)))
end
function nodeinjections.cmykcolor(c,m,y,k)
- return register(pageliteral(f_cmyk(c,m,y,k,c,m,y,k)))
+ return register(setstate(f_cmyk(c,m,y,k,c,m,y,k)))
end
function nodeinjections.graycolor(s) -- caching 0/1 does not pay off
- return register(pageliteral(f_gray(s,s)))
+ return register(setstate(f_gray(s,s)))
end
function nodeinjections.spotcolor(n,f,d,p)
if type(p) == "string" then
p = gsub(p,","," ") -- brr misuse of spot
end
- return register(pageliteral(f_spot(n,n,p,p)))
+ return register(setstate(f_spot(n,n,p,p)))
end
function nodeinjections.transparency(n)
- return register(pageliteral(f_tr_gs(n)))
+ return register(setstate(f_tr_gs(n)))
end
-- a bit weird but let's keep it here for a while
@@ -169,7 +167,7 @@ function nodeinjections.effect(effect,stretch,rulethickness)
-- always, no zero test (removed)
rulethickness = bp * rulethickness
effect = effects[effect] or effects['normal']
- return register(pageliteral(f_effect(stretch,rulethickness,effect))) -- watch order
+ return register(setstate(f_effect(stretch,rulethickness,effect))) -- watch order
end
-- spot- and indexcolors
@@ -727,29 +725,20 @@ function lpdf.finishtransparencycode()
end
end
--- this will move to lpdf-spe.lua an dwe then can also add a metatable with
--- normal context colors
-
do
- local pdfcolor = lpdf.color
- local pdftransparency = lpdf.transparency
-
- local f_slant = formatters["q 1 0 %N 1 0 0 cm"]
+ local pdfprint, pdfcolor, pdftransparency
- local slants = setmetatableindex(function(t,k)
- local v = { "pdf", "origin", f_slant(a) }
- t[k] = v
- return k
+ updaters.register("backend.update.lpdf",function()
+ pdfprint = lpdf.print
+ pdfcolor = lpdf.color
+ pdftransparency = lpdf.transparency
end)
- local function startslant(a)
- return slants[a]
- end
-
local c_cache = setmetatableindex(function(t,m)
+ -- We inherit the outer transparency.
local v = setmetatableindex(function(t,c)
- local p = { "pdf", "page", "q " .. pdfcolor(m,c) }
+ local p = "q " .. pdfcolor(m,c)
t[c] = p
return p
end)
@@ -757,13 +746,11 @@ do
return v
end)
- -- we inherit the outer transparency
-
local t_cache = setmetatableindex(function(t,transparency)
local p = pdftransparency(transparency)
local v = setmetatableindex(function(t,colormodel)
local v = setmetatableindex(function(t,color)
- local v = { "pdf", "page", "q " .. pdfcolor(colormodel,color) .. " " .. p }
+ local v = "q " .. pdfcolor(colormodel,color) .. " " .. p
t[color] = v
return v
end)
@@ -774,120 +761,33 @@ do
return v
end)
- local function startcolor(k)
- local m, c = colortoattributes(k)
- local t = transparencytoattribute(k)
- if t and t ~= unsetvalue then
- return t_cache[t][m][c]
- else
- return c_cache[m][c]
- end
- end
-
- -- A problem is that we need to transfer back and this is kind of
- -- messy so we force text mode .. i'll do a better job on that but
- -- will experiment first (both engines). Virtual fonts will change
- -- anyway.
-
- local vfspecials = backends.pdf.tables.vfspecials or allocate { }
- backends.pdf.tables.vfspecials = vfspecials
-
- vfspecials.startcolor = startcolor
- -- vfspecials.stopcolor = { "pdf", "text", "Q" } -- fails
- vfspecials.stopcolor = { "pdf", "page", "Q" }
-
- vfspecials.startslant = startslant
- vfspecials.stopslant = { "pdf", "page", "Q" } -- fails
-
-end
-
--- new method:
-
-do
-
updaters.register("backend.update.lpdf",function()
- pdfprint = lpdf.print
- end)
-
- -- Is this still used? It's a font property now.
-
- local f_slant = formatters["q 1 0 %N 1 0 0 cm"]
-
- local slants = setmetatableindex(function(t,k)
- local v = f_slant(a)
- t[k] = v
- return k
- end)
- local function startslant(a)
- return pdfprint("origin", slants[a])
- end
+ local vfinjectors = fonts.helpers.vfinjectors
- local function stopslant()
- pdfprint("text", "Q")
- end
+ vfinjectors.pdf = function(pos_h,pos_v,packet)
+ pdfprint(packet[2],packet[3])
+ end
- -- We inherit the outer transparency.
-
- local pdfcolor = lpdf.color
- local pdftransparency = lpdf.transparency
-
- -- local c_cache = setmetatableindex(function(t,m)
- -- local v = setmetatableindex(function(t,c)
- -- local p = "q " .. pdfcolor(m,c)
- -- t[c] = p
- -- return p
- -- end)
- -- t[m] = v
- -- return v
- -- end)
- --
- -- local t_cache = setmetatableindex(function(t,transparency)
- -- local p = pdftransparency(transparency)
- -- local v = setmetatableindex(function(t,colormodel)
- -- local v = setmetatableindex(function(t,color)
- -- local v = "q " .. pdfcolor(colormodel,color) .. " " .. p
- -- t[color] = v
- -- return v
- -- end)
- -- t[colormodel] = v
- -- return v
- -- end)
- -- t[transparency] = v
- -- return v
- -- end)
-
- -- local function startcolor(color)
- -- local m, c = colortoattributes(color)
- -- local t = transparencytoattribute(color)
- -- if t then
- -- pdfprint("page", t_cache[t][m][c])
- -- else
- -- pdfprint("page", c_cache[m][c])
- -- end
- -- end
-
- local function startcolor(color)
- local m, c = colortoattributes(color)
- local t = transparencytoattribute(color)
- if t and t ~= unsetvalue then
- pdfprint("page", "q " .. pdfcolor(m,c) .. " " .. pdftransparency(t))
- else
- pdfprint("page", "q " .. pdfcolor(m,c))
+ 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
+ else
+ pdfprint("page", "q")
+ end
end
- end
- local function stopcolor()
- pdfprint("text", "Q")
- end
+ vfinjectors.stopcolor = function()
+ pdfprint("text", "Q")
+ end
- updaters.register("backend.update.lpdf",function()
- fonts.vfcommands = {
- startslant = startslant,
- stopslant = stopslant,
- startcolor = startcolor,
- stopcolor = stopcolor,
- }
end)
end
diff --git a/tex/context/base/mkxl/lpdf-ini.lmt b/tex/context/base/mkxl/lpdf-ini.lmt
index 59e728dfb..ea9466d39 100644
--- a/tex/context/base/mkxl/lpdf-ini.lmt
+++ b/tex/context/base/mkxl/lpdf-ini.lmt
@@ -82,12 +82,11 @@ do
lpdf.getpos = drivers.getpos
end)
- local pdfgetmatrix, pdfhasmatrix, pdfprint, pdfgetpos
+ local pdfgetmatrix, pdfhasmatrix, pdfgetpos
updaters.register("backend.update.lpdf",function()
pdfgetmatrix = lpdf.getmatrix
pdfhasmatrix = lpdf.hasmatrix
- pdfprint = lpdf.print
pdfgetpos = lpdf.getpos
end)
@@ -541,21 +540,6 @@ end
local function add_x(t,k,v) rawset(t,k,tostring(v)) end
--- local mt_x = { __index = { __lpdftype__ = "stream" }, __lpdftype = "stream", __tostring = tostring_x, __call = value_x, __newindex = add_x }
--- local mt_d = { __index = { __lpdftype__ = "dictionary" }, __lpdftype = "dictionary", __tostring = tostring_d, __call = value_d, __add = add_to_d }
--- local mt_a = { __index = { __lpdftype__ = "array" }, __lpdftype = "array", __tostring = tostring_a, __call = value_a, __add = add_to_a }
--- local mt_u = { __index = { __lpdftype__ = "unicode" }, __lpdftype = "unicode", __tostring = tostring_u, __call = value_u }
--- local mt_s = { __index = { __lpdftype__ = "string" }, __lpdftype = "string", __tostring = tostring_s, __call = value_s }
--- local mt_p = { __index = { __lpdftype__ = "docstring" }, __lpdftype = "docstring", __tostring = tostring_p, __call = value_p }
--- local mt_n = { __index = { __lpdftype__ = "number" }, __lpdftype = "number", __tostring = tostring_n, __call = value_n }
--- local mt_c = { __index = { __lpdftype__ = "constant" }, __lpdftype = "constant", __tostring = tostring_c, __call = value_c }
--- local mt_z = { __index = { __lpdftype__ = "null" }, __lpdftype = "null", __tostring = tostring_z, __call = value_z }
--- local mt_t = { __index = { __lpdftype__ = "true" }, __lpdftype = "true", __tostring = tostring_t, __call = value_t }
--- local mt_f = { __index = { __lpdftype__ = "false" }, __lpdftype = "false", __tostring = tostring_f, __call = value_f }
--- local mt_r = { __index = { __lpdftype__ = "reference" }, __lpdftype = "reference", __tostring = tostring_r, __call = value_r }
--- local mt_v = { __index = { __lpdftype__ = "verbose" }, __lpdftype = "verbose", __tostring = tostring_v, __call = value_v }
--- local mt_l = { __index = { __lpdftype__ = "literal" }, __lpdftype = "literal", __tostring = tostring_l, __call = value_l }
-
local mt_x = { __index = { __lpdftype__ = "stream" }, __tostring = tostring_x, __call = value_x, __newindex = add_x }
local mt_d = { __index = { __lpdftype__ = "dictionary" }, __tostring = tostring_d, __call = value_d, __add = add_to_d }
local mt_a = { __index = { __lpdftype__ = "array" }, __tostring = tostring_a, __call = value_a, __add = add_to_a }
@@ -1259,6 +1243,17 @@ do
end
}
+ local setstate = nodes.nuts.pool.setstate
+
+ function nodeinjections.startalternate(str)
+ return setstate(f_actual_text(tosixteen(str)))
+ end
+
+ function nodeinjections.stopalternate()
+ return setstate("EMC")
+ end
+
+
end
-- interface
diff --git a/tex/context/base/mkxl/lpdf-lmt.lmt b/tex/context/base/mkxl/lpdf-lmt.lmt
index 44352994a..b57557aee 100644
--- a/tex/context/base/mkxl/lpdf-lmt.lmt
+++ b/tex/context/base/mkxl/lpdf-lmt.lmt
@@ -100,6 +100,10 @@ local report_objects = logs.reporter("backend","objects")
local trace_objects = false trackers.register("backend.objects", function(v) trace_objects = v end)
local trace_details = false trackers.register("backend.details", function(v) trace_details = v end)
+-- we collect them:
+
+local flushers = { }
+
-- used variables
local pdf_h, pdf_v
@@ -185,7 +189,7 @@ local tjfactor = 100 / 65536
lpdf.usedcharacters = usedcharacters
-local function updatefontstate(font)
+function flushers.updatefontstate(font)
fontcharacters = characters[font]
fontdescriptions = descriptions[font]
fontparameters = parameters[font]
@@ -400,8 +404,7 @@ local function pdf_goto_fontmode()
end
-- characters
-
-local flushcharacter do
+do
local round = math.round
@@ -413,52 +416,23 @@ local flushcharacter do
local hshift = false
local vshift = false
- -- local naturalwidths = setmetatableindex(function(t,font)
- -- local d = descriptions[font]
- -- local c = characters[font]
- -- local f = parameters[font].hfactor
- -- local v = setmetatableindex(function(t,char)
- -- local w
- -- local e = d and d[char]
- -- if e then
- -- w = e.width
- -- if w then
- -- w = w * f
- -- end
- -- end
- -- if not w then
- -- e = c[char]
- -- if e then
- -- w = e.width or 0
- -- end
- -- end
- -- if not w then
- -- w = 0
- -- end
- -- t[char] = w
- -- return w
- -- end)
- -- t[font] = v
- -- return v
- -- end)
-
local naturalwidths = setmetatableindex(function(t,font)
local d = descriptions[font]
local c = characters[font]
- local f = parameters[font].hfactor
+ local f = parameters[font].hfactor or parameters[font].factor
local v = setmetatableindex(function(t,char)
local w
- local e = c[char]
+ local e = d and d[char]
if e then
- w = e.width or 0
+ w = e.width
+ if w then
+ w = w * f
+ end
end
if not w then
- e = d and d[char]
+ e = c[char]
if e then
- w = e.width
- if w then
- w = w * f
- end
+ w = e.width or 0
end
end
if not w then
@@ -592,7 +566,7 @@ local flushcharacter do
-- luatex (a precursor to lmtx and also for comparison) but only in lmtx now so ...
-- time to move on I guess.
- flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width)
+ flushers.character = function(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width)
if sx ~= f_x_scale or sy ~= f_y_scale or need_tf or font ~= f_cur or f_pdf ~= f_pdf_cur or fs ~= fs_cur or mode == "page" then
pdf_goto_textmode()
setup_fontparameters(font,factor,f,e,sx,sy)
@@ -665,7 +639,7 @@ local flushcharacter do
end
- flushfontchar = function(font,char,data)
+ flushers.fontchar = function(font,char,data)
local dummy = usedfonts[font]
local index = data.index or char
if not pdfcharacters[index] then
@@ -690,14 +664,12 @@ local flushliteral do
local textliteral_code = literalvalues.text
local fontliteral_code = literalvalues.font
- local getdata = nuts.getdata
-
- flushliteral = function(current,pos_h,pos_v,mode,str)
- if mode then
- if not str then
- mode, str = originliteral_code, mode
- elseif mode == "mode" then
- mode = literalvalues[str]
+ flushliteral = function(current,pos_h,pos_v)
+ local p = nodeproperties[current]
+ if p then
+ local str = p.data
+ if str and str ~= "" then
+ local mode = p.mode
if mode == originliteral_code then
pdf_goto_pagemode()
pdf_set_pos(pos_h,pos_v)
@@ -707,49 +679,22 @@ local flushliteral do
pdf_goto_textmode()
elseif mode == fontliteral_code then
pdf_goto_fontmode()
- elseif mode == alwaysliteral_code then
+ elseif mode == alwaysliteral_code then -- aka direct
pdf_end_string_nl()
need_tm = true
elseif mode == rawliteral_code then
pdf_end_string_nl()
+ else
+ report("invalid literal mode %a when flushing %a",mode,str)
+ return
end
- return
- else
- mode = literalvalues[mode]
- end
- else
- local p = nodeproperties[current]
- if p then
- str = p.data
- mode = p.mode
- else
- str, mode = getdata(current)
- end
- end
- if str and str ~= "" then
- if mode == originliteral_code then
- pdf_goto_pagemode()
- pdf_set_pos(pos_h,pos_v)
- elseif mode == pageliteral_code then
- pdf_goto_pagemode()
- elseif mode == textliteral_code then
- pdf_goto_textmode()
- elseif mode == fontliteral_code then
- pdf_goto_fontmode()
- elseif mode == alwaysliteral_code then
- pdf_end_string_nl()
- need_tm = true
- elseif mode == rawliteral_code then
- pdf_end_string_nl()
- else
- report("check literal")
- pdf_goto_pagemode()
- pdf_set_pos(pos_h,pos_v)
+ b = b + 1 ; buffer[b] = str
end
- b = b + 1 ; buffer[b] = str
end
end
+ flushers.literal = flushliteral
+
function lpdf.print(mode,str)
-- This only works inside objects, don't change this to flush
-- in between. It's different from luatex but okay.
@@ -774,8 +719,8 @@ local flushliteral do
elseif mode == rawliteral_code then
pdf_end_string_nl()
else
- pdf_goto_pagemode()
- -- pdf_set_pos(pdf_h,pdf_v)
+ report("invalid literal mode %a when flushing %a",mode,str)
+ return
end
b = b + 1 ; buffer[b] = str
end
@@ -785,14 +730,14 @@ end
-- grouping & orientation
-local flushsave, flushrestore, flushsetmatrix do
+do
local matrices = { }
local positions = { }
local nofpositions = 0
local nofmatrices = 0
- flushsave = function(current,pos_h,pos_v)
+ local flushsave = function(current,pos_h,pos_v)
nofpositions = nofpositions + 1
positions[nofpositions] = { pos_h, pos_v, nofmatrices }
pdf_goto_pagemode()
@@ -800,7 +745,7 @@ local flushsave, flushrestore, flushsetmatrix do
b = b + 1 ; buffer[b] = "q"
end
- flushrestore = function(current,pos_h,pos_v)
+ local flushrestore = function(current,pos_h,pos_v)
if nofpositions < 1 then
return
end
@@ -822,7 +767,7 @@ local flushsave, flushrestore, flushsetmatrix do
local f_matrix_2 = formatters["%.6N 0 0 %.6N 0 0 cm"]
local f_matrix_4 = formatters["%.6N %.6N %.6N %.6N 0 0 cm"]
- flushsetmatrix = function(current,pos_h,pos_v)
+ local flushsetmatrix = function(current,pos_h,pos_v)
local p = nodeproperties[current]
if p then
local m = p.matrix
@@ -879,6 +824,10 @@ local flushsave, flushrestore, flushsetmatrix do
end
end
+ flushers.setmatrix = flushsetmatrix
+ flushers.save = flushsave
+ flushers.restore = flushrestore
+
function lpdf.hasmatrix()
return nofmatrices > 0
end
@@ -891,7 +840,7 @@ local flushsave, flushrestore, flushsetmatrix do
end
end
- pushorientation = function(orientation,pos_h,pos_v,pos_r)
+ flushers.pushorientation = function(orientation,pos_h,pos_v,pos_r)
pdf_goto_pagemode()
pdf_set_pos(pos_h,pos_v)
b = b + 1 ; buffer[b] = "q"
@@ -904,12 +853,76 @@ local flushsave, flushrestore, flushsetmatrix do
end
end
- poporientation = function(orientation,pos_h,pos_v,pos_r)
+ flushers.poporientation = function(orientation,pos_h,pos_v,pos_r)
pdf_goto_pagemode()
pdf_set_pos(pos_h,pos_v)
b = b + 1 ; buffer[b] = "Q"
end
+ --
+
+ flushers.startmatrix = function(current,pos_h,pos_v)
+ flushsave(current,pos_h,pos_v)
+ flushsetmatrix(current,pos_h,pos_v)
+ end
+
+ flushers.stopmatrix = function(current,pos_h,pos_v)
+ flushrestore(current,pos_h,pos_v)
+ end
+
+ flushers.startscaling = function(current,pos_h,pos_v)
+ flushsave(current,pos_h,pos_v)
+ flushsetmatrix(current,pos_h,pos_v)
+ end
+
+ flushers.stopscaling = function(current,pos_h,pos_v)
+ flushrestore(current,pos_h,pos_v)
+ end
+
+ flushers.startrotation = function(current,pos_h,pos_v)
+ flushsave(current,pos_h,pos_v)
+ flushsetmatrix(current,pos_h,pos_v)
+ end
+
+ flushers.stoprotation = function(current,pos_h,pos_v)
+ flushrestore(current,pos_h,pos_v)
+ end
+
+ flushers.startmirroring = function(current,pos_h,pos_v)
+ flushsave(current,pos_h,pos_v)
+ flushsetmatrix(current,pos_h,pos_v)
+ end
+
+ flushers.stopmirroring = function(current,pos_h,pos_v)
+ flushrestore(current,pos_h,pos_v)
+ end
+
+ flushers.startclipping = function(current,pos_h,pos_v)
+ flushsave(current,pos_h,pos_v)
+ flushliteral("origin",formatters["0 w %s W n"](properties[current].path))
+ end
+
+ flushers.stopclipping = function(current,pos_h,pos_v)
+ flushrestore(current,pos_h,pos_v)
+ end
+
+end
+
+do
+
+ local nodeproperties = nodes.properties.data
+
+ flushers.setstate = function(current,pos_h,pos_v)
+ local p = nodeproperties[current]
+ if p then
+ local d = p.data
+ if d and d ~= "" then
+ pdf_goto_pagemode()
+ b = b + 1 ; buffer[b] = d
+ end
+ end
+ end
+
end
-- rules
@@ -917,7 +930,7 @@ end
local flushedxforms = { } -- actually box resources but can also be direct
local localconverter = nil -- will be set
-local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
+local flushimage do
local rulecodes = nodes.rulecodes
local newrule = nodes.pool.rule
@@ -1041,7 +1054,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
end
end
--- updaters.register("backend.update.tex",function()
+ -- updaters.register("backend.update.tex",function()
updaters.register("backend.update.lpdf",function()
tex.saveboxresource = saveboxresource
tex.useboxresource = useboxresource
@@ -1115,7 +1128,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
local groups = 0
local group = nil
- flushgroup = function(content,bbox)
+ local flushgroup = function(content,bbox)
if not group then
group = pdfdictionary {
Type = pdfconstant("Group"),
@@ -1136,6 +1149,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
return f_gr(groups)
end
+ flushers.group = flushgroup
lpdf.flushgroup = flushgroup -- todo: access via driver in mlib-pps
-- end of experiment
@@ -1287,6 +1301,8 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
b = b + 1 ; buffer[b] = s_e
end
+ flushers.image = flushimage
+
-- For the moment we need this hack because the engine checks the 'image'
-- command in virtual fonts (so we use lua instead).
--
@@ -1294,7 +1310,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
-- never because the next are like the other engines and compensate for
-- small sizes which is needed for inaccurate viewers.
- flushrule = function(current,pos_h,pos_v,pos_r,size_h,size_v,subtype)
+ flushers.rule = function(current,pos_h,pos_v,pos_r,size_h,size_v,subtype)
if subtype == emptyrule_code then
return
@@ -1350,7 +1366,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
end
- flushsimplerule = function(pos_h,pos_v,pos_r,size_h,size_v)
+ flushers.simplerule = function(pos_h,pos_v,pos_r,size_h,size_v)
pdf_goto_pagemode()
b = b + 1 ; buffer[b] = s_b
@@ -1374,7 +1390,7 @@ local flushrule, flushsimplerule, flushspecialrule, flushimage, flushgroup do
b = b + 1 ; buffer[b] = s_e
end
- flushspecialrule = function(pos_h,pos_v,pos_r,width,height,depth,line,outline,baseline)
+ flushers.specialrule = function(pos_h,pos_v,pos_r,width,height,depth,line,outline,baseline)
pdf_goto_pagemode()
b = b + 1 ; buffer[b] = s_b
@@ -2953,24 +2969,7 @@ do
drivers.install {
name = "pdf",
- flushers = {
- character = flushcharacter,
- fontchar = flushfontchar,
- rule = flushrule,
- simplerule = flushsimplerule,
- specialrule = flushspecialrule,
- pushorientation = pushorientation,
- poporientation = poporientation,
- --
- literal = flushliteral,
- setmatrix = flushsetmatrix,
- save = flushsave,
- restore = flushrestore,
- image = flushimage,
- group = flushgroup,
- --
- updatefontstate = updatefontstate,
- },
+ flushers = flushers,
actions = {
prepare = prepare,
wrapup = wrapup,
diff --git a/tex/context/base/mkxl/lpdf-mis.lmt b/tex/context/base/mkxl/lpdf-mis.lmt
index 46accf9a4..afb149d8a 100644
--- a/tex/context/base/mkxl/lpdf-mis.lmt
+++ b/tex/context/base/mkxl/lpdf-mis.lmt
@@ -26,11 +26,14 @@ local nodeinjections = backends.pdf.nodeinjections
local codeinjections = backends.pdf.codeinjections
local registrations = backends.pdf.registrations
+local getpagedimensions = layouts.getpagedimensions
+local getcanvas = layouts.getcanvas
+
local nuts = nodes.nuts
local copy_node = nuts.copy
local nodepool = nuts.pool
-local pageliteral = nodepool.pageliteral
+local setstate = nodepool.setstate
local register = nodepool.register
local pdfdictionary = lpdf.dictionary
@@ -86,10 +89,10 @@ local v_righttoleft = variables.righttoleft
local v_title = variables.title
local v_nomenubar = variables.nomenubar
-local positive = register(pageliteral("/GSpositive gs"))
-local negative = register(pageliteral("/GSnegative gs"))
-local overprint = register(pageliteral("/GSoverprint gs"))
-local knockout = register(pageliteral("/GSknockout gs"))
+local positive = register(setstate("/GSpositive gs"))
+local negative = register(setstate("/GSnegative gs"))
+local overprint = register(setstate("/GSoverprint gs"))
+local knockout = register(setstate("/GSknockout gs"))
local omitextraboxes = false
@@ -410,46 +413,12 @@ local pagespecs = {
},
}
-local pagespec, topoffset, leftoffset, height, width, doublesided = "default", 0, 0, 0, 0, false
-local cropoffset, bleedoffset, trimoffset, artoffset = 0, 0, 0, 0
-local marked = false
-local copies = false
+local function documentspecification()
+ local canvas = getcanvas()
-local getpagedimensions getpagedimensions = function()
- getpagedimensions = backends.codeinjections.getpagedimensions
- return getpagedimensions()
-end
+ -- move this to layo-ini ?
-function codeinjections.setupcanvas(specification)
- local paperheight = specification.paperheight
- local paperwidth = specification.paperwidth
- local paperdouble = specification.doublesided
- --
- paperwidth, paperheight = codeinjections.setpagedimensions(paperwidth,paperheight)
- --
- pagespec = specification.mode or pagespec
- topoffset = specification.topoffset or 0
- leftoffset = specification.leftoffset or 0
- height = specification.height or paperheight
- width = specification.width or paperwidth
- marked = specification.print
- --
- copies = specification.copies
- if copies and copies < 2 then
- copies = false
- end
- --
- cropoffset = specification.cropoffset or 0
- trimoffset = cropoffset - (specification.trimoffset or 0)
- bleedoffset = trimoffset - (specification.bleedoffset or 0)
- artoffset = bleedoffset - (specification.artoffset or 0)
- --
- if paperdouble ~= nil then
- doublesided = paperdouble
- end
-end
-
-local function documentspecification()
+ local pagespec = canvas.pagespec
if not pagespec or pagespec == "" then
pagespec = v_default
end
@@ -460,7 +429,7 @@ local function documentspecification()
local spec = defaults or pagespecs[v_default]
-- successive keys can modify this
if spec.layout == "auto" then
- if doublesided then
+ if canvas.doublesided then
local s = pagespecs[v_doublesided] -- to be checked voor interfaces
for k, v in next, s do
spec[k] = v
@@ -478,6 +447,7 @@ local function documentspecification()
end
end
end
+
-- maybe interfaces.variables
local layout = spec.layout
local mode = spec.mode
@@ -495,6 +465,8 @@ local function documentspecification()
addtocatalog("PageMode",pdfconstant(mode))
end
local prints = nil
+ local marked = canvas.marked
+ local copies = canvas.copies
if marked then
local pages = structures.pages
local marked = pages.allmarked(marked)
@@ -534,10 +506,15 @@ local function boxvalue(n) -- we could share them
end
local function pagespecification()
- local paperwidth, paperheight = codeinjections.getpagedimensions()
+ local canvas = getcanvas()
+ local paperwidth = canvas.paperwidth
+ local paperheight = canvas.paperheight
+ local leftoffset = canvas.leftoffset
+ local topoffset = canvas.topoffset
+ --
local llx = leftoffset
- local lly = paperheight + topoffset - height
- local urx = width - leftoffset
+ local urx = canvas.width - leftoffset
+ local lly = paperheight + topoffset - canvas.height
local ury = paperheight - topoffset
-- boxes can be cached
local function extrabox(WhatBox,offset,always)
@@ -553,10 +530,10 @@ local function pagespecification()
if omitextraboxes then
-- only useful for testing / comparing
else
- extrabox("CropBox",cropoffset,true) -- mandate for rendering
- extrabox("TrimBox",trimoffset,true) -- mandate for pdf/x
- extrabox("BleedBox",bleedoffset) -- optional
- -- extrabox("ArtBox",artoffset) -- optional .. unclear what this is meant to do
+ extrabox("CropBox",canvas.cropoffset,true) -- mandate for rendering
+ extrabox("TrimBox",canvas.trimoffset,true) -- mandate for pdf/x
+ extrabox("BleedBox",canvas.bleedoffset) -- optional
+ -- extrabox("ArtBox",canvas.artoffset) -- optional .. unclear what this is meant to do
end
end
diff --git a/tex/context/base/mkxl/lpdf-ren.lmt b/tex/context/base/mkxl/lpdf-ren.lmt
index 8aa61e1dc..3794250d9 100644
--- a/tex/context/base/mkxl/lpdf-ren.lmt
+++ b/tex/context/base/mkxl/lpdf-ren.lmt
@@ -60,7 +60,7 @@ local copy_node = nuts.copy
local nodepool = nuts.pool
local register = nodepool.register
-local pageliteral = nodepool.pageliteral
+local setstate = nodepool.setstate
local pdf_ocg = pdfconstant("OCG")
local pdf_ocmd = pdfconstant("OCMD")
@@ -267,7 +267,7 @@ function nodeinjections.startlayer(name)
local c = cache[name]
if not c then
useviewerlayer(name)
- c = register(pageliteral(f_bdc(escapednames[name])))
+ c = register(setstate(f_bdc(escapednames[name])))
cache[name] = c
end
return copy_node(c)
@@ -275,7 +275,7 @@ end
function nodeinjections.stoplayer()
if not stop then
- stop = register(pageliteral(s_emc))
+ stop = register(setstate(s_emc))
end
return copy_node(stop)
end
@@ -292,7 +292,7 @@ function nodeinjections.startstackedlayer(s,t,first,last)
r[#r+1] = startlayer(values[t[i]])
end
r = concat(r," ")
- return pageliteral(r)
+ return setstate(r)
end
function nodeinjections.stopstackedlayer(s,t,first,last)
@@ -301,7 +301,7 @@ function nodeinjections.stopstackedlayer(s,t,first,last)
r[#r+1] = stoplayer()
end
r = concat(r," ")
- return pageliteral(r)
+ return setstate(r)
end
function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2)
@@ -313,7 +313,7 @@ function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2)
r[#r+1] = startlayer(values[t2[i]])
end
r = concat(r," ")
- return pageliteral(r)
+ return setstate(r)
end
-- transitions
diff --git a/tex/context/base/mkxl/lpdf-rul.lmt b/tex/context/base/mkxl/lpdf-rul.lmt
index ae2142a8e..efcc62073 100644
--- a/tex/context/base/mkxl/lpdf-rul.lmt
+++ b/tex/context/base/mkxl/lpdf-rul.lmt
@@ -33,13 +33,9 @@ local formatters = string.formatters
-- This is very pdf specific. Maybe move some to lpdf-rul.lua some day.
-local pdfprint
+local pdfprint ; pdfprint = function(...) pdfprint = lpdf.print return pdfprint(...) end
-pdfprint = function(...) pdfprint = lpdf.print return pdfprint(...) end
-
--- updaters.register("backend.update",function()
--- pdfprint = lpdf.print
--- end)
+-- updaters.register("backend.update",function() pdfprint = lpdf.print end)
do
diff --git a/tex/context/base/mkxl/lpdf-tag.lmt b/tex/context/base/mkxl/lpdf-tag.lmt
index 4ea92d951..44a84ea59 100644
--- a/tex/context/base/mkxl/lpdf-tag.lmt
+++ b/tex/context/base/mkxl/lpdf-tag.lmt
@@ -63,7 +63,7 @@ local a_image = attributes.private('image')
local nuts = nodes.nuts
local nodepool = nuts.pool
-local pageliteral = nodepool.pageliteral
+local setstate = nodepool.setstate
local register = nodepool.register
local getid = nuts.getid
@@ -369,7 +369,7 @@ local visualize = nil
function nodeinjections.addtags(head)
if not EMCliteral then
- EMCliteral = register(pageliteral("EMC"))
+ EMCliteral = register(setstate("EMC"))
end
local last = nil
@@ -516,9 +516,9 @@ end
end
end
if prev then
- literal = pageliteral(makecontent(prev,id,specification))
+ literal = setstate(makecontent(prev,id,specification))
elseif ignore then
- literal = pageliteral(makeignore(specification))
+ literal = setstate(makeignore(specification))
else
-- maybe also ignore or maybe better: comment or so
end
@@ -543,7 +543,7 @@ end
else
- local literal = pageliteral(makeignore(specification))
+ local literal = setstate(makeignore(specification))
inject(start,stop,list,literal)
@@ -667,9 +667,9 @@ end
-- end
--
-- if r > 0 then
--- local literal = pageliteral(concat(result,"\n"))
+-- local literal = setstate(concat(result,"\n"))
-- -- use insert instead:
--- local literal = pageliteral(result)
+-- local literal = setstate(result)
-- local prev = getprev(start)
-- if prev then
-- setlink(prev,literal)
@@ -691,7 +691,7 @@ end
-- for i=1,noftop do
-- result[i] = "EMC"
-- end
--- local literal = pageliteral(concat(result,"\n"))
+-- local literal = setstate(concat(result,"\n"))
-- -- use insert instead:
-- local next = getnext(last)
-- if next then
diff --git a/tex/context/base/mkxl/lpdf-vfc.lmt b/tex/context/base/mkxl/lpdf-vfc.lmt
deleted file mode 100644
index 6030bb028..000000000
--- a/tex/context/base/mkxl/lpdf-vfc.lmt
+++ /dev/null
@@ -1,42 +0,0 @@
-if not modules then modules = { } end modules ['lpdf-vfc'] = {
- 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 setmetatableindex = table.setmetatableindex
-
-local defaultline = 16384
-
-local vfspecials = backends.pdf.tables.vfspecials or utilities.storage.allocate { }
-backends.pdf.tables.vfspecials = vfspecials
-
-vfspecials.backgrounds = setmetatableindex(function(t,h)
- local v = setmetatableindex(function(t,d)
- local v = setmetatableindex(function(t,w)
- local v = { "frame", w, h, d, defaultline, true, true }
- t[w] = v
- return v
- end)
- t[d] = v
- return v
- end)
- t[h] = v
- return v
-end)
-
-vfspecials.outlines = setmetatableindex(function(t,h)
- local v = setmetatableindex(function(t,d)
- local v = setmetatableindex(function(t,w)
- local v = { "frame", w, h, d, defaultline, false, true }
- t[w] = v
- return v
- end)
- t[d] = v
- return v
- end)
- t[h] = v
- return v
-end)
diff --git a/tex/context/base/mkxl/math-act.lmt b/tex/context/base/mkxl/math-act.lmt
new file mode 100644
index 000000000..3076f2ac9
--- /dev/null
+++ b/tex/context/base/mkxl/math-act.lmt
@@ -0,0 +1,480 @@
+if not modules then modules = { } end modules ['math-act'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Here we tweak some font properties (if needed). The commented sections
+-- have been removed (no longer viable) but can be found in the .lua variant.
+
+local type, next = type, next
+local fastcopy, insert, remove = table.fastcopy, table.insert, table.remove
+local formatters = string.formatters
+
+local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end)
+local trace_collecting = false trackers.register("math.collecting", function(v) trace_collecting = v end)
+
+local report_math = logs.reporter("mathematics","initializing")
+
+local context = context
+local commands = commands
+local mathematics = mathematics
+local texsetdimen = tex.setdimen
+local abs = math.abs
+
+local helpers = fonts.helpers
+local upcommand = helpers.commands.up
+local rightcommand = helpers.commands.right
+local charcommand = helpers.commands.char
+local prependcommands = helpers.prependcommands
+
+local sequencers = utilities.sequencers
+local appendgroup = sequencers.appendgroup
+local appendaction = sequencers.appendaction
+
+local fontchars = fonts.hashes.characters
+local fontproperties = fonts.hashes.properties
+
+local mathfontparameteractions = sequencers.new {
+ name = "mathparameters",
+ arguments = "target,original",
+}
+
+appendgroup("mathparameters","before") -- user
+appendgroup("mathparameters","system") -- private
+appendgroup("mathparameters","after" ) -- user
+
+function fonts.constructors.assignmathparameters(original,target)
+ local runner = mathfontparameteractions.runner
+ if runner then
+ runner(original,target)
+ end
+end
+
+function mathematics.initializeparameters(target,original)
+ local mathparameters = original.mathparameters
+ if mathparameters and next(mathparameters) then
+ mathparameters = mathematics.dimensions(mathparameters)
+ if not mathparameters.SpaceBeforeScript then
+ mathparameters.SpaceBeforeScript = mathparameters.SpaceAfterScript
+ end
+ target.mathparameters = mathparameters
+ end
+end
+
+sequencers.appendaction("mathparameters","system","mathematics.initializeparameters")
+
+local how = {
+ -- RadicalKernBeforeDegree = "horizontal",
+ -- RadicalKernAfterDegree = "horizontal",
+ ScriptPercentScaleDown = "unscaled",
+ ScriptScriptPercentScaleDown = "unscaled",
+ RadicalDegreeBottomRaisePercent = "unscaled",
+ NoLimitSupFactor = "unscaled",
+ NoLimitSubFactor = "unscaled",
+}
+
+function mathematics.scaleparameters(target,original)
+ if not target.properties.math_is_scaled then
+ local mathparameters = target.mathparameters
+ if mathparameters and next(mathparameters) then
+ local parameters = target.parameters
+ local factor = parameters.factor
+ local hfactor = parameters.hfactor
+ local vfactor = parameters.vfactor
+ for name, value in next, mathparameters do
+ local h = how[name]
+ if h == "unscaled" then
+ -- kept
+ elseif h == "horizontal" then
+ value = value * hfactor
+ elseif h == "vertical"then
+ value = value * vfactor
+ else
+ value = value * factor
+ end
+ mathparameters[name] = value
+ end
+ end
+ target.properties.math_is_scaled = true
+ end
+end
+
+-- AccentBaseHeight vs FlattenedAccentBaseHeight
+
+function mathematics.checkaccentbaseheight(target,original)
+ local mathparameters = target.mathparameters
+ if mathparameters and mathparameters.AccentBaseHeight == 0 then
+ mathparameters.AccentBaseHeight = target.parameters.x_height -- needs checking
+ end
+end
+
+function mathematics.checkprivateparameters(target,original)
+ local mathparameters = target.mathparameters
+ if mathparameters then
+ local parameters = target.parameters
+ local properties = target.properties
+ if parameters then
+ local size = parameters.size
+ if size then
+ if not mathparameters.FractionDelimiterSize then
+ mathparameters.FractionDelimiterSize = 1.01 * size
+ end
+ if not mathparameters.FractionDelimiterDisplayStyleSize then
+ mathparameters.FractionDelimiterDisplayStyleSize = 2.40 * size
+ end
+ elseif properties then
+ report_math("invalid parameters in font %a",properties.fullname or "?")
+ else
+ report_math("invalid parameters in font")
+ end
+ elseif properties then
+ report_math("no parameters in font %a",properties.fullname or "?")
+ else
+ report_math("no parameters and properties in font")
+ end
+ end
+end
+
+function mathematics.overloadparameters(target,original)
+ local mathparameters = target.mathparameters
+ if mathparameters and next(mathparameters) then
+ local goodies = target.goodies
+ if goodies then
+ for i=1,#goodies do
+ local goodie = goodies[i]
+ local mathematics = goodie.mathematics
+ local parameters = mathematics and mathematics.parameters
+ if parameters then
+ if trace_defining then
+ report_math("overloading math parameters in %a @ %p",target.properties.fullname,target.parameters.size)
+ end
+ for name, value in next, parameters do
+ local tvalue = type(value)
+ if tvalue == "string" then
+ report_math("comment for math parameter %a: %s",name,value)
+ else
+ local oldvalue = mathparameters[name]
+ local newvalue = oldvalue
+ if oldvalue then
+ if tvalue == "number" then
+ newvalue = value
+ elseif tvalue == "function" then
+ newvalue = value(oldvalue,target,original)
+ elseif not tvalue then
+ newvalue = nil
+ end
+ if trace_defining and oldvalue ~= newvalue then
+ report_math("overloading math parameter %a: %S => %S",name,oldvalue,newvalue)
+ end
+ else
+ report_math("invalid math parameter %a",name)
+ end
+ mathparameters[name] = newvalue
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+local function applytweaks(when,target,original)
+ local goodies = original.goodies
+ if goodies then
+ for i=1,#goodies do
+ local goodie = goodies[i]
+ local mathematics = goodie.mathematics
+ local tweaks = mathematics and mathematics.tweaks
+ if type(tweaks) == "table" then
+ tweaks = tweaks[when]
+ if type(tweaks) == "table" then
+ if trace_defining then
+ report_math("tweaking math of %a @ %p (%s)",target.properties.fullname,target.parameters.size,when)
+ end
+ for i=1,#tweaks do
+ local tweak= tweaks[i]
+ local tvalue = type(tweak)
+ if tvalue == "function" then
+ tweak(target,original)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function mathematics.tweakbeforecopyingfont(target,original)
+ local mathparameters = target.mathparameters -- why not hasmath
+ if mathparameters then
+ applytweaks("beforecopying",target,original)
+ end
+end
+
+function mathematics.tweakaftercopyingfont(target,original)
+ local mathparameters = target.mathparameters -- why not hasmath
+ if mathparameters then
+ applytweaks("aftercopying",target,original)
+ end
+end
+
+sequencers.appendaction("mathparameters","system","mathematics.scaleparameters")
+sequencers.appendaction("mathparameters","system","mathematics.checkaccentbaseheight") -- should go in lfg instead
+sequencers.appendaction("mathparameters","system","mathematics.checkprivateparameters") -- after scaling !
+sequencers.appendaction("mathparameters","system","mathematics.overloadparameters")
+
+sequencers.appendaction("beforecopyingcharacters","system","mathematics.tweakbeforecopyingfont")
+sequencers.appendaction("aftercopyingcharacters", "system","mathematics.tweakaftercopyingfont")
+
+local virtualized = mathematics.virtualized
+
+-- no, it's a feature now (see good-mth):
+--
+-- sequencers.appendaction("aftercopyingcharacters", "system","mathematics.overloaddimensions")
+
+-- a couple of predefined tweaks:
+
+local tweaks = { }
+mathematics.tweaks = tweaks
+
+-- helpers
+
+local setmetatableindex = table.setmetatableindex
+
+local getfontoffamily = tex.getfontoffamily
+
+local fontcharacters = fonts.hashes.characters
+local extensibles = utilities.storage.allocate()
+fonts.hashes.extensibles = extensibles
+
+local chardata = characters.data
+local extensibles = mathematics.extensibles
+
+-- we use numbers at the tex end (otherwise we could stick to chars)
+
+local e_left = extensibles.left
+local e_right = extensibles.right
+local e_horizontal = extensibles.horizontal
+local e_mixed = extensibles.mixed
+local e_unknown = extensibles.unknown
+
+local unknown = { e_unknown, false, false }
+
+local function extensiblecode(font,unicode)
+ local characters = fontcharacters[font]
+ local character = characters[unicode]
+ if not character then
+ return unknown
+ end
+ local first = character.next
+ local code = unicode
+ local next = first
+ while next do
+ code = next
+ character = characters[next]
+ next = character.next
+ end
+ local char = chardata[unicode]
+ if not char then
+ return unknown
+ end
+ if character.horiz_variants then
+ if character.vert_variants then
+ return { e_mixed, code, character }
+ else
+ local m = char.mathextensible
+ local e = m and extensibles[m]
+ return e and { e, code, character } or unknown
+ end
+ elseif character.vert_variants then
+ local m = char.mathextensible
+ local e = m and extensibles[m]
+ return e and { e, code, character } or unknown
+ elseif first then
+ -- assume accent (they seldom stretch .. sizes)
+ local m = char.mathextensible or char.mathstretch
+ local e = m and extensibles[m]
+ return e and { e, code, character } or unknown
+ else
+ return unknown
+ end
+end
+
+setmetatableindex(extensibles,function(extensibles,font)
+ local codes = { }
+ setmetatableindex(codes, function(codes,unicode)
+ local status = extensiblecode(font,unicode)
+ codes[unicode] = status
+ return status
+ end)
+ extensibles[font] = codes
+ return codes
+end)
+
+local function extensiblecode(family,unicode)
+ return extensibles[getfontoffamily(family or 0)][unicode][1]
+end
+
+-- left : [head] ...
+-- right : ... [head]
+-- horizontal : [head] ... [head]
+--
+-- abs(right["start"] - right["end"]) | right.advance | characters[right.glyph].width
+
+local function horizontalcode(family,unicode)
+ local font = getfontoffamily(family or 0)
+ local data = extensibles[font][unicode]
+ local kind = data[1]
+ local loffset = 0
+ local roffset = 0
+ if kind == e_left then
+ local charlist = data[3].horiz_variants
+ if charlist then
+ local left = charlist[1]
+ loffset = abs((left["start"] or 0) - (left["end"] or 0))
+ end
+ elseif kind == e_right then
+ local charlist = data[3].horiz_variants
+ if charlist then
+ local right = charlist[#charlist]
+ roffset = abs((right["start"] or 0) - (right["end"] or 0))
+ end
+ elseif kind == e_horizontal then
+ local charlist = data[3].horiz_variants
+ if charlist then
+ local left = charlist[1]
+ local right = charlist[#charlist]
+ loffset = abs((left ["start"] or 0) - (left ["end"] or 0))
+ roffset = abs((right["start"] or 0) - (right["end"] or 0))
+ end
+ end
+ return kind, loffset, roffset
+end
+
+mathematics.extensiblecode = extensiblecode
+mathematics.horizontalcode = horizontalcode
+
+interfaces.implement {
+ name = "extensiblecode",
+ arguments = { "integer", "integer" },
+ actions = { extensiblecode, context }
+}
+
+interfaces.implement {
+ name = "horizontalcode",
+ arguments = { "integer", "integer" },
+ actions = function(family,unicode)
+ local kind, loffset, roffset = horizontalcode(family,unicode)
+ texsetdimen("scratchleftoffset", loffset)
+ texsetdimen("scratchrightoffset",roffset)
+ context(kind)
+ end
+}
+
+
+local stack = { }
+
+function mathematics.registerfallbackid(n,id,name)
+ if trace_collecting then
+ report_math("resolved fallback font %i, name %a, id %a, used %a",
+ n,name,id,fontproperties[id].fontname)
+ end
+ stack[#stack][n] = id
+end
+
+interfaces.implement { -- will be shared with text
+ name = "registerfontfallbackid",
+ arguments = { "integer", "integer", "string" },
+ actions = mathematics.registerfallbackid,
+}
+
+function mathematics.resolvefallbacks(target,specification,fallbacks)
+ local definitions = fonts.collections.definitions[fallbacks]
+ if definitions then
+ local size = specification.size -- target.size
+ local list = { }
+ insert(stack,list)
+ context.pushcatcodes("prt") -- context.unprotect()
+ for i=1,#definitions do
+ local definition = definitions[i]
+ local name = definition.font
+ local features = definition.features or ""
+ local size = size * (definition.rscale or 1)
+ context.font_fallbacks_register_math(i,name,features,size)
+ if trace_collecting then
+ report_math("registering fallback font %i, name %a, size %a, features %a",i,name,size,features)
+ end
+ end
+ context.popcatcodes()
+ end
+end
+
+function mathematics.finishfallbacks(target,specification,fallbacks)
+ local list = remove(stack)
+ if list and #list > 0 then
+ local definitions = fonts.collections.definitions[fallbacks]
+ if definitions and #definitions > 0 then
+ if trace_collecting then
+ report_math("adding fallback characters to font %a",specification.hash)
+ end
+ local definedfont = fonts.definers.internal
+ local copiedglyph = fonts.handlers.vf.math.copy_glyph
+ local fonts = target.fonts
+ local size = specification.size -- target.size
+ local characters = target.characters
+ if not fonts then
+ fonts = { }
+ target.fonts = fonts
+ end
+ if #fonts == 0 then
+ fonts[1] = { id = 0, size = size } -- self, will be resolved later
+ end
+ local done = { }
+ for i=1,#definitions do
+ local definition = definitions[i]
+ local name = definition.font
+ local start = definition.start
+ local stop = definition.stop
+ local gaps = definition.gaps
+ local check = definition.check
+ local force = definition.force
+ local rscale = definition.rscale or 1
+ local offset = definition.offset or start
+ local id = list[i]
+ if id then
+ local index = #fonts + 1
+ fonts[index] = { id = id, size = size }
+ local chars = fontchars[id]
+ local function remap(unic,unicode,gap)
+ if check and not chars[unicode] then
+ return
+ end
+ if force or (not done[unic] and not characters[unic]) then
+ if trace_collecting then
+ report_math("replacing math character %C by %C using vector %a and font id %a for %a%s%s",
+ unic,unicode,fallbacks,id,fontproperties[id].fontname,check and ", checked",gap and ", gap plugged")
+ end
+ characters[unic] = copiedglyph(target,characters,chars,unicode,index)
+ done[unic] = true
+ end
+ end
+ local step = offset - start
+ for unicode = start, stop do
+ remap(unicode + step,unicode,false)
+ end
+ if gaps then
+ for unic, unicode in next, gaps do
+ remap(unic,unicode,true)
+ remap(unicode,unicode,true)
+ end
+ end
+ end
+ end
+ elseif trace_collecting then
+ report_math("no fallback characters added to font %a",specification.hash)
+ end
+ end
+end
diff --git a/tex/context/base/mkxl/math-ali.mkxl b/tex/context/base/mkxl/math-ali.mkxl
index d90f3ab0f..72f857720 100644
--- a/tex/context/base/mkxl/math-ali.mkxl
+++ b/tex/context/base/mkxl/math-ali.mkxl
@@ -285,7 +285,7 @@
\math_number_right_of_eqalign
\global\settrue\c_math_eqalign_first
\crcr
- \dostoptagged} % finish row
+ \noalign{\dostoptagged}} % finish row
\permanent\protected\def\math_alignment_NC
{\relax
diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl
index 95501be65..01ecd63a2 100644
--- a/tex/context/base/mkxl/math-ini.mkxl
+++ b/tex/context/base/mkxl/math-ini.mkxl
@@ -66,7 +66,7 @@
\registerctxluafile{math-ini}{}
\registerctxluafile{math-dim}{}
-\registerctxluafile{math-act}{}
+\registerctxluafile{math-act}{autosuffix}
\registerctxluafile{math-ext}{}
\registerctxluafile{math-vfu}{autosuffix}
\registerctxluafile{math-ttv}{}
diff --git a/tex/context/base/mkxl/math-noa.lmt b/tex/context/base/mkxl/math-noa.lmt
index c884e6927..92edbc441 100644
--- a/tex/context/base/mkxl/math-noa.lmt
+++ b/tex/context/base/mkxl/math-noa.lmt
@@ -693,7 +693,8 @@ do
end
-- We can optimize this if we really think that math is a bottleneck which it never
- -- really is.
+ -- really is. Beware: the font is the text font in the family, so we only check the
+ -- text font here.
relocate[mathchar_code] = function(pointer)
local g = getattr(pointer,a_mathgreek) or 0
@@ -757,7 +758,13 @@ do
end
end
if not characters[char] then
+ local fam = getfam(pointer)
+ local fnt = getfontoffamily(fam,1)
setchar(pointer,errorchar(font,char))
+ if font ~= fnt then
+ errorchar(fnt,char)
+ errorchar(getfontoffamily(fam,2),char)
+ end
end
if trace_analyzing then
setnodecolor(pointer,"font:medi")
diff --git a/tex/context/base/mkxl/meta-imp-punk.mkxl b/tex/context/base/mkxl/meta-imp-punk.mkxl
new file mode 100644
index 000000000..050023642
--- /dev/null
+++ b/tex/context/base/mkxl/meta-imp-punk.mkxl
@@ -0,0 +1,272 @@
+%D \module
+%D [ file=meta-imp-punk,
+%D version=2020.01.16,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Punk,
+%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.
+
+% This file is a merge of the original punk files by Donald Knuth, who
+% added this comment:
+%
+% Font inspired by Gerard and Marjan Unger's lectures, Feb 1985
+%
+% The regular punk files are part of TeXLive and in metafont format. All
+% errors introduced are ours. We also changed the encoding to unicode. In
+% due time we might add a few more more characters. We still need to
+% improve some of the metrics which involves a bit of trial and error. The
+% font just covers basic latin shapes but in ConTeXt MkIV we add virtual
+% composed shapes. There is a module m-punk.tex that implements this. This
+% derivate is also used in mk.tex (mk.pdf) which is one of our tests for
+% LuaTeX. We published an article on it in the MAPS (NTG magazine).
+%
+% 2008, mkiv variant: Taco Hoekwater & Hans Hagen
+% 2020, lmtx variant: Hans Hagen (playground)
+
+\startMPcalculation{simplefun}
+
+ picture PunkShapes[][];
+
+ numeric PunkId ; PunkId := 0 ;
+ numeric PunkBase ; PunkBase := 0 ;
+ string PunkName ; PunkName := "punk" ;
+ numeric PunkUsed ; PunkUsed := 0 ;
+ numeric PunkSlant ; PunkSlant := 0 ;
+ numeric PunkWeight ; PunkWeight := 1 ;
+ numeric PunkSqueeze ; PunkSqueeze := 1 ;
+ numeric PunkExtend ; PunkExtend := 1 ;
+ numeric PunkVariants ; PunkVariants := 0 ;
+
+ numeric PunkRatio ; PunkRatio := 2/3 ;
+ numeric PunkScale ; PunkScale := 20 ; % when zero we use the knuth values
+ numeric PunkN ; PunkN := 0 ;
+
+ def beginpunkchar(expr c, n, hor, ver) =
+ begingroup ;
+ save uc, w, h, d, hdev, vdev ;
+ hdev := hor * dev ; % modify horizontal amounts of deviation
+ vdev := ver * dev ; % modify vertical amounts of deviation
+ uc := if string c : utfnum(c) else : c fi ;
+ h := if PunkScale > 0 : PunkN else : n fi / PunkSqueeze ;
+ w := n * PunkExtend ;
+ d := 0 ;
+ clearxy ;
+ clearit ;
+ enddef ;
+
+ def endpunkchar =
+ if PunkSlant <> 0 :
+ currentpicture := currentpicture slanted PunkSlant ;
+ fi ;
+ save llx, lly, uly ;
+ llx := xpart llcorner currentpicture ;
+ lly := ypart llcorner currentpicture ;
+ uly := ypart ulcorner currentpicture ;
+
+ currentpicture := currentpicture shifted (- llx + 1, 0);
+ w := bbwidth(currentpicture) + 2 ;
+ h := uly ;
+ d := if lly < 0 : - lly else : 0 fi ;
+
+ PunkUsed := if PunkBase > 0 : PunkBase else : uc fi;
+ PunkShapes[PunkId][PunkUsed] := currentpicture ;
+ lmt_registerglyph [
+ category = PunkName,
+ unicode = PunkUsed,
+ tounicode = uc,
+ width = w,
+ height = h,
+ depth = d,
+ code = "draw PunkShapes[" & decimal PunkId & "][" & decimal PunkUsed & "]",
+ ] ;
+ if PunkBase > 0 :
+ PunkBase := PunkBase + 1 ;
+ fi ;
+ endgroup ;
+ enddef ;
+
+ def initialize_punk_upper =
+ PunkN := PunkScale ;
+ dev := 1 ;
+ enddef ;
+
+ def initialize_punk_lower =
+ PunkN := PunkScale * PunkRatio ;
+ dev := .5 ;
+ enddef ;
+
+ def revert_punk_lower =
+ PunkN := PunkScale ;
+ dev := 1 ;
+ enddef ;
+
+ def beginpunkfont =
+
+ begingroup ;
+
+ save dev;
+
+ save u ; u := 1 ;
+
+ PunkBase := 0 ;
+
+ pen linepen ; linepen := pencircle scaled (PunkWeight * u) ;
+ pen dotpen ; dotpen := linepen scaled 2 slanted -PunkSlant ;
+
+ pickup linepen ;
+
+ save pp ; vardef pp expr z =
+ z + (hdev * normaldeviate, vdev * normaldeviate)
+ enddef ;
+
+ save pd ; def pd expr z =
+ drawdot z withpen dotpen ;
+ enddef ;
+
+ PunkId := PunkId + 1 ;
+
+ lmt_registerglyphs [
+ name = PunkName, % todo: when we do name = name we get ['"name"'] = name
+ units = 25,
+ width = 25,
+ height = 25,
+ depth = 0,
+ usecolor = true,
+ ] ;
+
+ def endchar = endpunkchar enddef ;
+
+ enddef ;
+
+ def endpunkfont =
+ endgroup;
+ enddef ;
+
+ % We started out with immediate:
+
+ % def MakePunkFont (expr name, filename, slant, weight, squeeze, extend) =
+ % begingroup ;
+ % save PunkName, PunkFileName, PunkSlant, PunkWeight, PunkSqueeze, PunkExend, PunkVariants ;
+ % string PunkName, PunkFileName ;
+ % PunkFileName := filename ;
+ % PunkName := name ;
+ % PunkSlant := slant ;
+ % PunkWeight := weight ;
+ % PunkSqueeze := squeeze ;
+ % PunkExtend := extend ;
+ % PunkVariants := 0 ;
+ % beginpunkfont ;
+ % loadfile(PunkFileName) ;
+ % endpunkfont ;
+ % endgroup ;
+ % enddef ;
+ %
+ % MakePunkFont("punk", "punkfont-characters.mp", 1, 0 ) ;
+ % MakePunkFont("punkbold", "punkfont-characters.mp", 2, 0 ) ;
+ % MakePunkFont("punkslanted", "punkfont-characters.mp", 1, 0.15) ;
+ % MakePunkFont("punkboldslanted", "punkfont-characters.mp", 2, 0.15) ;
+
+ % And ended up with delayed:
+
+ def punkpreroll =
+ begingroup ;
+ save PunkName, PunkFileName, PunkSlant, PunkWeight, PunkSqueeze, PunkExtend, PunkVariants ;
+ string PunkName, PunkFileName ;
+ PunkName := getparameterdefault "mpsfont" "name" "punk" ;
+ PunkFileName := getparameterdefault "mpsfont" "filename" "punkfont-characters.mp" ;
+ PunkSlant := scantokens(getparameterdefault "mpsfont" "slant" "0") ;
+ PunkWeight := scantokens(getparameterdefault "mpsfont" "weight" "1") ;
+ PunkSqueeze := scantokens(getparameterdefault "mpsfont" "squeeze" "1") ;
+ PunkExtend := scantokens(getparameterdefault "mpsfont" "extend" "1") ;
+ PunkVariants := scantokens(getparameterdefault "mpsfont" "variants" "0");
+ beginpunkfont ;
+ loadfile(PunkFileName) ;
+ if PunkVariants > 0 :
+ PunkBase := 57344 ; % 0xE000 ; 0xF0000 ;
+ for i=1 upto PunkVariants :
+ loadfile(PunkFileName) ;
+ endfor ;
+ fi ;
+ endpunkfont ;
+ endgroup ;
+ enddef ;
+
+\stopMPcalculation
+
+% Are these names okay? If so it can go into the core.
+
+\permanent\protected\def\enablerandomvariants{\setcharactercasing[randomvariant]}
+\permanent\protected\def\randomvariants {\groupedcommand\enablerandomvariants\donothing}
+\permanent\protected\def\startrandomvariants {\begingroup\enablerandomvariants}
+\permanent\protected\def\stoprandomvariants {\endgroup}
+
+\definefontfeature [punk] [metapost={category=punk,preroll=punkpreroll}]
+\definefontfeature [punkrandom] [metapost={category=punk,preroll=punkpreroll,variants=10}]
+\definefontfeature [punkbold] [metapost={category=punk,preroll=punkpreroll,weight=2}]
+\definefontfeature [punkslanted] [metapost={category=punk,preroll=punkpreroll,slant=.15}]
+\definefontfeature [punkboldslanted] [metapost={category=punk,preroll=punkpreroll,slant=.15,weight=2}]
+\definefontfeature [punkveryslanted] [metapost={category=punk,preroll=punkpreroll,slant=-.15}]
+\definefontfeature [punksqueezed] [metapost={category=punk,preroll=punkpreroll,squeeze=.5}]
+\definefontfeature [punkextended] [metapost={category=punk,preroll=punkpreroll,extend=1.3}]
+
+\continueifinputfile{meta-imp-punk.mkxl}
+
+% immediate:
+%
+% \definefontfeature [punk] [metapost=punk]
+% \definefontfeature [punkbold] [metapost=punkbold]
+% \definefontfeature [punkslanted] [metapost=punkslanted]
+% \definefontfeature [punkboldslanted] [metapost=punkboldslanted]
+
+% delayed:
+
+% name=punk
+% filename=punkfont-characters.mp
+
+\setupbodyfont[dejavu]
+
+\definefont[PunkA][Serif*punk]
+\definefont[PunkB][Serif*punkbold]
+\definefont[PunkC][Serif*punkslanted]
+\definefont[PunkD][Serif*punkboldslanted]
+\definefont[PunkE][Serif*punkveryslanted]
+\definefont[PunkF][Serif*punkrandom]
+\definefont[PunkG][Serif*punksqueezed]
+\definefont[PunkH][Serif*punkextended]
+
+\starttext
+
+\startTEXpage[offset=10pt,width=30cm]
+ % \showglyphs
+ {\darkcyan \PunkA \samplefile{tufte} \par}
+ {\darkmagenta \PunkB \samplefile{tufte} \par}
+ {\darkred \PunkC \samplefile{tufte} \par}
+ {\darkgreen \PunkD \samplefile{tufte} \par}
+ {\darkblue \PunkE \samplefile{tufte} \par}
+ {\darkyellow \PunkF \enablerandomvariants \samplefile{tufte} \par}
+ {\darkgray \PunkG \samplefile{tufte} \par}
+ {\darkorange \PunkH \samplefile{tufte} \par}
+\stopTEXpage
+
+\startTEXpage[offset=10pt,width=2cm]
+ \PunkF \enablerandomvariants
+ \dostepwiserecurse{1}{2000}{1}{\glyphscale#1\relax f }
+\stopTEXpage
+
+% \setupbodyfont[dejavu]
+
+\setupbodyfont[punk] %one first needs to load a bodyfont !
+
+\startTEXpage[offset=10pt,width=20cm]
+ {\darkcyan \tf \samplefile{zapf} \par}
+ {\darkmagenta \bf \samplefile{zapf} \par}
+ {\darkred \sl \samplefile{zapf} \par}
+ {\darkgreen \bs \samplefile{zapf} \par}
+\stopTEXpage
+
+\stoptext
diff --git a/tex/context/base/mkxl/mlib-mpf.lmt b/tex/context/base/mkxl/mlib-mpf.lmt
index 6bd31376c..d66491a16 100644
--- a/tex/context/base/mkxl/mlib-mpf.lmt
+++ b/tex/context/base/mkxl/mlib-mpf.lmt
@@ -86,12 +86,10 @@ do
else
runscripts[nofscripts] = name
end
--- print("set",name,nofscripts,f)
return nofscripts
end
function metapost.scriptindex(name)
--- print("get",name,runnames[name] or 0)
return runnames[name] or 0
end
@@ -945,9 +943,14 @@ do
registerscript("setcount", function() setcount(scanstring(),scannumeric()) end)
registerscript("settoks", function() settoks (scanstring(),scanstring()) end)
+ local utfnum = utf.byte
local utflen = utf.len
local utfsub = utf.sub
+ registerscript("utfnum", function()
+ injectnumeric(utfnum(scanstring()))
+ end)
+
registerscript("utflen", function()
injectnumeric(utflen(scanstring()))
end)
diff --git a/tex/context/base/mkxl/node-ext.lmt b/tex/context/base/mkxl/node-ext.lmt
new file mode 100644
index 000000000..2f909cd3d
--- /dev/null
+++ b/tex/context/base/mkxl/node-ext.lmt
@@ -0,0 +1,650 @@
+if not modules then modules = { } end modules ['back-out'] = {
+ version = 1.001,
+ comment = "companion to back-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, unpack, rawset = type, unpack, type
+local loadstring = loadstring
+local sind, cosd, abs = math.sind, math.cosd, math.abs
+local insert, remove = table.insert, table.remove
+
+local context = context
+local implement = interfaces.implement
+
+local allocate = utilities.storage.allocate
+
+local formatters = string.formatters
+
+local get = token.get_index -- getters
+local scanners = tokens.scanners
+local scaninteger = scanners.integer
+local scanstring = scanners.string
+local scankeyword = scanners.keyword
+local scantokenlist = scanners.tokenlist
+local scannumber = scanners.number
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local copynut = nuts.copy
+local nutpool = nuts.pool
+local nodepool = nodes.pool
+
+local nodeproperties = nodes.properties.data
+
+local register = nutpool.register
+local newnut = nuts.new
+local tonode = nodes.tonode
+
+-- Whatsits are a generic node type with very few fields. We use them to implement
+-- whatever we like. Some are good old tex whatsits but many are specific to the
+-- macro package. They are part of the backend.
+
+backends = backends or { }
+local backends = backends
+
+local whatsit_code = nodes.nodecodes.whatsit
+local whatsitcodes = allocate { }
+nodes.whatsitcodes = whatsitcodes
+local lastwhatsit = 0
+
+nodes.subtypes.whatsit = whatsitcodes
+
+local function registerwhatsit(name)
+ lastwhatsit = lastwhatsit + 1
+ whatsitcodes[lastwhatsit] = name
+ whatsitcodes[name] = lastwhatsit
+ return lastwhatsit
+end
+
+local function registerwhatsitnode(name)
+ return register(newnut(whatsit_code,registerwhatsit(name)))
+end
+
+-- We only have a subset of literals. In fact, we try to avoid literals.
+
+do
+
+ local literalvalues = allocate { }
+ nodes.literalvalues = literalvalues
+ local lastliteral = 0
+ local literalnode = registerwhatsitnode("literal")
+
+ local function registerliteral(name,alias)
+ lastliteral = lastliteral + 1
+ literalvalues[lastliteral] = name
+ literalvalues[name] = lastliteral
+ if alias then
+ literalvalues[alias] = lastliteral
+ end
+ return lastliteral
+ end
+
+ local originliteral_code = registerliteral("origin")
+ local pageliteral_code = registerliteral("page")
+ local directliteral_code = registerliteral("always","direct")
+ local rawliteral_code = registerliteral("raw")
+ local textliteral_code = registerliteral("text") -- not to be used
+ local fontliteral_code = registerliteral("font") -- not to be used
+
+ function nutpool.originliteral(str) local t = copynut(literalnode) nodeproperties[t] = { data = str, mode = originliteral_code } return t end
+ function nutpool.pageliteral (str) local t = copynut(literalnode) nodeproperties[t] = { data = str, mode = pageliteral_code } return t end
+ function nutpool.directliteral(str) local t = copynut(literalnode) nodeproperties[t] = { data = str, mode = directliteral_code } return t end
+ function nutpool.rawliteral (str) local t = copynut(literalnode) nodeproperties[t] = { data = str, mode = rawliteral_code } return t end
+
+ local pdfliterals = {
+ [originliteral_code] = originliteral_code, [literalvalues[originliteral_code]] = originliteral_code,
+ [pageliteral_code] = pageliteral_code, [literalvalues[pageliteral_code]] = pageliteral_code,
+ [directliteral_code] = directliteral_code, [literalvalues[directliteral_code]] = directliteral_code,
+ [rawliteral_code] = rawliteral_code, [literalvalues[rawliteral_code]] = rawliteral_code,
+ }
+
+ function nutpool.literal(mode,str)
+ local t = copynut(literalnode)
+ if str then
+ nodeproperties[t] = { data = str, mode = pdfliterals[mode] or pageliteral_code }
+ else
+ nodeproperties[t] = { data = mode, mode = pageliteral_code }
+ end
+ return t
+ end
+
+end
+
+-- The latelua node is just another whatsit and we handle the \LUA\ code with
+-- other \LUA\ code, contrary to \LUATEX\ where it's a native node.
+
+do
+
+ local getdata = nuts.getdata
+ local serialize = token.serialize
+
+ local lateluanode = registerwhatsitnode("latelua")
+ local noflatelua = 0
+
+ function nutpool.latelua(code)
+ local n = copynut(lateluanode)
+ nodeproperties[n] = { data = code }
+ return n
+ end
+
+ function backends.latelua(current,pos_h,pos_v) -- todo: pass pos_h and pos_v (more efficient in lmtx)
+ local p = nodeproperties[current]
+ if p then
+ data = p.data
+ else
+ data = getdata(current)
+ end
+ noflatelua = noflatelua + 1
+ local kind = type(data)
+ if kind == "table" then
+ data.action(data.specification or data)
+ elseif kind == "function" then
+ data()
+ else
+ if kind ~= "string" then
+ data = serialize(data)
+ end
+ if #data ~= "" then
+ local code = loadstring(data)
+ if code then
+ code()
+ end
+ end
+ end
+ end
+
+ function backends.getcallbackstate()
+ return { count = noflatelua }
+ end
+
+ implement {
+ name = "latelua",
+ public = true,
+ protected = true,
+ actions = function()
+ local node = copynut(lateluanode)
+ local name = "latelua"
+ if scankeyword("name") then
+ name = scanstring()
+ end
+ local data = scantokenlist()
+ nodeproperties[node] = { name = name, data = data }
+ return context(tonode(node))
+ end,
+ }
+
+end
+
+-- This can be anything. Dealing with these nodes is done via properties, as with
+-- the other whatsits.
+
+do
+
+ local usernode = registerwhatsitnode("userdefined")
+
+ local userids = allocate()
+ local lastid = 0
+
+ setmetatable(userids, {
+ __index = function(t,k)
+ if type(k) == "string" then
+ lastid = lastid + 1
+ rawset(userids,lastid,k)
+ rawset(userids,k,lastid)
+ return lastid
+ else
+ rawset(userids,k,k)
+ return k
+ end
+ end,
+ __call = function(t,k)
+ return t[k]
+ end
+ } )
+
+ function nutpool.userdefined(id,data)
+ local n = copynut(usernode)
+ nodeproperties[n] = { id = id, data = data }
+ return n
+ end
+
+ nutpool .usernode = nutpool.userdefined
+ nutpool .userids = userids
+ nodepool.userids = userids
+
+end
+
+-- This one is only used by generic packages.
+
+do
+
+ local saveposnode = registerwhatsitnode("savepos")
+
+ function nutpool.savepos()
+ return copynut(saveposnode)
+ end
+
+end
+
+do
+
+ local savenode = registerwhatsitnode("save")
+ local restorenode = registerwhatsitnode("restore")
+ local setmatrixnode = registerwhatsitnode("setmatrix")
+
+ local stack = { }
+ local restore = true -- false
+
+ -- these are old school nodes
+
+ function nutpool.save()
+ return copynut(savenode)
+ end
+
+ function nutpool.restore()
+ return copynut(restorenode)
+ end
+
+ function nutpool.setmatrix(rx,sx,sy,ry,tx,ty)
+ local t = copynut(setmatrixnode)
+ nodeproperties[t] = { matrix = { rx, sx, sy, ry, tx, ty } }
+ return t
+ end
+
+ -- common
+
+ local function stopcommon(n)
+ local top = remove(stack)
+ if top == false then
+ return -- not wrapped
+ elseif top == true then
+ return copynut(n)
+ elseif top then
+ local t = copynut(n)
+ nodeproperties[t] = { matrix = { unpack(top) } }
+ return t
+ else
+ return -- nesting error
+ end
+ end
+
+ -- matrix
+
+ local startmatrixnode = registerwhatsitnode("startmatrix")
+ local stopmatrixnode = registerwhatsitnode("stopmatrix")
+
+ local function startmatrix(rx, sx, sy, ry)
+ if rx == 1 and sx == 0 and sy == 0 and ry == 1 then
+ insert(stack,false)
+ else
+ local t = copynut(startmatrixnode)
+ nodeproperties[t] = { matrix = { rx, sx, sy, ry } }
+ insert(stack,store and { -rx, -sx, -sy, -ry } or true)
+ return t
+ end
+ end
+
+ local function stopmatrix()
+ return stopcommon(stopmatrixnode)
+ end
+
+ implement {
+ name = "startmatrix",
+ actions = function()
+ local rx, sx, sy, ry = 1, 0, 0, 1
+ while true do
+ if scankeyword("rx") then rx = scannumber()
+ elseif scankeyword("ry") then ry = scannumber()
+ elseif scankeyword("sx") then sx = scannumber()
+ elseif scankeyword("sy") then sy = scannumber()
+ else break end
+ end
+ local t = startmatrix(rx,sx,sy,ry)
+ if t then
+ context(tonode(t))
+ end
+ end,
+ }
+
+ implement {
+ name = "stopmatrix",
+ actions = function()
+ local t = stopmatrix(n)
+ if t then
+ context(tonode(t))
+ end
+ end,
+ }
+
+ -- scale
+
+ local startscalingnode = registerwhatsitnode("startscaling")
+ local stopscalingnode = registerwhatsitnode("stopscaling")
+
+ local function startscaling(rx, ry) -- at the tex end we use sx and sy instead of rx and ry
+ if rx == 1 and ry == 1 then
+ insert(stack,false)
+ else
+ if rx == 0 then
+ rx = 0.0001
+ end
+ if ry == 0 then
+ ry = 0.0001
+ end
+ local t = copynut(startscalingnode)
+ nodeproperties[t] = { matrix = { rx, 0, 0, ry } }
+ insert(stack,restore and { 1/rx, 0, 0, 1/ry } or true)
+ return t
+ end
+ end
+
+ local function stopscaling() -- at the tex end we use sx and sy instead of rx and ry
+ return stopcommon(stopscalingnode)
+ end
+
+ implement {
+ name = "startscaling",
+ actions = function()
+ local rx, ry = 1, 1
+ while true do
+ if scankeyword("rx") then
+ rx = scannumber()
+ elseif scankeyword("ry") then
+ ry = scannumber()
+ else
+ break
+ end
+ end
+ local t = startscaling(rx,ry)
+ if t then
+ context(tonode(t))
+ end
+ end,
+ }
+
+ implement {
+ name = "stopscaling",
+ actions = function()
+ local t = stopscaling(n)
+ if t then
+ context(tonode(t))
+ end
+ end,
+ }
+
+ -- rotate
+
+ local startrotationnode = registerwhatsitnode("startrotation")
+ local stoprotationnode = registerwhatsitnode("stoprotation")
+
+ local function startrotation(a)
+ if a == 0 then
+ insert(stack,false)
+ else
+ local s, c = sind(a), cosd(a)
+ if abs(s) < 0.000001 then
+ s = 0 -- otherwise funny -0.00000
+ end
+ if abs(c) < 0.000001 then
+ c = 0 -- otherwise funny -0.00000
+ end
+ local t = copynut(startrotationnode)
+ nodeproperties[t] = { matrix = { c, s, -s, c } }
+ insert(stack,restore and { c, -s, s, c } or true)
+ return t
+ end
+ end
+
+ local function stoprotation()
+ return stopcommon(stoprotationnode)
+ end
+
+ nutpool.startrotation = startrotation
+
+ implement {
+ name = "startrotation",
+ actions = function()
+ local n = scannumber()
+ local t = startrotation(n)
+ if t then
+ context(tonode(t))
+ end
+ end,
+ }
+
+ implement {
+ name = "stoprotation",
+ actions = function()
+ local t = stoprotation()
+ if t then
+ context(tonode(t))
+ end
+ end,
+ }
+
+ -- mirror
+
+ local startmirroringnode = registerwhatsitnode("startmirroring")
+ local stopmirroringnode = registerwhatsitnode("stopmirroring")
+
+ local function startmirroring()
+ local t = copynut(startmirroringnode)
+ nodeproperties[t] = { matrix = { -1, 0, 0, 1 } }
+ return t
+ end
+
+ local function stopmirroring()
+ local t = copynut(stopmirroringnode)
+ nodeproperties[t] = { matrix = { -1, 0, 0, 1 } }
+ return t
+ end
+
+ implement {
+ name = "startmirroring",
+ actions = function()
+ context(tonode(startmirroring()))
+ end,
+ }
+
+ implement {
+ name = "stopmirroring",
+ actions = function()
+ context(tonode(stopmirroring()))
+ end,
+ }
+
+ -- clip
+
+ local startclippingnode = registerwhatsitnode("startclipping")
+ local stopclippingnode = registerwhatsitnode("stopclipping")
+
+ local function startclipping(path)
+ local t = copynut(startclippingnode)
+ nodeproperties[t] = { path = path }
+ return t
+ end
+
+ local function stopclipping()
+ return copynut(stopclippingnode)
+ end
+
+ implement {
+ name = "startclipping",
+ actions = function()
+ context(tonode(startclipping(scanstring())))
+ end
+ }
+
+ implement {
+ name = "stopclipping",
+ actions = function()
+ context(tonode(stopclipping()))
+ end,
+ }
+
+end
+
+-- The (delayed and immediate) write operations are emulated in \LUA\ and presented
+-- as primitives at the \TEX\ end.
+
+do
+
+ local logwriter = logs.writer
+ local openfile = io.open
+ local flushio = io.flush
+ local serialize = token.serialize
+
+ local opennode = registerwhatsitnode("open")
+ local writenode = registerwhatsitnode("write")
+ local closenode = registerwhatsitnode("close")
+ local channels = { }
+ local immediate_code = tex.flagcodes.immediate
+
+ function backends.openout(n)
+ local p = nodeproperties[n]
+ if p then
+ local handle = openfile(p.filename,"wb") or false
+ if handle then
+ channels[p.channel] = handle
+ else
+ -- error
+ end
+ end
+ end
+
+ function backends.writeout(n)
+ local p = nodeproperties[n]
+ if p then
+ local handle = channels[p.channel]
+ local content = serialize(p.data)
+ if handle then
+ handle:write(content,"\n")
+ else
+ logwriter(content,"\n")
+ end
+ end
+ end
+
+ function backends.closeout(n)
+ local p = nodeproperties[n]
+ if p then
+ local channel = p.channel
+ local handle = channels[channel]
+ if handle then
+ handle:close()
+ channels[channel] = false
+ flushio()
+ else
+ -- error
+ end
+ end
+ end
+
+ local function immediately(prefix)
+ return prefix and (prefix & immediate_code) ~= 0
+ end
+
+ implement {
+ name = "openout",
+ public = true,
+ usage = "value",
+ actions = function(prefix)
+ local channel = scaninteger()
+ scankeyword("=") -- hack
+ local filename = scanstring()
+ if not immediately(prefix) then
+ local n = copynut(opennode)
+ nodeproperties[n] = { channel = channel, filename = filename } -- action = "open"
+ return context(tonode(n))
+ elseif not channels[channel] then
+ local handle = openfile(filename,"wb") or false
+ if handle then
+ channels[channel] = handle
+ else
+ -- error
+ end
+ end
+ end,
+ }
+
+ implement {
+ name = "write",
+ public = true,
+ usage = "value",
+ actions = function(prefix)
+ local channel = scaninteger()
+ if not immediately(prefix) then
+ local t = scantokenlist()
+ local n = copynut(writenode)
+ nodeproperties[n] = { channel = channel, data = t } -- action = "write"
+ return context(tonode(n))
+ else
+ local content = scanstring()
+ local handle = channels[channel]
+ if handle then
+ handle:write(content,"\n")
+ else
+ logwriter(content,"\n")
+ end
+ end
+ end,
+ }
+
+ implement {
+ name = "closeout",
+ public = true,
+ usage = "value",
+ actions = function(prefix)
+ local channel = scaninteger()
+ if not immediately(prefix) then
+ local n = copynut(closenode)
+ nodeproperties[n] = { channel = channel } -- action = "close"
+ return context(tonode(n))
+ else
+ local handle = channels[channel]
+ if handle then
+ handle:close()
+ channels[channel] = false
+ flushio()
+ else
+ -- error
+ end
+ end
+ end,
+ }
+
+ -- why ...
+
+ local open_command = get(token.create("openout"))
+ local write_command = get(token.create("write"))
+ local close_command = get(token.create("closeout"))
+
+end
+
+-- states: these get injected independent of grouping
+
+do
+
+ local setstatenode = registerwhatsitnode("setstate")
+
+ function nutpool.setstate(data)
+ local n = copynut(setstatenode)
+ nodeproperties[n] = { data = data }
+ return n
+ end
+
+end
+
+-- We don't support specials so we make them dummies.
+
+do
+ implement {
+ name = "special",
+ actions = scanstring,
+ public = true,
+ protected = true,
+ }
+end
diff --git a/tex/context/base/mkxl/node-fin.lmt b/tex/context/base/mkxl/node-fin.lmt
index dab90863a..a9180ddb2 100644
--- a/tex/context/base/mkxl/node-fin.lmt
+++ b/tex/context/base/mkxl/node-fin.lmt
@@ -36,6 +36,7 @@ local setlist = nuts.setlist
local setleader = nuts.setleader
local copy_node = nuts.copy
+local find_tail = nuts.tail
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
@@ -165,13 +166,15 @@ function states.finalize(namespace,attribute,head) -- is this one ok?
if id == hlist_code or id == vlist_code then
local content = getlist(head)
if content then
- local list = insert_node_before(content,content,copy_node(nsnone)) -- two return values
+-- local list = insert_node_before(content,content,copy_node(nsnone)) -- two return values
+ local list = insert_node_after(content,find_tail(content),copy_node(nsnone)) -- two return values
if list ~= content then
setlist(head,list)
end
end
else
- head = insert_node_before(head,head,copy_node(nsnone))
+-- head = insert_node_before(head,head,copy_node(nsnone))
+ head = insert_node_after(find_tail(head),head,copy_node(nsnone))
end
return head, true
end
@@ -295,6 +298,75 @@ states.process = function(namespace,attribute,head,default)
return process(attribute,head,default)
end
+local function simple(attribute,head)
+ local check = false
+ local leader = nil
+ for stack, id, subtype, content in nextcontent, head do
+ if id == glyph_code or id == disc_code then
+ check = true
+ elseif id == glue_code then
+ check = true
+ leader = content
+ elseif id == hlist_code or id == vlist_code then
+ if getorientation(stack) then
+ local outer = getattr(stack,attribute)
+ if outer then
+ if current ~= outer then
+ if current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ end
+ head = insert_node_before(head,stack,copy_node(nsdata[c]))
+ current = outer
+ end
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ current = 0
+ end
+ end
+ local list = simple(attribute,content)
+ if content ~= list then
+ setlist(stack,list)
+ end
+ elseif id == rule_code then
+ check = has_dimensions(stack)
+ end
+ if check then
+ local c = getattr(stack,attribute)
+ if c then
+ if current ~= c then
+ if current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ end
+ head = insert_node_before(head,stack,copy_node(nsdata[c]))
+ current = c
+ end
+ if leader then
+ local savedcurrent = current
+ local ci = getid(leader)
+ if ci == hlist_code or ci == vlist_code then
+ current = 0
+ end
+ local list = simple(attribute,leader)
+ if leader ~= list then
+ setleader(stack,list)
+ end
+ current = savedcurrent
+ leader = false
+ end
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ current = 0
+ end
+ check = false
+ end
+ end
+ return head
+end
+
+states.simple = function(namespace,attribute,head,default)
+ return simple(attribute,head,default)
+end
+
-- we can force a selector, e.g. document wide color spaces, saves a little
-- watch out, we need to check both the selector state (like colorspace) and
-- the main state (like color), otherwise we get into troubles when a selector
diff --git a/tex/context/base/mkxl/node-ini.lmt b/tex/context/base/mkxl/node-ini.lmt
index 0fba0a4d9..4ba4b4000 100644
--- a/tex/context/base/mkxl/node-ini.lmt
+++ b/tex/context/base/mkxl/node-ini.lmt
@@ -65,31 +65,6 @@ local function simplified(t)
return r
end
-local nodecodes = simplified(node.types())
-
-local whatcodes = allocate {
- literal = 0x1, [0x1] = "literal",
- latelua = 0x2, [0x2] = "latelua",
- userdefined = 0x3, [0x3] = "userdefined",
- savepos = 0x4, [0x4] = "savepos",
- save = 0x5, [0x5] = "save",
- restore = 0x6, [0x6] = "restore",
- setmatrix = 0x7, [0x7] = "setmatrix",
- open = 0x8, [0x8] = "open",
- close = 0x9, [0x9] = "close",
- write = 0xA, [0xA] = "write",
-}
-
-local usercodes = allocate {
- [ 97] = "attribute", -- a
- [100] = "number", -- d
- [102] = "float", -- f
- [108] = "lua", -- l
- [110] = "node", -- n
- [115] = "string", -- s
- [116] = "token" -- t
-}
-
local noadoptions = allocate {
set = 0x08,
unused_1 = 0x00 + 0x08,
@@ -102,15 +77,7 @@ local noadoptions = allocate {
right = 0x14 + 0x08,
}
-local literalvalues = allocate {
- [0] = "origin",
- [1] = "page",
- [2] = "always",
- [3] = "raw",
- [4] = "text",
- [5] = "font",
- [6] = "special",
-}
+local nodecodes = simplified(node.types())
gluecodes = allocate(swapped(gluecodes,gluecodes))
dircodes = allocate(swapped(dircodes,dircodes))
@@ -118,7 +85,6 @@ boundarycodes = allocate(swapped(boundarycodes,boundarycodes))
noadcodes = allocate(swapped(noadcodes,noadcodes))
radicalcodes = allocate(swapped(radicalcodes,radicalcodes))
nodecodes = allocate(swapped(nodecodes,nodecodes))
-whatcodes = allocate(swapped(whatcodes,whatcodes))
listcodes = allocate(swapped(listcodes,listcodes))
glyphcodes = allocate(swapped(glyphcodes,glyphcodes))
kerncodes = allocate(swapped(kerncodes,kerncodes))
@@ -129,18 +95,15 @@ accentcodes = allocate(swapped(accentcodes,accentcodes))
fencecodes = allocate(swapped(fencecodes,fencecodes))
parcodes = allocate(swapped(parcodes,parcodes))
rulecodes = allocate(swapped(rulecodes,rulecodes))
-usercodes = allocate(swapped(usercodes,usercodes))
noadoptions = allocate(swapped(noadoptions,noadoptions))
dirvalues = allocate(swapped(dirvalues,dirvalues))
-literalvalues = allocate(swapped(literalvalues,literalvalues))
fillvalues = allocate(swapped(fillvalues,fillvalues))
nodes.gluecodes = gluecodes
nodes.dircodes = dircodes
nodes.boundarycodes = boundarycodes
nodes.noadcodes = noadcodes
-nodes.whatcodes = whatcodes
nodes.listcodes = listcodes
nodes.glyphcodes = glyphcodes
nodes.kerncodes = kerncodes
@@ -152,13 +115,11 @@ nodes.radicalcodes = radicalcodes
nodes.fencecodes = fencecodes
nodes.parcodes = parcodes
nodes.rulecodes = rulecodes
-nodes.usercodes = usercodes
nodes.noadoptions = noadoptions
nodes.fillvalues = fillvalues
nodes.fillcodes = fillvalues -- for now
nodes.dirvalues = dirvalues
-nodes.literalvalues = literalvalues
nodes.nodecodes = nodecodes
@@ -167,7 +128,6 @@ local subtypes = allocate {
dir = dircodes,
boundary = boundarycodes,
noad = noadcodes,
- whatsit = whatcodes,
glyph = glyphcodes,
kern = kerncodes,
penalty = penaltycodes,
@@ -201,11 +161,9 @@ nodes.subtypes = subtypes
nodes.skipcodes = gluecodes
nodes.directioncodes = dircodes
-nodes.whatsitcodes = whatcodes
nodes.discretionarycodes = disccodes
nodes.directionvalues = dirvalues
-nodes.literalvalues = literalvalues
glyphcodes.glyph = glyphcodes.character
@@ -218,8 +176,6 @@ listcodes.column = listcodes.alignment
kerncodes.kerning = kerncodes.fontkern
kerncodes.italiccorrection = kerncodes.italiccorrection or 1 -- new
-literalvalues.direct = literalvalues.always
-
nodes.noadoptions = {
set = 0x08,
unused_1 = 0x00 + 0x08,
diff --git a/tex/context/base/mkxl/node-ini.mkxl b/tex/context/base/mkxl/node-ini.mkxl
index 4de4e00b4..b3f17e041 100644
--- a/tex/context/base/mkxl/node-ini.mkxl
+++ b/tex/context/base/mkxl/node-ini.mkxl
@@ -22,6 +22,7 @@
\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}
@@ -33,11 +34,10 @@
\registerctxluafile{node-dir}{} % experimental, not yet (and maybe never) used
\registerctxluafile{node-pro}{autosuffix}
\registerctxluafile{node-ser}{autosuffix}
-%registerctxluafile{node-ext}{}
\registerctxluafile{node-acc}{autosuffix} % experimental
%registerctxluafile{node-prp}{} % makes no sense (yet)
\registerctxluafile{node-scn}{autosuffix}
-\registerctxluafile{node-syn}{}
+\registerctxluafile{node-syn}{autosuffix}
\registerctxluafile{node-par}{autosuffix}
%D This might go away (needs checking anyway, very old code):
diff --git a/tex/context/base/mkxl/node-res.lmt b/tex/context/base/mkxl/node-res.lmt
index 7a37b1b9e..fbb1d1fe2 100644
--- a/tex/context/base/mkxl/node-res.lmt
+++ b/tex/context/base/mkxl/node-res.lmt
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['node-res'] = {
license = "see context related readme files"
}
-local type, next = type, next
+local type, next, rawset = type, next, rawset
local gmatch, format = string.gmatch, string.format
--[[ldx--
@@ -21,7 +21,6 @@ local report_nodes = logs.reporter("nodes","housekeeping")
nodes.pool = nodes.pool or { }
local nodepool = nodes.pool
-local whatsitcodes = nodes.whatsitcodes
local gluecodes = nodes.gluecodes
local kerncodes = nodes.kerncodes
local rulecodes = nodes.rulecodes
@@ -36,7 +35,6 @@ local rule_code = nodecodes.rule
local kern_code = nodecodes.kern
local glue_code = nodecodes.glue
local gluespec_code = nodecodes.gluespec
-local whatsit_code = nodecodes.whatsit
local currentfont = font.current
local texgetcount = tex.getcount
@@ -45,25 +43,6 @@ local allocate = utilities.storage.allocate
local reserved = { }
local nofreserved = 0
-local userids = allocate()
-local lastid = 0
-
-setmetatable(userids, {
- __index = function(t,k)
- if type(k) == "string" then
- lastid = lastid + 1
- rawset(userids,lastid,k)
- rawset(userids,k,lastid)
- return lastid
- else
- rawset(userids,k,k)
- return k
- end
- end,
- __call = function(t,k)
- return t[k]
- end
-} )
-- nuts overload
@@ -149,10 +128,7 @@ local function register_node(n)
return n
end
-nodepool.userids = userids
nodepool.register = register_node
-
-nutpool.userids = userids
nutpool.register = register_node -- could be register_nut
-- so far
@@ -168,11 +144,6 @@ local glyph = register_nut(new_nut(glyph_code,0))
local textdir = register_nut(new_nut(nodecodes.dir))
-local latelua = register_nut(new_nut(whatsit_code,whatsitcodes.latelua))
-local savepos = register_nut(new_nut(whatsit_code,whatsitcodes.savepos))
-
-local user_node = new_nut(whatsit_code,whatsitcodes.userdefined)
-
local left_margin_kern = register_nut(new_nut(kern_code,kerncodes.leftmargincode))
local right_margin_kern = register_nut(new_nut(kern_code,kerncodes.rightmargincode))
@@ -414,16 +385,6 @@ function nutpool.leader(width,list)
return n
end
-function nutpool.savepos()
- return copy_nut(savepos)
-end
-
-function nutpool.latelua(code)
- local n = copy_nut(latelua)
- nodeproperties[n] = { data = code }
- return n
-end
-
function nutpool.leftmarginkern(glyph,width)
local n = copy_nut(left_margin_kern)
if not glyph then
diff --git a/tex/context/base/mkxl/node-syn.lmt b/tex/context/base/mkxl/node-syn.lmt
new file mode 100644
index 000000000..ce5f0d2dd
--- /dev/null
+++ b/tex/context/base/mkxl/node-syn.lmt
@@ -0,0 +1,782 @@
+if not modules then modules = { } end modules ['node-syn'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- Because we have these fields in some node that are used by synctex, and because
+-- some users seem to like that feature, I decided to implement a variant that might
+-- work out better for ConTeXt. This is experimental code. I don't use it myself so
+-- it will take a while to mature. There will be some helpers that one can use in
+-- more complex situations like included xml files. Currently (somewhere else) we
+-- take care of valid files, that is: we prohibit access to files in the tree
+-- because we don't want users to mess up styles.
+--
+-- It is unclear how the output gets interpreted but by reverse engineering (and
+-- stripping) the file generated by generic synctex, I got there eventually. For
+-- instance, we only need to be able to go back to a place where text is entered,
+-- but still we need all that redundant box wrapping. Anyway, I was able to get a
+-- minimal output and cross my fingers that the parser used in editors is not
+-- changed in fundamental ways.
+--
+-- I only tested SumatraPDF with SciTE, for which one needs to configure in the
+-- viewer:
+--
+-- InverseSearchCmdLine = c:\data\system\scite\wscite\scite.exe "%f" "-goto:%l" $
+--
+-- In fact, a way more powerful implementation would have been not to add a library
+-- to a viewer, but letthe viewer call an external program:
+--
+-- InverseSearchCmdLine = mtxrun.exe --script synctex --edit --name="%f" --line="%l" $
+--
+-- which would (re)launch the editor in the right spot. That way we can really
+-- tune well to the macro package used and also avoid the fuzzy heuristics of
+-- the library.
+--
+-- Unfortunately syntex always removes the files at the end and not at the start
+-- (this happens in synctexterminate) so we need to work around that by using an
+-- intermediate file. This is no big deal in context (which has a runner) but
+-- definitely not nice.
+--
+-- The visualizer code is only needed for testing so we don't use fancy colors or
+-- provide more detail. After all we're only interested in rendered source text
+-- anyway. We try to play safe which sometimes means that we'd better no go
+-- somewhere than go someplace wrong.
+--
+-- A previous version had a mode for exporting boxes and such but I removed that
+-- as it made no sense. Also, collecting output in a table was not faster than
+-- directly piping to the file, probably because the amount is not that large. We
+-- keep some left-overs commented.
+--
+-- A significate reduction in file size can be realized when reusing the same
+-- values. Actually that triggered the current approach in ConTeXt. In the latest
+-- synctex parser vertical positions can be repeated by an "=" sign but for some
+-- reason only for that field. It's probably trivial to do that for all of "w h d v
+-- h" but it currently not the case so I'll delay that till all are supported. (We
+-- could benefit a lot from such a repetition scheme but not much from a "v" alone
+-- which -alas- indicates that synctex is still mostly a latex targeted story.)
+--
+-- It's kind of hard to fight the parser because it really wants to go to some file
+-- but maybe some day I can figure it out. Some untagged text (in the pdf) somehow
+-- gets seen as part of the last box. Anonymous content is simply not part of the
+-- concept. Using a dummy name doesn't help either as the editor gets a signal to
+-- open that dummy. Even an empty filename doesn't work.
+--
+-- We output really simple and compact code, like:
+--
+-- SyncTeX Version:1
+-- Input:1:e:/tmp/oeps.tex
+-- Input:2:c:/data/develop/context/sources/klein.tex
+-- Output:pdf
+-- Magnification:1000
+-- Unit:1
+-- X Offset:0
+-- Y Offset:0
+-- Content:
+-- !160
+-- {1
+-- h0,0:0,0,0,0,0
+-- v0,0:0,55380990:39158276,55380990,0
+-- h2,1:4661756,9176901:27969941,655360,327680
+-- h2,2:4661756,10125967:26048041,655360,327680
+-- h2,3:30962888,10125967:1668809,655360,327680
+-- h2,3:4661756,11075033:23142527,655360,327680
+-- h2,4:28046650,11075033:4585047,655360,327680
+-- h2,4:4661756,12024099:22913954,655360,327680
+-- h2,5:27908377,12024099:4723320,655360,327680
+-- h2,5:4661756,12973165:22918783,655360,327680
+-- h2,6:27884864,12973165:4746833,655360,327680
+-- h2,6:4661756,13922231:18320732,655360,327680
+-- ]
+-- !533
+-- }1
+-- Input:3:c:/data/develop/context/sources/ward.tex
+-- !57
+-- {2
+-- h0,0:0,0,0,0,0
+-- v0,0:0,55380990:39158276,55380990,0
+-- h3,1:4661756,9176901:18813145,655360,327680
+-- h3,2:23713999,9176901:8917698,655360,327680
+-- h3,2:4661756,10125967:10512978,655360,327680
+-- h3,3:15457206,10125967:17174491,655360,327680
+-- h3,3:4661756,11075033:3571223,655360,327680
+-- h3,4:8459505,11075033:19885281,655360,327680
+-- h3,5:28571312,11075033:4060385,655360,327680
+-- h3,5:4661756,12024099:15344870,655360,327680
+-- ]
+-- !441
+-- }2
+-- !8
+-- Postamble:
+-- Count:22
+-- !23
+-- Post scriptum:
+--
+-- But for some reason, when the pdf file has some extra content (like page numbers)
+-- the main document is consulted. Bah. It would be nice to have a mode for *only*
+-- looking at marked areas. It somehow works not but maybe depends on the parser.
+--
+-- Supporting reuseable objects makes not much sense as these are often graphics or
+-- ornamental. They can not have hyperlinks etc (at least not without some hackery
+-- which I'm not willing to do) so basically they are sort of useless for text.
+--
+-- Some generic (more clever code) has been removed as I don't see things change
+-- that much.
+
+local type, rawset = type, rawset
+local concat = table.concat
+local formatters = string.formatters
+local replacesuffix, suffixonly, nameonly = file.replacesuffix, file.suffix, file.nameonly
+local openfile, renamefile, removefile = io.open, os.rename, os.remove
+
+local report_system = logs.reporter("system")
+
+local tex = tex
+local texget = tex.get
+
+local nuts = nodes.nuts
+
+local getid = nuts.getid
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getnext = nuts.getnext
+local getwhd = nuts.getwhd
+local getwidth = nuts.getwidth
+local getsubtype = nuts.getsubtype
+
+local nodecodes = nodes.nodecodes
+local kerncodes = nodes.kerncodes
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
+local kern_code = nodecodes.kern
+----- rule_code = nodecodes.rule
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local dir_code = nodecodes.dir
+local fontkern_code = kerncodes.fontkern
+
+local cancel_code = nodes.dircodes.cancel
+
+local insert_before = nuts.insert_before
+local insert_after = nuts.insert_after
+
+local nodepool = nuts.pool
+local new_latelua = nodepool.latelua
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+
+local getdimensions = nuts.dimensions
+local getrangedimensions = nuts.rangedimensions
+
+local getsynctexfields = nuts.getsynctexfields or nuts.get_synctex_fields
+local forcesynctextag = tex.forcesynctextag or tex.force_synctex_tag
+local forcesynctexline = tex.forcesynctexline or tex.force_synctex_line
+local getsynctexline = tex.getsynctexline or tex.get_synctex_line
+local setsynctexmode = tex.setsynctexmode or tex.set_synctex_mode
+
+local foundintree = resolvers.foundintree
+
+local getpagedimensions = layouts.getpagedimensions
+
+local eol = "\010"
+
+----- f_glue = formatters["g%i,%i:%i,%i\010"]
+----- f_glyph = formatters["x%i,%i:%i,%i\010"]
+----- f_kern = formatters["k%i,%i:%i,%i:%i\010"]
+----- f_rule = formatters["r%i,%i:%i,%i:%i,%i,%i\010"]
+----- f_form = formatters["f%i,%i,%i\010"]
+local z_hlist = "[0,0:0,0:0,0,0\010"
+local z_vlist = "(0,0:0,0:0,0,0\010"
+----- z_xform = "<0,0:0,0,0\010" -- or so
+local s_hlist = "]\010"
+local s_vlist = ")\010"
+----- s_xform = ">\010"
+local f_hlist_1 = formatters["h%i,%i:%i,%i:%i,%i,%i\010"]
+local f_hlist_2 = formatters["h%i,%i:%i,%s:%i,%i,%i\010"]
+local f_vlist_1 = formatters["v%i,%i:%i,%i:%i,%i,%i\010"]
+local f_vlist_2 = formatters["v%i,%i:%i,%s:%i,%i,%i\010"]
+
+local synctex = luatex.synctex or { }
+luatex.synctex = synctex
+
+local getpos ; getpos = function() getpos = job.positions.getpos return getpos() end
+
+-- status stuff
+
+local enabled = false
+local paused = 0
+local used = false
+local never = false
+
+-- the file name stuff
+
+local noftags = 0
+local stnums = { }
+local nofblocked = 0
+local blockedfilenames = { }
+local blockedsuffixes = {
+ mkii = true,
+ mkiv = true,
+ mkvi = true,
+ mkxl = true,
+ mklx = true,
+ mkix = true,
+ mkxi = true,
+ -- lfg = true,
+}
+
+local sttags = table.setmetatableindex(function(t,name)
+ if blockedsuffixes[suffixonly(name)] then
+ -- Just so that I don't get the ones on my development tree.
+ nofblocked = nofblocked + 1
+ return 0
+ elseif blockedfilenames[nameonly(name)] then
+ -- So we can block specific files.
+ nofblocked = nofblocked + 1
+ return 0
+ elseif foundintree(name) then
+ -- One shouldn't edit styles etc this way.
+ nofblocked = nofblocked + 1
+ return 0
+ else
+ noftags = noftags + 1
+ t[name] = noftags
+ stnums[noftags] = name
+ return noftags
+ end
+end)
+
+function synctex.blockfilename(name)
+ blockedfilenames[nameonly(name)] = name
+end
+
+function synctex.setfilename(name,line)
+ if paused == 0 and name then
+ forcesynctextag(sttags[name])
+ if line then
+ forcesynctexline(line)
+ end
+ end
+end
+
+function synctex.resetfilename()
+ if paused == 0 then
+ forcesynctextag(0)
+ forcesynctexline(0)
+ end
+end
+
+do
+
+ local nesting = 0
+ local ignored = false
+
+ function synctex.pushline()
+ nesting = nesting + 1
+ if nesting == 1 then
+ local l = getsynctexline()
+ ignored = l and l > 0
+ if not ignored then
+ forcesynctexline(texget("inputlineno"))
+ end
+ end
+ end
+
+ function synctex.popline()
+ if nesting == 1 then
+ if not ignored then
+ forcesynctexline()
+ ignored = false
+ end
+ end
+ nesting = nesting - 1
+ end
+
+end
+
+-- the node stuff
+
+local filehandle = nil
+local nofsheets = 0
+local nofobjects = 0
+local last = 0
+local filesdone = 0
+local tmpfile = false
+local logfile = false
+
+local function writeanchor()
+ local size = filehandle:seek("end")
+ filehandle:write("!",size-last,eol)
+ last = size
+end
+
+local function writefiles()
+ local total = #stnums
+ if filesdone < total then
+ for i=filesdone+1,total do
+ filehandle:write("Input:",i,":",stnums[i],eol)
+ end
+ filesdone = total
+ end
+end
+
+local function makenames()
+ logfile = replacesuffix(tex.jobname,"synctex")
+ tmpfile = replacesuffix(logfile,"syncctx")
+end
+
+local function flushpreamble()
+ makenames()
+ filehandle = openfile(tmpfile,"wb")
+ if filehandle then
+ filehandle:write("SyncTeX Version:1",eol)
+ writefiles()
+ filehandle:write("Output:pdf",eol)
+ filehandle:write("Magnification:1000",eol)
+ filehandle:write("Unit:1",eol)
+ filehandle:write("X Offset:0",eol)
+ filehandle:write("Y Offset:0",eol)
+ filehandle:write("Content:",eol)
+ flushpreamble = function()
+ writefiles()
+ return filehandle
+ end
+ else
+ enabled = false
+ end
+ return filehandle
+end
+
+function synctex.wrapup()
+ if tmpfile then
+ renamefile(tmpfile,logfile)
+ tmpfile = nil
+ end
+end
+
+local function flushpostamble()
+ if not filehandle then
+ return
+ end
+ writeanchor()
+ filehandle:write("Postamble:",eol)
+ filehandle:write("Count:",nofobjects,eol)
+ writeanchor()
+ filehandle:write("Post scriptum:",eol)
+ filehandle:close()
+ enabled = false
+end
+
+local x_hlist do
+
+ local function doaction_1(t,l,w,h,d)
+ local pagewidth, pageheight = getpagedimensions()
+ local x, y = getpos()
+ filehandle:write(f_hlist_1(t,l,x,pageheight-y,w,h,d))
+ nofobjects = nofobjects + 1
+ end
+
+ local lasty = false
+
+ local function doaction_2(t,l,w,h,d)
+ local pagewidth, pageheight = getpagedimensions()
+ local x, y = getpos()
+ y = pageheight - y
+ filehandle:write(f_hlist_2(t,l,x,y == lasty and "=" or y,w,h,d))
+ lasty = y
+ nofobjects = nofobjects + 1
+ end
+
+ local doaction = doaction_1
+
+ x_hlist = function(head,current,t,l,w,h,d)
+ if filehandle then
+ return insert_before(head,current,new_latelua(function() doaction(t,l,w,h,d) end))
+ else
+ return head
+ end
+ end
+
+ directives.register("system.synctex.compression", function(v)
+ doaction = tonumber(v) == 2 and doaction_2 or doaction_1
+ end)
+
+end
+
+-- color is already handled so no colors
+
+local collect = nil
+local fulltrace = false
+local trace = false
+local height = 10 * 65536
+local depth = 5 * 65536
+local traceheight = 32768
+local tracedepth = 32768
+
+trackers.register("system.synctex.visualize", function(v)
+ trace = v
+ fulltrace = v == "real"
+end)
+
+local function inject(head,first,last,tag,line)
+ local w, h, d = getdimensions(first,getnext(last))
+ if h < height then
+ h = height
+ end
+ if d < depth then
+ d = depth
+ end
+ if trace then
+ head = insert_before(head,first,new_rule(w,fulltrace and h or traceheight,fulltrace and d or tracedepth))
+ head = insert_before(head,first,new_kern(-w))
+ end
+ head = x_hlist(head,first,tag,line,w,h,d)
+ return head
+end
+
+local function collect_min(head)
+ local current = head
+ while current do
+ local id = getid(current)
+ if id == glyph_code then
+ local first = current
+ local last = current
+ local tag = 0
+ local line = 0
+ while true do
+ if id == glyph_code then
+ local tc, lc = getsynctexfields(current)
+ if tc and tc > 0 then
+ tag = tc
+ line = lc
+ end
+ last = current
+ elseif id == disc_code or (id == kern_code and getsubtype(current) == fontkern_code) then
+ last = current
+ else
+ if tag > 0 then
+ head = inject(head,first,last,tag,line)
+ end
+ break
+ end
+ current = getnext(current)
+ if current then
+ id = getid(current)
+ else
+ if tag > 0 then
+ head = inject(head,first,last,tag,line)
+ end
+ return head
+ end
+ end
+ end
+ -- pick up (as id can have changed)
+ if id == hlist_code or id == vlist_code then
+ local list = getlist(current)
+ if list then
+ local l = collect(list)
+ if l ~= list then
+ setlist(current,l)
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ return head
+end
+
+local function inject(parent,head,first,last,tag,line)
+ local w, h, d = getrangedimensions(parent,first,getnext(last))
+ if h < height then
+ h = height
+ end
+ if d < depth then
+ d = depth
+ end
+ if trace then
+ head = insert_before(head,first,new_rule(w,fulltrace and h or traceheight,fulltrace and d or tracedepth))
+ head = insert_before(head,first,new_kern(-w))
+ end
+ head = x_hlist(head,first,tag,line,w,h,d)
+ return head
+end
+
+local function collect_max(head,parent)
+ local current = head
+ while current do
+ local id = getid(current)
+ if id == glyph_code then
+ local first = current
+ local last = current
+ local tag = 0
+ local line = 0
+ while true do
+ if id == glyph_code then
+ local tc, lc = getsynctexfields(current)
+ if tc and tc > 0 then
+ if tag > 0 and (tag ~= tc or line ~= lc) then
+ head = inject(parent,head,first,last,tag,line)
+ first = current
+ end
+ tag = tc
+ line = lc
+ last = current
+ else
+ if tag > 0 then
+ head = inject(parent,head,first,last,tag,line)
+ tag = 0
+ end
+ first = nil
+ last = nil
+ end
+ elseif id == disc_code then
+ if not first then
+ first = current
+ end
+ last = current
+ elseif id == kern_code and getsubtype(current) == fontkern_code then
+ if first then
+ last = current
+ end
+ elseif id == glue_code then
+ if tag > 0 then
+ local tc, lc = getsynctexfields(current)
+ if tc and tc > 0 then
+ if tag ~= tc or line ~= lc then
+ head = inject(parent,head,first,last,tag,line)
+ tag = 0
+ break
+ end
+ else
+ head = inject(parent,head,first,last,tag,line)
+ tag = 0
+ break
+ end
+ else
+ tag = 0
+ break
+ end
+ id = nil -- so no test later on
+ elseif id == penalty_code then
+ -- go on (and be nice for math)
+ else
+ if tag > 0 then
+ head = inject(parent,head,first,last,tag,line)
+ tag = 0
+ end
+ break
+ end
+ current = getnext(current)
+ if current then
+ id = getid(current)
+ else
+ if tag > 0 then
+ head = inject(parent,head,first,last,tag,line)
+ end
+ return head
+ end
+ end
+ end
+ -- pick up (as id can have changed)
+ if id == hlist_code or id == vlist_code then
+ local list = getlist(current)
+ if list then
+ local l = collect(list,current)
+ if l and l ~= list then
+ setlist(current,l)
+ end
+ end
+ end
+ current = getnext(current)
+ end
+ return head
+end
+
+collect = collect_max
+
+function synctex.collect(head,where)
+ if enabled and where ~= "object" then
+ return collect(head,head)
+ else
+ return head
+ end
+end
+
+-- also no solution for bad first file resolving in sumatra
+
+function synctex.start()
+ if enabled then
+ nofsheets = nofsheets + 1 -- could be realpageno
+ if flushpreamble() then
+ writeanchor()
+ filehandle:write("{",nofsheets,eol)
+ -- this seems to work:
+ local pagewidth, pageheight = getpagedimensions()
+ filehandle:write(z_hlist)
+ filehandle:write(f_vlist_1(0,0,0,pageheight,pagewidth,pageheight,0))
+ end
+ end
+end
+
+function synctex.stop()
+ if enabled then
+ -- filehandle:write(s_vlist,s_hlist)
+ filehandle:write(s_hlist)
+ writeanchor()
+ filehandle:write("}",nofsheets,eol)
+ nofobjects = nofobjects + 2
+ end
+end
+
+local enablers = { }
+local disablers = { }
+
+function synctex.registerenabler(f)
+ enablers[#enablers+1] = f
+end
+
+function synctex.registerdisabler(f)
+ disablers[#disablers+1] = f
+end
+
+function synctex.enable()
+ if not never and not enabled then
+ enabled = true
+ setsynctexmode(3) -- we want details
+ if not used then
+ nodes.tasks.enableaction("shipouts","luatex.synctex.collect")
+ report_system("synctex functionality is enabled, expect 5-10 pct runtime overhead!")
+ used = true
+ end
+ for i=1,#enablers do
+ enablers[i](true)
+ end
+ end
+end
+
+function synctex.disable()
+ if enabled then
+ setsynctexmode(0)
+ report_system("synctex functionality is disabled!")
+ enabled = false
+ for i=1,#disablers do
+ disablers[i](false)
+ end
+ end
+end
+
+function synctex.finish()
+ if enabled then
+ flushpostamble()
+ else
+ makenames()
+ removefile(logfile)
+ removefile(tmpfile)
+ end
+end
+
+local filename = nil
+
+function synctex.pause()
+ paused = paused + 1
+ if enabled and paused == 1 then
+ setsynctexmode(0)
+ end
+end
+
+function synctex.resume()
+ if enabled and paused == 1 then
+ setsynctexmode(3)
+ end
+ paused = paused - 1
+end
+
+-- not the best place
+
+luatex.registerstopactions(synctex.finish)
+
+statistics.register("synctex tracing",function()
+ if used then
+ return string.format("%i referenced files, %i files ignored, %i objects flushed, logfile: %s",
+ noftags,nofblocked,nofobjects,logfile)
+ end
+end)
+
+local implement = interfaces.implement
+local variables = interfaces.variables
+
+function synctex.setup(t)
+ if t.state == variables.never then
+ synctex.disable() -- just in case
+ never = true
+ return
+ end
+ if t.method == variables.max then
+ collect = collect_max
+ else
+ collect = collect_min
+ end
+ if t.state == variables.start then
+ synctex.enable()
+ else
+ synctex.disable()
+ end
+end
+
+implement {
+ name = "synctexblockfilename",
+ arguments = "string",
+ actions = synctex.blockfilename,
+}
+
+implement {
+ name = "synctexsetfilename",
+ arguments = "string",
+ actions = synctex.setfilename,
+}
+
+implement {
+ name = "synctexresetfilename",
+ actions = synctex.resetfilename,
+}
+
+implement {
+ name = "setupsynctex",
+ actions = synctex.setup,
+ arguments = {
+ {
+ { "state" },
+ { "method" },
+ },
+ },
+}
+
+implement {
+ name = "synctexpause",
+ actions = synctex.pause,
+}
+
+implement {
+ name = "synctexresume",
+ actions = synctex.resume,
+}
+
+implement {
+ name = "synctexpushline",
+ actions = synctex.pushline,
+}
+
+implement {
+ name = "synctexpopline",
+ actions = synctex.popline,
+}
+
+implement {
+ name = "synctexdisable",
+ actions = synctex.disable,
+}
diff --git a/tex/context/base/mkxl/node-tra.lmt b/tex/context/base/mkxl/node-tra.lmt
index da3cb1d33..6060522be 100644
--- a/tex/context/base/mkxl/node-tra.lmt
+++ b/tex/context/base/mkxl/node-tra.lmt
@@ -704,7 +704,7 @@ table.setmetatableindex(nodestracerpool,function(t,k,v)
return v
end)
-function nutstracerpool.rule(w,h,d,c,s) -- so some day we can consider using literals (speedup)
+function nutstracerpool.rule(w,h,d,c,s)
return setproperties(new_rule(w,h,d),c,s)
end
diff --git a/tex/context/base/mkxl/page-lin.lmt b/tex/context/base/mkxl/page-lin.lmt
index 9ea502899..f50031ab3 100644
--- a/tex/context/base/mkxl/page-lin.lmt
+++ b/tex/context/base/mkxl/page-lin.lmt
@@ -192,7 +192,7 @@ local function resolve(n,m) -- we can now check the 'line' flag (todo)
if content then
if id == hlist_code then
for current, subtype in nextwhatsit, content do
- if subtype == latelua_code then
+ if subtype == latelua_code then -- this has to change!
local a = getattr(current,a_linereference)
if a then
cross_references[a] = m
diff --git a/tex/context/base/mkxl/scrn-pag.lmt b/tex/context/base/mkxl/scrn-pag.lmt
new file mode 100644
index 000000000..210a57707
--- /dev/null
+++ b/tex/context/base/mkxl/scrn-pag.lmt
@@ -0,0 +1,56 @@
+if not modules then modules = { } end modules ['scrn-pag'] = {
+ version = 1.001,
+ comment = "companion to scrn-pag.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+interactions = interactions or { }
+interactions.pages = interactions.pages or { }
+local pages = interactions.pages
+
+local implement = interfaces.implement
+
+pages.setupcanvas = layouts.setupcanvas
+
+local codeinjections = backends.codeinjections
+
+function pages.setpagetransition(specification)
+ codeinjections.setpagetransition(specification)
+end
+
+implement {
+ name = "setupcanvas",
+ actions = pages.setupcanvas,
+ arguments = {
+ {
+ { "mode" },
+ { "singlesided", "boolean" },
+ { "doublesided", "boolean" },
+ { "leftoffset", "dimen" },
+ { "topoffset", "dimen" },
+ { "width", "dimen" },
+ { "height", "dimen" },
+ { "paperwidth", "dimen" },
+ { "paperheight", "dimen" },
+ { "cropoffset", "dimen" },
+ { "bleedoffset", "dimen" },
+ { "artoffset", "dimen" },
+ { "trimoffset", "dimen" },
+ { "copies", "integer" },
+ { "print", "string" }, -- , tohash
+ }
+ }
+}
+
+implement {
+ name = "setpagetransition",
+ actions = pages.setpagetransition,
+ arguments = {
+ {
+ { "n" },
+ { "delay", "integer" },
+ }
+ }
+}
diff --git a/tex/context/base/mkxl/scrn-pag.mklx b/tex/context/base/mkxl/scrn-pag.mklx
index 80e16f63d..67e24178e 100644
--- a/tex/context/base/mkxl/scrn-pag.mklx
+++ b/tex/context/base/mkxl/scrn-pag.mklx
@@ -15,7 +15,7 @@
\writestatus{loading}{ConTeXt Screen Macros / Pages}
-\registerctxluafile{scrn-pag}{}
+\registerctxluafile{scrn-pag}{autosuffix}
\unprotect
diff --git a/tex/context/base/mkxl/spac-hor.mkxl b/tex/context/base/mkxl/spac-hor.mkxl
index 426580c7d..13d1f9021 100644
--- a/tex/context/base/mkxl/spac-hor.mkxl
+++ b/tex/context/base/mkxl/spac-hor.mkxl
@@ -677,6 +677,29 @@
\newskip \s_spac_narrower_right_last
\newconditional\s_spac_narrower_last_swap
+% \def\spac_narrower_start_apply#1%
+% {\narrowerparameter\c!before
+% \global\s_spac_narrower_left \zeropoint
+% \global\s_spac_narrower_right \zeropoint
+% \global\s_spac_narrower_middle\zeropoint
+% \edef\askednarrower{#1}%
+% \ifx\askednarrower\v!reverse
+% \ifconditional\s_spac_narrower_last_swap
+% \leftskip \s_spac_narrower_right_last
+% \rightskip\s_spac_narrower_left_last
+% \setfalse\s_spac_narrower_last_swap
+% \else
+% \leftskip \s_spac_narrower_left_last
+% \rightskip\s_spac_narrower_right_last
+% \settrue\s_spac_narrower_last_swap
+% \fi
+% \else
+% \normalexpanded{\processcommalistwithparameters[\askednarrower]}\spac_narrower_initialize
+% \advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax
+% \advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax
+% \fi
+% \seteffectivehsize}
+
\def\spac_narrower_start_apply#1%
{\narrowerparameter\c!before
\global\s_spac_narrower_left \zeropoint
@@ -685,18 +708,18 @@
\edef\askednarrower{#1}%
\ifx\askednarrower\v!reverse
\ifconditional\s_spac_narrower_last_swap
- \leftskip \s_spac_narrower_right_last
- \rightskip\s_spac_narrower_left_last
+ \frozen\leftskip \s_spac_narrower_right_last
+ \frozen\rightskip\s_spac_narrower_left_last
\setfalse\s_spac_narrower_last_swap
\else
- \leftskip \s_spac_narrower_left_last
- \rightskip\s_spac_narrower_right_last
+ \frozen\leftskip \s_spac_narrower_left_last
+ \frozen\rightskip\s_spac_narrower_right_last
\settrue\s_spac_narrower_last_swap
\fi
\else
\normalexpanded{\processcommalistwithparameters[\askednarrower]}\spac_narrower_initialize
- \advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax
- \advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax
+ \frozen\advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax
+ \frozen\advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax
\fi
\seteffectivehsize}
diff --git a/tex/context/base/mkxl/strc-reg.mkxl b/tex/context/base/mkxl/strc-reg.mkxl
index af98ca481..dcfdd0946 100644
--- a/tex/context/base/mkxl/strc-reg.mkxl
+++ b/tex/context/base/mkxl/strc-reg.mkxl
@@ -40,6 +40,20 @@
% \index[pageclass::] {textclass::entry}
% \index[pageclass::key]{textclass::entry}
+% nice example:
+%
+% \setupregister[index]
+% [n=1,
+% pageleft=\hfilll,
+% pageright=\frozen\parfillleftskip 0pt plus 1fill\frozen\parfillrightskip 0pt\par]
+%
+% \starttext
+%
+% {\showmakeup \placeindex \page}
+%
+% % \dorecurse{10}{\dontleavehmode \index{AAA}\page}
+% \dorecurse{100}{\dontleavehmode\index{AAA}\page}
+
% tzt variant with n entries, parameters and userdata (altnum)
\installcorenamespace{register}
diff --git a/tex/context/base/mkxl/trac-vis.lmt b/tex/context/base/mkxl/trac-vis.lmt
index 8c04a0372..6e9bd8e8c 100644
--- a/tex/context/base/mkxl/trac-vis.lmt
+++ b/tex/context/base/mkxl/trac-vis.lmt
@@ -595,17 +595,28 @@ local whatsit do
local w_cache = caches["whatsit"]
local tags = {
- open = "OPN",
- write = "WRI",
- close = "CLS",
- special = "SPE",
- latelua = "LUA",
- savepos = "POS",
- userdefined = "USR",
- literal = "LIT",
- setmatrix = "MAT",
- save = "SAV",
- restore = "RES",
+ [whatsitcodes.open] = "OPN",
+ [whatsitcodes.write] = "WRI",
+ [whatsitcodes.close] = "CLS",
+ -- [whatsitcodes.special] = "SPE",
+ [whatsitcodes.latelua] = "LUA",
+ [whatsitcodes.savepos] = "POS",
+ [whatsitcodes.userdefined] = "USR",
+ [whatsitcodes.literal] = "LIT",
+ [whatsitcodes.setmatrix] = "MAT",
+ [whatsitcodes.save] = "SAV",
+ [whatsitcodes.restore] = "RES",
+ [whatsitcodes.startscaling] = "+SCA",
+ [whatsitcodes.stopscaling] = "-SCA",
+ [whatsitcodes.startrotation] = "+ROT",
+ [whatsitcodes.stoprotation] = "-ROT",
+ [whatsitcodes.startmirroring] = "+MIR",
+ [whatsitcodes.stopmirroring] = "-MIR",
+ [whatsitcodes.startclipping] = "+CLP",
+ [whatsitcodes.stopclipping] = "-CLP",
+ [whatsitcodes.startmatrix] = "+MAT",
+ [whatsitcodes.stopmatrix] = "-MAT",
+ [whatsitcodes.setstate] = "SET", -- can't happen because these are added after visualizing
}
whatsit = function(head,current)
@@ -614,7 +625,7 @@ local whatsit do
if info then
-- print("hit whatsit")
else
- info = sometext(formatters["W:%s"](what),usedfont,nil,c_white)
+ info = sometext(formatters["W:%s"](tags[what] or what),usedfont,nil,c_white)
setattr(info,a_layer,l_whatsit)
w_cache[what] = info
end
@@ -880,20 +891,13 @@ local ruledglyph do
setboth(current)
local linewidth = emwidth/(2*fraction)
local x_offset, y_offset, l_margin, r_margin, raise = getoffsets(current)
- wd = wd - l_margin - r_margin
- local info = (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule {
+ local info = setlink((dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule {
width = wd,
height = ht,
depth = dp,
line = linewidth,
type = "box",
- }
- if l_margin == 0 then
- info = setlink(info,new_kern(-wd))
- else
- info = setlink(new_kern(-l_margin),info,new_kern(-wd+l_margin))
- end
- --
+ },new_kern(-wd))
local c, f = isglyph(current)
local char = chardata[f][c]
if char and type(char.unicode) == "table" then -- hackery test
@@ -1409,7 +1413,7 @@ do
trace_marginkern = band(a,0x100000) ~= 0
trace_mathlistkern = band(a,0x200000) ~= 0
trace_dir = band(a,0x400000) ~= 0
- trace_whatsit = band(a,0x800000) ~= 0
+ trace_par = band(a,0x800000) ~= 0
end
elseif a == unsetvalue then
goto list
diff --git a/tex/context/base/mkxl/typo-cap.lmt b/tex/context/base/mkxl/typo-cap.lmt
index dbf6950c8..67acb2535 100644
--- a/tex/context/base/mkxl/typo-cap.lmt
+++ b/tex/context/base/mkxl/typo-cap.lmt
@@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['typo-cap'] = {
local next, type, tonumber = next, type, tonumber
local format, insert = string.format, table.insert
-local div, getrandom = math.div, utilities.randomizer.get
+local div, getrandom, random = math.div, utilities.randomizer.get, math.random
local trace_casing = false trackers.register("typesetters.casing", function(v) trace_casing = v end)
@@ -435,3 +435,24 @@ interfaces.implement {
actions = cases.set,
arguments = { "argument" }
}
+
+-- An example of a special plug, see type-imp-punk for usage.
+
+cases.register("randomvariant", function(start)
+ local char, fnt = isglyph(start)
+ local data = fontchar[fnt][char]
+ if data then
+ local variants = data.variants
+ if variants then
+ local n = #variants
+ local i = getrandom("variant",1,n+1)
+ if i > n then
+ -- we keep the original
+ else
+ setchar(start,variants[i])
+ end
+ return start, true
+ end
+ end
+ return start, false
+end)
diff --git a/tex/context/fonts/mkiv/bonum-math.lfg b/tex/context/fonts/mkiv/bonum-math.lfg
index 8dfa63405..51ca2d7f1 100644
--- a/tex/context/fonts/mkiv/bonum-math.lfg
+++ b/tex/context/fonts/mkiv/bonum-math.lfg
@@ -1,5 +1,8 @@
-local kern_200 = { bottomright = { { kern = -200 } } }
-local kern_100 = { bottomright = { { kern = -100 } } }
+local kern_V = { bottomright = { { kern = -200 } } }
+local kern_W = { bottomright = { { kern = -100 } } }
+local offset_f = { xoffset = "llx" }
+
+-- Beware of updates in ssty slots!
return {
name = "bonum-math",
@@ -10,12 +13,21 @@ return {
mathematics = {
dimensions = {
default = {
- [0x1D453] = { xoffset = "llx" },-- 𝑓
+ -- [0x1D453] = offset_f, -- 𝑓
+ -- ["1:0x1D453"] = offset_f, -- needed for compact
+ -- ["2:0x1D453"] = offset_f, -- needed for compact
+ ["*:0x1D453"] = offset_f, -- 𝑓
},
},
kerns = {
- [0x1D449] = kern_200, -- 𝑉
- [0x1D44A] = kern_100, -- 𝑊
+ -- [0x1D449] = kern_V, -- 𝑉
+ -- ["1:0x1D449"] = kern_V, -- needed for compact
+ -- ["2:0x1D449"] = kern_V, -- needed for compact
+ -- [0x1D44A] = kern_W, -- 𝑊
+ -- ["1:0x1D44A"] = kern_W, -- needed for compact
+ -- ["2:0x1D44A"] = kern_W, -- needed for compact
+ ["*:0x1D449"] = kern_V, -- 𝑉
+ ["*:0x1D44A"] = kern_W, -- 𝑊
},
alternates = {
dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" },
diff --git a/tex/context/fonts/mkiv/dejavu-math.lfg b/tex/context/fonts/mkiv/dejavu-math.lfg
index d28c69060..608b396f8 100644
--- a/tex/context/fonts/mkiv/dejavu-math.lfg
+++ b/tex/context/fonts/mkiv/dejavu-math.lfg
@@ -1,4 +1,7 @@
-local kern_250 = { bottomright = { { kern = -250 } } }
+local kern_V = { bottomright = { { kern = -250 } } }
+local kern_W = kern_W
+
+-- Beware of updates in ssty slots!
return {
name = "dejavu-math",
@@ -8,8 +11,14 @@ return {
copyright = "ConTeXt development team",
mathematics = {
kerns = {
- [0x1D449] = kern_250, --
- [0x1D44A] = kern_250, -- 𝑊
+ -- [0x1D449] = kern_V, -- 𝑉
+ -- ["1:0x1D449"] = kern_V, -- needed for compact
+ -- ["2:0x1D449"] = kern_V, -- needed for compact
+ -- [0x1D44A] = kern_W, -- 𝑊
+ -- ["1:0x1D44A"] = kern_W, -- needed for compact
+ -- ["2:0x1D44A"] = kern_W, -- needed for compact
+ ["*:0x1D449"] = kern_V, -- 𝑉
+ ["*:0x1D44A"] = kern_W, -- 𝑊
},
alternates = {
dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" },
diff --git a/tex/context/fonts/mkiv/minion-math.lfg b/tex/context/fonts/mkiv/minion-math.lfg
index a4f539ec7..863836c1c 100644
--- a/tex/context/fonts/mkiv/minion-math.lfg
+++ b/tex/context/fonts/mkiv/minion-math.lfg
@@ -1,6 +1,5 @@
-local kern_100 = { bottomright = { { kern = -100 } } }
-local kern_150 = { bottomright = { { kern = -150 } } }
-local kern_200 = { bottomright = { { kern = -200 } } }
+local kern_W = { bottomright = { { kern = -150 } } }
+local kern_V = { bottomright = { { kern = -200 } } }
return {
name = "minion-math",
@@ -23,8 +22,9 @@ return {
},
mathematics = {
kerns = {
- [0x1D449] = kern_200, -- 𝑉
- [0x1D44A] = kern_150, -- 𝑊
+ [0x1D449] = kern_V, -- 𝑉
+ [0x1D44A] = kern_W, -- 𝑊
+ -- todo: ssty 1/2
},
},
}
diff --git a/tex/context/fonts/mkiv/pagella-math.lfg b/tex/context/fonts/mkiv/pagella-math.lfg
index c85ff3f6b..d4ae14162 100644
--- a/tex/context/fonts/mkiv/pagella-math.lfg
+++ b/tex/context/fonts/mkiv/pagella-math.lfg
@@ -1,7 +1,8 @@
-local kern_200 = { bottomright = { { kern = -200 } } }
-local kern_100 = { bottomright = { { kern = -100 } } }
+local kern_V = { bottomright = { { kern = -200 } } }
+local kern_W = { bottomright = { { kern = -100 } } }
+local offset_f = { xoffset = "llx" }
--- Beware of updates !
+-- Beware of updates in ssty slots!
return {
name = "pagella-math",
@@ -12,13 +13,22 @@ return {
mathematics = {
dimensions = {
default = {
- -- [0x1D453] = { xoffset = 162, width = 278 + 162 },-- 𝑓
- [0x1D453] = { xoffset = "llx" },-- 𝑓
+ -- [0x1D453] = { xoffset = 162, width = 278 + 162 },-- 𝑓
+ -- [0x1D453] = offset_f, -- 𝑓
+ -- ["1:0x1D453"] = offset_f, -- needed for compact
+ -- ["2:0x1D453"] = offset_f, -- needed for compact
+ ["*:0x1D453"] = offset_f, -- 𝑓
},
},
kerns = {
- [0x1D449] = kern_200, -- 𝑉
- [0x1D44A] = kern_100, -- 𝑊
+ -- [0x1D449] = kern_V, -- 𝑉
+ -- ["1:0x1D449"] = kern_V, -- needed for compact
+ -- ["2:0x1D449"] = kern_V, -- needed for compact
+ -- [0x1D44A] = kern_W, -- 𝑊
+ -- ["1:0x1D44A"] = kern_W, -- needed for compact
+ -- ["2:0x1D44A"] = kern_W, -- needed for compact
+ ["*:0x1D449"] = kern_V, -- 𝑉
+ ["*:0x1D44A"] = kern_W, -- 𝑊
},
alternates = {
dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" },
diff --git a/tex/context/fonts/mkiv/schola-math.lfg b/tex/context/fonts/mkiv/schola-math.lfg
index 9787c18a9..b60bc6d99 100644
--- a/tex/context/fonts/mkiv/schola-math.lfg
+++ b/tex/context/fonts/mkiv/schola-math.lfg
@@ -1,5 +1,7 @@
-local kern_200_050 = { bottomright = { { kern = -200 } }, topright = { { kern = 50 } } }
-local kern_100_050 = { bottomright = { { kern = -100 } }, topright = { { kern = 50 } } }
+local kern_V = { bottomright = { { kern = -200 } }, topright = { { kern = 50 } } }
+local kern_W = { bottomright = { { kern = -100 } }, topright = { { kern = 50 } } }
+
+-- Beware of updates in ssty slots!
return {
name = "schola-math",
@@ -9,8 +11,14 @@ return {
copyright = "ConTeXt development team",
mathematics = {
kerns = {
- [0x1D449] = kern_200_050, --
- [0x1D44A] = kern_100_050, -- 𝑊
+ -- [0x1D449] = kern_V, -- 𝑉
+ -- ["1:0x1D449"] = kern_V, -- needed for compact
+ -- ["2:0x1D449"] = kern_V, -- needed for compact
+ -- [0x1D44A] = kern_W, -- 𝑊
+ -- ["1:0x1D44A"] = kern_W, -- needed for compact
+ -- ["2:0x1D44A"] = kern_W, -- needed for compact
+ ["*:0x1D449"] = kern_V, -- 𝑉
+ ["*:0x1D44A"] = kern_W, -- 𝑊
},
alternates = {
dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" },
diff --git a/tex/context/fonts/mkiv/termes-math.lfg b/tex/context/fonts/mkiv/termes-math.lfg
index 1501fd536..3cf8685eb 100644
--- a/tex/context/fonts/mkiv/termes-math.lfg
+++ b/tex/context/fonts/mkiv/termes-math.lfg
@@ -1,5 +1,8 @@
-local kern_200 = { bottomright = { { kern = -200 } } }
-local kern_100 = { bottomright = { { kern = -100 } } }
+local kern_V = { bottomright = { { kern = -200 } } }
+local kern_W = { bottomright = { { kern = -100 } } }
+local offset_f = { xoffset = "llx" }
+
+-- Beware of updates in ssty slots!
return {
name = "termes-math",
@@ -10,12 +13,21 @@ return {
mathematics = {
dimensions = {
default = {
- [0x1D453] = { xoffset = "llx" },-- 𝑓
+ -- [0x1D453] = offset_f, -- 𝑓
+ -- ["1:0x1D453"] = offset_f, -- needed for compact
+ -- ["2:0x1D453"] = offset_f, -- needed for compact
+ ["*:0x1D453"] = offset_f, -- 𝑓
},
},
kerns = {
- [0x1D449] = kern_200, -- 𝑉
- [0x1D44A] = kern_100, -- 𝑊
+ -- [0x1D449] = kern_V, -- 𝑉
+ -- ["1:0x1D449"] = kern_V, -- needed for compact
+ -- ["2:0x1D449"] = kern_V, -- needed for compact
+ -- [0x1D44A] = kern_W, -- 𝑊
+ -- ["1:0x1D44A"] = kern_W, -- needed for compact
+ -- ["2:0x1D44A"] = kern_W, -- needed for compact
+ ["*:0x1D449"] = kern_V, -- 𝑉
+ ["*:0x1D44A"] = kern_W, -- 𝑊
},
alternates = {
dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" },
diff --git a/tex/context/fonts/mkiv/type-imp-punk.mkxl b/tex/context/fonts/mkiv/type-imp-punk.mkxl
new file mode 100644
index 000000000..aa01a1d4e
--- /dev/null
+++ b/tex/context/fonts/mkiv/type-imp-punk.mkxl
@@ -0,0 +1,54 @@
+%D \module
+%D [ file=type-imp-punk,
+%D version=2020.01.17,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Punk Again,
+%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 Yet another look at punk.
+
+\ifdefined\enablerandomvariants\else
+ \useMPlibrary[punk]
+\fi
+
+\doifelse {\truefontname{Serif}} {unknown} {
+ \writestatus{fonts}{you need to load a base bodyfont first}
+ \endinput
+} {
+ % we're ok
+}
+
+\starttypescriptcollection[punk]
+
+ \definefontfeature [punk] [metapost={category=punk,preroll=punkpreroll}]
+ \definefontfeature [punkrandom] [metapost={category=punk,preroll=punkpreroll,variants=5}]
+ \definefontfeature [punkbold] [metapost={category=punk,preroll=punkpreroll,weight=2}]
+ \definefontfeature [punkslanted] [metapost={category=punk,preroll=punkpreroll,slant=.15}]
+ \definefontfeature [punkboldslanted] [metapost={category=punk,preroll=punkpreroll,slant=.15,weight=2}]
+ \definefontfeature [punkveryslanted] [metapost={category=punk,preroll=punkpreroll,slant=-.15}]
+ \definefontfeature [punksqueezed] [metapost={category=punk,preroll=punkpreroll,squeeze=.5}]
+ \definefontfeature [punkextended] [metapost={category=punk,preroll=punkpreroll,extend=1.3}]
+
+ \definefontsynonym [punkbase] [\truefontname{Serif}]
+
+ \starttypescript [\s!serif] [punk]
+ \definefontsynonym [\s!Serif] [punkbase] [\s!features=punk]
+ \definefontsynonym [\s!SerifSlanted] [punkbase] [\s!features=punkslanted]
+ \definefontsynonym [\s!SerifBold] [punkbase] [\s!features=punkbold]
+ \definefontsynonym [\s!SerifBoldSlanted][punkbase] [\s!features=punkboldslanted]
+ \definefontsynonym [\s!SerifItalic] [\s!SerifSlanted]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!SerifBoldSlanted]
+ \stoptypescript
+
+ \starttypescript [punk]
+ \definetypeface [punk] [\s!rm] [\s!serif] [punk] [\s!default]
+ \stoptypescript
+
+\stoptypescriptcollection
+
diff --git a/tex/context/fonts/mkiv/type-imp-texgyre.mkiv b/tex/context/fonts/mkiv/type-imp-texgyre.mkiv
index d10fe505f..72d3b3588 100644
--- a/tex/context/fonts/mkiv/type-imp-texgyre.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-texgyre.mkiv
@@ -247,8 +247,8 @@
\starttypescript [\s!math][times,termes][\s!all]
% \loadfontgoodies[texgyre]
% \definefontsynonym[\s!MathRoman][file:texgyre-termes-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre]
- \definefontsynonym[\s!MathRoman] [file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,mathextra},\s!goodies=termes-math]
- \definefontsynonym[\s!MathRomanBold][file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,termes-math-bold,mathextra},\s!goodies=termes-math]
+ \definefontsynonym[\s!MathRoman] [file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=termes-math]
+ \definefontsynonym[\s!MathRomanBold][file:texgyretermes-math.otf][\s!features={\s!math\mathsizesuffix,termes-math-bold,mathextra},\s!goodies=termes-math]
\stoptypescript
\stoptypescriptcollection
@@ -276,8 +276,8 @@
\starttypescript [\s!math][palatino,pagella][\s!all]
% \loadfontgoodies[texgyre]
% \definefontsynonym[\s!MathRoman][file:texgyre-pagella-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre]
- \definefontsynonym[\s!MathRoman] [file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,mathextra},\s!goodies=pagella-math]
- \definefontsynonym[\s!MathRomanBold][file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,pagella-math-bold,mathextra},\s!goodies=pagella-math]
+ \definefontsynonym[\s!MathRoman] [file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=pagella-math]
+ \definefontsynonym[\s!MathRomanBold][file:texgyrepagella-math.otf][\s!features={\s!math\mathsizesuffix,pagella-math-bold,mathextra},\s!goodies=pagella-math]
\stoptypescript
\stoptypescriptcollection
@@ -289,8 +289,8 @@
\starttypescript [\s!math][bookman,bonum][\s!all]
% \loadfontgoodies[texgyre]
% \definefontsynonym[\s!MathRoman][file:texgyre-bonum-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre]
- \definefontsynonym[\s!MathRoman] [file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,mathextra},\s!goodies=bonum-math]
- \definefontsynonym[\s!MathRomanBold][file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,bonum-math-bold,mathextra},\s!goodies=bonum-math]
+ \definefontsynonym[\s!MathRoman] [file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=bonum-math]
+ \definefontsynonym[\s!MathRomanBold][file:texgyrebonum-math.otf][\s!features={\s!math\mathsizesuffix,bonum-math-bold,mathextra},\s!goodies=bonum-math]
\stoptypescript
\stoptypescriptcollection
@@ -300,8 +300,8 @@
\starttypescript [\s!math][schoolbook,schola][\s!all]
% \loadfontgoodies[texgyre]
% \definefontsynonym[\s!MathRoman][file:texgyre-schola-math-regular.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=texgyre]
- \definefontsynonym[\s!MathRoman] [file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,mathextra},\s!goodies=schola-math]
- \definefontsynonym[\s!MathRomanBold][file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,oldmath,schola-math-bold,mathextra},\s!goodies=schola-math]
+ \definefontsynonym[\s!MathRoman] [file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,mathextra},\s!goodies=schola-math]
+ \definefontsynonym[\s!MathRomanBold][file:texgyreschola-math.otf][\s!features={\s!math\mathsizesuffix,schola-math-bold,mathextra},\s!goodies=schola-math]
\stoptypescript
\stoptypescriptcollection
diff --git a/tex/context/fonts/mkiv/xits-math.lfg b/tex/context/fonts/mkiv/xits-math.lfg
index b37ab1277..88d3a8d45 100644
--- a/tex/context/fonts/mkiv/xits-math.lfg
+++ b/tex/context/fonts/mkiv/xits-math.lfg
@@ -14,6 +14,7 @@ local italics = {
-- [0x1D44E] = 0.99, -- a (fraction of quad)
-- [0x1D44F] = 100, -- b (font points)
[0x1D453] = -0.0375, -- f
+ -- todo: ssty 1/2
}
}
diff --git a/tex/context/modules/mkiv/m-punk.mkiv b/tex/context/modules/mkiv/m-punk.mkiv
index 47f1a0177..9eb7411ba 100644
--- a/tex/context/modules/mkiv/m-punk.mkiv
+++ b/tex/context/modules/mkiv/m-punk.mkiv
@@ -17,6 +17,11 @@
%D https://www.youtube.com/watch?v=g5c2Htj8Vtw
%D \stoptyping
+\ifcase\contextlmtxmode\else
+ \writestatus{punk}{use metapost library punk instead}
+ \endinput
+\fi
+
\startluacode
local concat = table.concat
local round = math.round
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index c1300a71b..552559e96 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-11 16:28
+-- merge date : 2021-01-17 21:39
do -- begin closure to overcome local limits and interference