summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv')
-rw-r--r--tex/context/base/mkiv/attr-ini.lua7
-rw-r--r--tex/context/base/mkiv/back-ini.mkiv23
-rw-r--r--tex/context/base/mkiv/back-lua.lua336
-rw-r--r--tex/context/base/mkiv/back-mps.lua223
-rw-r--r--tex/context/base/mkiv/back-trf.lua17
-rw-r--r--tex/context/base/mkiv/cldf-int.lua382
-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/driv-ini.lua117
-rw-r--r--tex/context/base/mkiv/driv-shp.lua695
-rw-r--r--tex/context/base/mkiv/grph-inc.mkiv4
-rw-r--r--tex/context/base/mkiv/lpdf-eng.lua26
-rw-r--r--tex/context/base/mkiv/lpdf-epa.lua15
-rw-r--r--tex/context/base/mkiv/lpdf-lmt.lua390
-rw-r--r--tex/context/base/mkiv/lpdf-mis.lua4
-rw-r--r--tex/context/base/mkiv/luat-cnf.lua2
-rw-r--r--tex/context/base/mkiv/mult-def.lua13
-rw-r--r--tex/context/base/mkiv/mult-def.mkiv6
-rw-r--r--tex/context/base/mkiv/mult-prm.lua1
-rw-r--r--tex/context/base/mkiv/node-fin.lua17
-rw-r--r--tex/context/base/mkiv/node-fnt.lua4
-rw-r--r--tex/context/base/mkiv/node-nut.lua36
-rw-r--r--tex/context/base/mkiv/node-ref.lua59
-rw-r--r--tex/context/base/mkiv/page-run.lua2
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin26899 -> 26904 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin251955 -> 253018 bytes
-rw-r--r--tex/context/base/mkiv/strc-doc.lua11
-rw-r--r--tex/context/base/mkiv/strc-lnt.mkvi7
-rw-r--r--tex/context/base/mkiv/strc-reg.lua65
-rw-r--r--tex/context/base/mkiv/syst-ini.mkiv26
-rw-r--r--tex/context/base/mkiv/toks-ini.lua16
-rw-r--r--tex/context/base/mkiv/toks-scn.lua2
-rw-r--r--tex/context/base/mkiv/trac-deb.lua5
-rw-r--r--tex/context/base/mkiv/trac-inf.lua6
-rw-r--r--tex/context/base/mkiv/typo-cap.lua8
-rw-r--r--tex/context/base/mkiv/typo-pag.lua143
-rw-r--r--tex/context/base/mkiv/util-jsn.lua33
37 files changed, 1776 insertions, 929 deletions
diff --git a/tex/context/base/mkiv/attr-ini.lua b/tex/context/base/mkiv/attr-ini.lua
index dd971afc1..5d35d6ab5 100644
--- a/tex/context/base/mkiv/attr-ini.lua
+++ b/tex/context/base/mkiv/attr-ini.lua
@@ -34,6 +34,8 @@ attributes.states = attributes.states or { }
attributes.handlers = attributes.handlers or { }
attributes.unsetvalue = -0x7FFFFFFF
+local currentfont = font.current
+
local names = attributes.names
local numbers = attributes.numbers
local list = attributes.list
@@ -146,7 +148,7 @@ function attributes.save(name)
end
store[name] = {
attr = t,
- font = font.current(),
+ font = currentfont(),
}
end
@@ -163,7 +165,8 @@ function attributes.restore(name)
end
if font then
-- tex.font = font
- context.getvalue(fonts.hashes.csnames[font]) -- we don't have a direct way yet (will discuss it with taco)
+ -- context.getvalue(fonts.hashes.csnames[font])
+ currentfont(font)
end
end
-- store[name] = nil
diff --git a/tex/context/base/mkiv/back-ini.mkiv b/tex/context/base/mkiv/back-ini.mkiv
index ff19d0229..007f80d1a 100644
--- a/tex/context/base/mkiv/back-ini.mkiv
+++ b/tex/context/base/mkiv/back-ini.mkiv
@@ -64,8 +64,27 @@
\fi
\to \everysetupbackend
-%D For older styles:
+%D For the moment this is an experiment (defauls is pdf, but we also
+%D have lua, json and mps).
+%D
+%D \starttyping
+%D % \setupoutput[lua]
+%D % \setupoutput[json]
+%D % \setupoutput[mps]
+%D % \setupoutput[none] % for testing only
+%D % \setupoutput[empty] % for testing only
+%D
+%D \starttext
+%D \dorecurse{1000}{
+%D {\tf \red \samplefile{tufte}} \par
+%D {\bf \green \samplefile {ward}} \par
+%D {\sl \blue \samplefile{davis}} \par
+%D }
+%D \stoptext
+%D \stoptyping
+
+\unexpanded\def\setupoutput[#1]%
+ {\clf_enabledriver{#1}}
-\let\setupoutput\gobbleoneoptional
\protect \endinput
diff --git a/tex/context/base/mkiv/back-lua.lua b/tex/context/base/mkiv/back-lua.lua
index 257fda0a2..4e95d37e3 100644
--- a/tex/context/base/mkiv/back-lua.lua
+++ b/tex/context/base/mkiv/back-lua.lua
@@ -6,47 +6,349 @@ if not modules then modules = { } end modules ['back-lua'] = {
license = "see context related readme files"
}
-local buffer = { }
-local b = 0
+-- we can remap fonts
+
+local fontproperties = fonts.hashes.properties
+local fontparameters = fonts.hashes.parameters
+local fontshapes = fonts.hashes.shapes
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local bpfactor = number.dimenfactors.bp
+local texgetbox = tex.getbox
+
+local rulecodes = nodes.rulecodes
+local normalrule_code = rulecodes.normal
+----- boxrule_code = rulecodes.box
+----- imagerule_code = rulecodes.image
+----- emptyrule_code = rulecodes.empty
+----- userrule_code = rulecodes.user
+----- overrule_code = rulecodes.over
+----- underrule_code = rulecodes.under
+----- fractionrule_code = rulecodes.fraction
+----- radicalrule_code = rulecodes.radical
+local outlinerule_code = rulecodes.outline
+
+-- todo : per instance
+
+local pages = { }
+local fonts = { }
+local names = { }
+local mapping = { }
+local used = { }
+local shapes = { }
+local glyphs = { }
+local buffer = { }
+local b = 0
+local converter = nil
+
+local compact = false -- true
+local shapestoo = true
+
+local x, y, d, f, c, w, h, t, r, o
local function reset()
buffer = { }
b = 0
+ t = nil
+ x = nil
+ y = nil
+ d = nil
+ f = nil
+ c = nil
+ w = nil
+ h = nil
+ r = nil
+ o = nil
+end
+
+local function result()
+ -- todo: we're now still in the pdf backend but need different codeinjections
+ local codeinjections = backends.pdf.codeinjections
+ local getvariable = codeinjections.getidentityvariable or function() end
+ local jobname = environment.jobname or tex.jobname or "unknown"
+ return {
+ metadata = {
+ unit = "bp",
+ jobname = jobname,
+ title = getvariable("title") or jobname,
+ subject = getvariable("subject"),
+ author = getvariable("author"),
+ keywords = getvariable("keywords"),
+ time = os.date("%Y-%m-%d %H:%M"),
+ engine = environment.luatexengine .. " " .. environment.luatexversion,
+ context = environment.version,
+ },
+ fonts = fonts,
+ pages = pages,
+ shapes = shapes,
+ }
+end
+
+-- actions
+
+local function outputfilename(driver)
+ return tex.jobname .. "-output.lua"
+end
+
+local function save() -- might become a driver function that already is plugged into stopactions
+ local filename = outputfilename()
+ drivers.report("saving result in %a",filename)
+ starttiming(drivers)
+ local data = result()
+ if data then
+ io.savedata(filename,table.serialize(data))
+ end
+ stoptiming(drivers)
end
-local function initialize(specification)
+local function prepare(driver)
+ converter = drivers.converters.lmtx
+ luatex.registerstopactions(1,function()
+ save()
+ end)
+end
+
+local function initialize(driver,details)
reset()
end
-local function finalize()
+local function finalize(driver,details)
+ local n = details.pagenumber
+ local b = details.boundingbox
+ pages[n] = {
+ number = n,
+ content = buffer,
+ boundingbox = {
+ b[1] * bpfactor,
+ b[2] * bpfactor,
+ b[3] * bpfactor,
+ b[4] * bpfactor,
+ },
+ }
+end
+
+local function wrapup(driver)
end
-local function fetch()
- local saved = buffer
+local function cleanup(driver)
reset()
- return saved
end
-local function flushcharacter(current, pos_h, pos_v, pod_r, font, char)
- b = b + 1 ; buffer[b] = { "glyph", font, char, pos_h, pos_v, pos_r }
+local function convert(driver,boxnumber,pagenumber)
+ converter(driver,texgetbox(boxnumber),"page",pagenumber)
+end
+
+-- flushers
+
+local function updatefontstate(id)
+ if not mapping[id] then
+ local fn = #fonts + 1
+ mapping[id] = fn
+ local properties = fontproperties[id]
+ local parameters = fontparameters[id]
+ local filename = file.basename(properties.filename)
+ local fontname = properties.fullname or properties.fontname
+ if shapestoo then
+ if not names[fontname] then
+ local sn = #shapes+1
+ names[fontname] = sn
+ shapes[sn] = { }
+ glyphs[sn] = fontshapes[id].glyphs
+ end
+ end
+ fonts[fn] = {
+ filename = filename,
+ name = fontname,
+ size = parameters.size * bpfactor,
+ shapes = shapestoo and names[fontname] or nil,
+ }
+ end
+end
+
+local function flushcharacter(current, pos_h, pos_v, pos_r, font, char)
+ local fnt = mapping[font]
+ b = b + 1
+ buffer[b] = {
+ t = "glyph" ~= t and "glyph" or nil,
+ f = font ~= f and fnt or nil,
+ c = char ~= c and char or nil,
+ x = pos_h ~= x and (pos_h * bpfactor) or nil,
+ y = pos_v ~= y and (pos_v * bpfactor) or nil,
+ d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil,
+ }
+ t = "glyph"
+ f = font
+ c = char
+ x = pos_h
+ y = pos_v
+ d = pos_r
+ if shapestoo then
+ -- can be sped up if needed
+ local sn = fonts[fnt].shapes
+ local shp = shapes[sn]
+ if not shp[char] then
+ shp[char] = glyphs[sn][char]
+ end
+ end
+end
+
+local function rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o)
+ b = b + 1
+ buffer[b] = {
+ t = "rule" ~= t and "rule" or nil,
+ r = rule_s ~= r and rule_s or nil,
+ o = rule_s == "outline" and rule_o ~= o and (rule_o * bpfactor) or nil,
+ w = size_h ~= w and (size_h * bpfactor) or nil,
+ h = size_v ~= h and (size_v * bpfactor) or nil,
+ x = pos_h ~= x and (pos_h * bpfactor) or nil,
+ y = pos_v ~= y and (pos_v * bpfactor) or nil,
+ d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil,
+ }
+ t = "rule"
+ w = size_h
+ h = size_v
+ x = pos_h
+ y = pos_v
+ d = pos_r
+end
+
+local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v, subtype)
+ local rule_s, rule_o
+ if subtype == normalrule_code then
+ rule_s = "normal"
+ elseif subtype == outlinerule_code then
+ rule_s = "outline"
+ rule_o = getdata(current)
+ else
+ return
+ end
+ return rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o)
end
-local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v)
- b = b + 1 ; buffer[b] = { "rule", size_h, size_v, pos_h, pos_v, pos_r }
+local function flushsimplerule(current, pos_h, pos_v, pos_r, size_h, size_v)
+ return rule(pos_h, pos_v, pos_r, size_h, size_v, "normal", nil)
end
-- file stuff too
+-- todo: default flushers
+-- also color (via hash)
+
+-- installer
drivers.install {
name = "lua",
actions = {
- initialize = initialize,
- finalize = finalize,
- fetch = fetch,
- reset = reset,
+ prepare = prepare,
+ initialize = initialize,
+ finalize = finalize,
+ wrapup = wrapup,
+ cleanup = cleanup,
+ convert = convert,
+ outputfilename = outputfilename,
+ },
+ flushers = {
+ updatefontstate = updatefontstate,
+ character = flushcharacter,
+ rule = flushrule,
+ }
+}
+
+-- actions
+
+local function outputfilename(driver)
+ return tex.jobname .. "-output.json"
+end
+
+local function save() -- might become a driver function that already is plugged into stopactions
+ local filename = outputfilename()
+ drivers.report("saving result in %a",filename)
+ starttiming(drivers)
+ local data = result()
+ if data then
+ if not utilities.json then
+ require("util-jsn")
+ end
+ io.savedata(filename,utilities.json.tostring(data,not compact))
+ end
+ stoptiming(drivers)
+end
+
+local function prepare(driver)
+ converter = drivers.converters.lmtx
+ luatex.registerstopactions(1,function()
+ save()
+ end)
+end
+
+-- installer
+
+drivers.install {
+ name = "json",
+ actions = {
+ prepare = prepare,
+ initialize = initialize,
+ finalize = finalize,
+ wrapup = wrapup,
+ cleanup = cleanup,
+ convert = convert,
+ outputfilename = outputfilename,
+ },
+ flushers = {
+ updatefontstate = updatefontstate,
+ character = flushcharacter,
+ rule = flushrule,
+ }
+}
+
+-- actions
+
+local function outputfilename(driver)
+ return tex.jobname .. "-output.js"
+end
+
+local function save() -- might become a driver function that already is plugged into stopactions
+ local filename = outputfilename()
+ drivers.report("saving result in %a",filename)
+ starttiming(drivers)
+ local data = result()
+ if data then
+ if not utilities.json then
+ require("util-jsn")
+ end
+ io.savedata(filename,
+ "const JSON_CONTEXT = JSON.parse ( `" ..
+ utilities.json.tostring(data,not compact) ..
+ "` ) ;\n"
+ )
+ end
+ stoptiming(drivers)
+end
+
+local function prepare(driver)
+ converter = drivers.converters.lmtx
+ luatex.registerstopactions(1,function()
+ save()
+ end)
+end
+
+-- installer
+
+drivers.install {
+ name = "js",
+ actions = {
+ prepare = prepare,
+ initialize = initialize,
+ finalize = finalize,
+ wrapup = wrapup,
+ cleanup = cleanup,
+ convert = convert,
+ outputfilename = outputfilename,
},
flushers = {
- character = flushcharacter,
- rule = flushrule,
+ updatefontstate = updatefontstate,
+ character = flushcharacter,
+ rule = flushrule,
}
}
diff --git a/tex/context/base/mkiv/back-mps.lua b/tex/context/base/mkiv/back-mps.lua
index 380fb7a35..96c850ed6 100644
--- a/tex/context/base/mkiv/back-mps.lua
+++ b/tex/context/base/mkiv/back-mps.lua
@@ -6,89 +6,200 @@ if not modules then modules = { } end modules ['back-mps'] = {
license = "see context related readme files"
}
--- The basics are the same as the lua variant.
-
-local formatters = string.formatters
-local bpfactor = number.dimenfactors.bp
-
-local buffer = { }
-local b = 0
+local fontproperties = fonts.hashes.properties
+local fontparameters = fonts.hashes.parameters
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local bpfactor = number.dimenfactors.bp
+local texgetbox = tex.getbox
+local formatters = string.formatters
+
+local rulecodes = nodes.rulecodes
+local normalrule_code = rulecodes.normal
+----- boxrule_code = rulecodes.box
+----- imagerule_code = rulecodes.image
+----- emptyrule_code = rulecodes.empty
+----- userrule_code = rulecodes.user
+----- overrule_code = rulecodes.over
+----- underrule_code = rulecodes.under
+----- fractionrule_code = rulecodes.fraction
+----- radicalrule_code = rulecodes.radical
+local outlinerule_code = rulecodes.outline
+
+local fonts = { }
+local pages = { }
+local buffer = { }
+local b = 0
+local converter = nil
local function reset()
buffer = { }
b = 0
end
-local function initialize(specification)
- reset()
+local f_font = formatters[ "\\definefont[%s][file:%s*none @ %sbp]\n" ]
+
+local f_glyph = formatters[ [[draw textext.drt("\%s\char%i\relax") shifted (%N,%N);]] ]
+local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
+local f_outline = formatters[ [[draw unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
+
+-- actions
+
+local function outputfilename(driver)
+ return tex.jobname .. "-output.tex"
end
-local function finalize()
+local function save() -- might become a driver function that already is plugged into stopactions
+ starttiming(drivers)
+ if #pages > 0 then
+ local filename = outputfilename()
+ drivers.report("saving result in %a",filename)
+ reset()
+ b = b + 1
+ buffer[b] = "\\starttext\n"
+ for k, v in table.sortedhash(fonts) do
+ b = b + 1
+ buffer[b] = f_font(v.name,v.filename,v.size)
+ end
+ for i=1,#pages do
+ b = b + 1
+ buffer[b] = pages[i]
+ end
+ b = b + 1
+ buffer[b] = "\\stoptext\n"
+ io.savedata(filename,table.concat(buffer,"",1,b))
+ end
+ stoptiming(drivers)
end
-local function fetch()
- local saved = buffer
- reset()
- return saved
+local function prepare(driver)
+ converter = drivers.converters.lmtx
+ luatex.registerstopactions(1,function()
+ save()
+ end)
end
-local function flushcharacter(current, pos_h, pos_v, pod_r, font, char)
- b = b + 1 ; buffer[b] = { "glyph", font, char, pos_h, pos_v, pos_r }
+local function initialize(driver,details)
+ reset()
+ b = b + 1
+ buffer[b] = "\n\\startMPpage"
end
-local function flushrule(current, pos_h, pos_v, pod_r, size_h, size_v)
- b = b + 1 ; buffer[b] = { "rule", size_h, size_v, pos_h, pos_v, pos_r }
+local function finalize(driver,details)
+ b = b + 1
+ buffer[b] = "\\stopMPpage\n"
+ pages[details.pagenumber] = table.concat(buffer,"\n",1,b)
end
-drivers.install {
- name = "mps",
- actions = {
- initialize = initialize,
- finalize = finalize,
- fetch = fetch,
- reset = reset,
- },
- flushers = {
- character = flushcharacter,
- rule = flushrule,
- }
-}
+local function wrapup(driver)
+end
-if not mp then
- return
+local function cleanup(driver)
+ reset()
end
-local mpprint = mp.print
+local function convert(driver,boxnumber,pagenumber)
+ converter(driver,texgetbox(boxnumber),"page",pagenumber)
+end
-local f_glyph = formatters[ [[draw textext.drt("\setfontid%i\relax\char%i\relax") shifted (%N,%N);]] ]
-local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
+-- flushers
-local current = nil
-local size = 0
+local last
-function mp.place_buffermake(box)
- drivers.convert("mps",box)
- current = drivers.action("mps","fetch")
- size = #current
+local function updatefontstate(id)
+ if fonts[id] then
+ last = fonts[id].name
+ else
+ last = "MPSfont" .. converters.Characters(id)
+ fonts[id] = {
+ filename = file.basename(fontproperties[id].filename),
+ size = fontparameters[id].size * bpfactor,
+ name = last,
+ }
+ end
end
-function mp.place_buffersize()
- mpprint(size)
+local function flushcharacter(current, pos_h, pos_v, pod_r, font, char)
+ b = b + 1
+ buffer[b] = f_glyph(last,char,pos_h*bpfactor,pos_v*bpfactor)
end
-function mp.place_bufferslot(i)
- if i > 0 and i <= size then
- local b = buffer[i]
- local t = b[1]
- if t == "glyph" then
- mpprint(f_glyph(b[2],b[3],b[4]*bpfactor,b[5]*bpfactor))
- elseif t == "rule" then
- mpprint(f_rule(b[2]*bpfactor,b[3]*bpfactor,b[4]*bpfactor,b[5]*bpfactor))
- end
+local function flushrule(current, pos_h, pos_v, pod_r, size_h, size_v, subtype)
+ if subtype == normalrule_code then
+ b = b + 1
+ buffer[b] = f_rule(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor)
+ elseif subtype == outlinerule_code then
+ b = b + 1
+ buffer[b] = f_outline(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor)
end
end
-function mp.place_bufferwipe()
- current = nil
- size = 0
+local function flushsimplerule(current, pos_h, pos_v, pod_r, size_h, size_v)
+ b = b + 1
+ buffer[b] = f_rule(size_h*bpfactor,size_v*bpfactor,pos_h*bpfactor,pos_v*bpfactor)
end
+
+-- installer
+
+drivers.install {
+ name = "mps",
+ actions = {
+ prepare = prepare,
+ initialize = initialize,
+ finalize = finalize,
+ wrapup = wrapup,
+ cleanup = cleanup,
+ convert = convert,
+ outputfilename = outputfilename,
+ },
+ flushers = {
+ updatefontstate = updatefontstate,
+ character = flushcharacter,
+ rule = flushrule,
+ simplerule = flushsimplerule,
+ }
+}
+
+-- extras
+
+-- if not mp then
+-- return
+-- end
+--
+-- local mpprint = mp.print
+-- local formatters = string.formatters
+--
+-- local f_glyph = formatters[ [[draw textext.drt("\setfontid%i\relax\char%i\relax") shifted (%N,%N);]] ]
+-- local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
+--
+-- local current = nil
+-- local size = 0
+--
+-- function mp.place_buffermake(box)
+-- drivers.convert("mps",box)
+-- current = drivers.action("mps","fetch")
+-- size = #current
+-- end
+--
+-- function mp.place_buffersize()
+-- mpprint(size)
+-- end
+--
+-- function mp.place_bufferslot(i)
+-- if i > 0 and i <= size then
+-- local b = buffer[i]
+-- local t = b[1]
+-- if t == "glyph" then
+-- mpprint(f_glyph(b[2],b[3],b[4]*bpfactor,b[5]*bpfactor))
+-- elseif t == "rule" then
+-- mpprint(f_rule(b[2]*bpfactor,b[3]*bpfactor,b[4]*bpfactor,b[5]*bpfactor))
+-- end
+-- end
+-- end
+--
+-- function mp.place_bufferwipe()
+-- current = nil
+-- size = 0
+-- end
diff --git a/tex/context/base/mkiv/back-trf.lua b/tex/context/base/mkiv/back-trf.lua
index 721c856a9..1586bc440 100644
--- a/tex/context/base/mkiv/back-trf.lua
+++ b/tex/context/base/mkiv/back-trf.lua
@@ -141,14 +141,23 @@ implement { name = "stopmirroring", actions = startmirroring } -- not: stopsome
-- 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["q 0 w %s W n"](scanstring())))
+ context(savenode())
+ context(literalnode("origin",formatters["0 w %s W n"](scanstring())))
end
local function stopclipping()
- -- context(restorenode())
- context(literalnode("Q"))
+ context(restorenode())
end
implement { name = "startclipping", actions = startclipping }
diff --git a/tex/context/base/mkiv/cldf-int.lua b/tex/context/base/mkiv/cldf-int.lua
index 52cfea8d0..937e1da60 100644
--- a/tex/context/base/mkiv/cldf-int.lua
+++ b/tex/context/base/mkiv/cldf-int.lua
@@ -11,8 +11,9 @@ if not modules then modules = { } end modules ['cldf-int'] = {
-- needs checking
-- todo: multilingual
-local format, insert, remove, concat = string.format, table.insert, table.remove, table.concat
-local unpack = unpack or table.unpack
+local format, byte = string.format, string.byte
+local insert, remove, concat = table.insert, table.remove, table.concat
+local unpack, type = unpack or table.unpack, type
local catcodenumbers = catcodes.numbers
@@ -24,140 +25,282 @@ local contextsprint = context.sprint
local trace_define = false trackers.register("context.define", function(v) trace_define = v end)
-interfaces = interfaces or { }
+interfaces = interfaces or { }
+local implement = interfaces.implement
+local estart = interfaces.elements.start
+local estop = interfaces.elements.stop
-_clmh_ = utilities.parsers.settings_to_hash
-_clma_ = utilities.parsers.settings_to_array
+if CONTEXTLMTXMODE > 0 then
-local starters, stoppers, macros, stack = { }, { }, { }, { }
+ local scanners = tokens.scanners
+ local shortcuts = tokens.shortcuts
-local checkers = {
- [0] = "",
- "\\dosingleempty",
- "\\dodoubleempty",
- "\\dotripleempty",
- "\\doquadrupleempty",
- "\\doquintupleempty",
- "\\dosixtupleempty",
-}
+ local scanpeek = scanners.peek
+ local scankey = scanners.key
+ local scanvalue = scanners.value
+ local scanskip = scanners.skip
-function _clmm_(name,...)
- macros[name](...)
-end
+ local open = byte('[')
+ local close = byte(']')
+ local equal = byte('=')
+ local comma = byte(',')
-function _clmb_(name,...)
- local sn = stack[name]
- insert(sn,{...})
- starters[name](...)
-end
-
-function _clme_(name)
- local sn = stack[name]
- local sv = remove(sn)
- if sv then
- stoppers[name](unpack(sv))
- else
- -- nesting error
+ function scanhash(t)
+ if scanpeek() == open then
+ local data = { }
+ scanskip()
+ while true do
+ local c = scanpeek()
+ if c == comma then
+ scanskip()
+ elseif c == close then
+ scanskip()
+ break
+ else
+ local key = scankey(equal)
+ if key then
+ if scanpeek() == equal then
+ scanskip()
+ data[key] = scanvalue(comma,close) or ""
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ end
+ return data
+ end
end
-end
-_clmn_ = tonumber
+ function scanarray(t)
+ if scanpeek() == open then
+ local data = { }
+ local d = 0
+ scanskip()
+ while true do
+ local c = scanpeek()
+ if c == comma then
+ scanskip()
+ elseif c == close then
+ scanskip()
+ break
+ else
+ local v = scanvalue(comma,close) or ""
+ d = d + 1
+ data[d] = v
+ end
+ end
+ return data
+ end
+ end
-local estart = interfaces.elements.start
-local estop = interfaces.elements.stop
+ shortcuts.scanhash = scanhash
+ shortcuts.scanarray = scanarray
--- this is a bit old definition ... needs to be modernized
+ scanners.hash = scanhash
+ scanners.array = scanarray
-function interfaces.definecommand(name,specification) -- name is optional
- if type(name) == "table" then
- specification = name
- name = specification.name
+ local function remap(arguments)
+ -- backward compatibility
+ if type(arguments) == "table" then
+ for i=1,#arguments do
+ local a = arguments[i]
+ if type(a) == "table" then
+ local t = a[2]
+ arguments[i] = t == "list" and "array" or t
+ end
+ end
+ return arguments
+ end
end
- if name and specification then
- local arguments = specification.arguments
- local na = (arguments and #arguments) or 0
- local environment = specification.environment
- if na == 0 then
+
+ function interfaces.definecommand(name,specification) -- name is optional
+ if type(name) == "table" then
+ specification = name
+ name = specification.name
+ end
+ if name and specification then
+ local environment = specification.environment
+ local arguments = remap(specification.arguments)
if environment then
- contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{\\ctxlua{_clmb_('",name,"')}}")
- contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}")
+ local starter = specification.starter
+ local stopper = specification.stopper
+ if starter and stopper then
+ implement {
+ name = estart .. name,
+ arguments = arguments,
+ public = true,
+ protected = true,
+ actions = starter,
+ }
+ implement {
+ name = estop .. name,
+ public = true,
+ protected = true,
+ actions = stopper,
+ }
+ else
+ -- message
+ end
end
if not environment or environment == "both" then
- contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{\\ctxlua{_clmm_('",name,"')}}")
- end
- else
- -- we could flush immediate but tracing is bad then
- stack[name] = { }
- local opt = 0
- local done = false
- local snippets = { } -- we can reuse it
- local mkivdo = "\\mkivdo" .. name -- maybe clddo
- snippets[#snippets+1] = "\\def"
- snippets[#snippets+1] = mkivdo
- for i=1,na do
- local a = arguments[i]
- local variant = a[1]
- if variant == "option" then
- snippets[#snippets+1] = "[#"
- snippets[#snippets+1] = i
- snippets[#snippets+1] = "]"
- if not done then
- opt = opt + 1
- end
+ local macro = specification.macro
+ if macro then
+ implement {
+ name = name,
+ arguments = arguments,
+ public = true,
+ protected = true,
+ actions = macro,
+ }
else
- done = true -- no more optional checking after this
- snippets[#snippets+1] = "#"
- snippets[#snippets+1] = i
+ -- message
end
end
- if environment then
- snippets[#snippets+1] = "{\\ctxlua{_clmb_('"
- snippets[#snippets+1] = name
- snippets[#snippets+1] = "'"
+ else
+ -- message
+ end
+ end
+
+
+else
+
+ _clmh_ = utilities.parsers.settings_to_hash
+ _clma_ = utilities.parsers.settings_to_array
+
+ local starters, stoppers, macros, stack = { }, { }, { }, { }
+
+ local checkers = {
+ [0] = "",
+ "\\dosingleempty",
+ "\\dodoubleempty",
+ "\\dotripleempty",
+ "\\doquadrupleempty",
+ "\\doquintupleempty",
+ "\\dosixtupleempty",
+ }
+
+ function _clmm_(name,...)
+ macros[name](...)
+ end
+
+ function _clmb_(name,...)
+ local sn = stack[name]
+ insert(sn,{...})
+ starters[name](...)
+ end
+
+ function _clme_(name)
+ local sn = stack[name]
+ local sv = remove(sn)
+ if sv then
+ stoppers[name](unpack(sv))
+ else
+ -- nesting error
+ end
+ end
+
+ _clmn_ = tonumber
+
+ local estart = interfaces.elements.start
+ local estop = interfaces.elements.stop
+
+ -- this is a bit old definition ... needs to be modernized
+
+ function interfaces.definecommand(name,specification) -- name is optional
+ if type(name) == "table" then
+ specification = name
+ name = specification.name
+ end
+ if name and specification then
+ local arguments = specification.arguments
+ local na = (arguments and #arguments) or 0
+ local environment = specification.environment
+ if na == 0 then
+ if environment then
+ contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{\\ctxlua{_clmb_('",name,"')}}")
+ contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}")
+ end
+ if not environment or environment == "both" then
+ contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{\\ctxlua{_clmm_('",name,"')}}")
+ end
else
- snippets[#snippets+1] = "{\\ctxlua{_clmm_('"
- snippets[#snippets+1] = name
- snippets[#snippets+1] = "'"
- end
- for i=1,na do
- local a = arguments[i]
- local variant = a[2]
- if variant == "list" then
- snippets[#snippets+1] = ",_clma_([[#"
- snippets[#snippets+1] = i
- snippets[#snippets+1] = "]])"
- elseif variant == "hash" then
- snippets[#snippets+1] = ",_clmh_([[#"
- snippets[#snippets+1] = i
- snippets[#snippets+1] = "]])"
- elseif variant == "number" then
- snippets[#snippets+1] = ",_clmn_([[#"
- snippets[#snippets+1] = i
- snippets[#snippets+1] = "]])"
+ -- we could flush immediate but tracing is bad then
+ stack[name] = { }
+ local opt = 0
+ local done = false
+ local snippets = { } -- we can reuse it
+ local mkivdo = "\\mkivdo" .. name -- maybe clddo
+ snippets[#snippets+1] = "\\def"
+ snippets[#snippets+1] = mkivdo
+ for i=1,na do
+ local a = arguments[i]
+ local variant = a[1]
+ if variant == "option" then
+ snippets[#snippets+1] = "[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]"
+ if not done then
+ opt = opt + 1
+ end
+ else
+ done = true -- no more optional checking after this
+ snippets[#snippets+1] = "#"
+ snippets[#snippets+1] = i
+ end
+ end
+ if environment then
+ snippets[#snippets+1] = "{\\ctxlua{_clmb_('"
+ snippets[#snippets+1] = name
+ snippets[#snippets+1] = "'"
else
- snippets[#snippets+1] = ",[[#"
- snippets[#snippets+1] = i
- snippets[#snippets+1] = "]]"
+ snippets[#snippets+1] = "{\\ctxlua{_clmm_('"
+ snippets[#snippets+1] = name
+ snippets[#snippets+1] = "'"
+ end
+ for i=1,na do
+ local a = arguments[i]
+ local variant = a[2]
+ if variant == "list" then
+ snippets[#snippets+1] = ",_clma_([==[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]==])"
+ elseif variant == "hash" then
+ snippets[#snippets+1] = ",_clmh_([==[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]==])"
+ elseif variant == "number" then
+ snippets[#snippets+1] = ",_clmn_([==[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]==])"
+ else
+ snippets[#snippets+1] = ",[==[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]==]"
+ end
+ end
+ snippets[#snippets+1] = ")}}"
+ contextsprint(ctxcatcodes,unpack(snippets))
+ if environment then
+ -- needs checking
+ contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{",checkers[opt],mkivdo,"}")
+ contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}")
+ end
+ if not environment or environment == "both" then
+ contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{",checkers[opt],mkivdo,"}")
end
end
- snippets[#snippets+1] = ")}}"
- contextsprint(ctxcatcodes,unpack(snippets))
if environment then
- -- needs checking
- contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{",checkers[opt],mkivdo,"}")
- contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}")
- end
- if not environment or environment == "both" then
- contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{",checkers[opt],mkivdo,"}")
+ starters[name] = specification.starter
+ stoppers[name] = specification.stopper
+ else
+ macros[name] = specification.macro
end
end
- if environment then
- starters[name] = specification.starter
- stoppers[name] = specification.stopper
- else
- macros[name] = specification.macro
- end
end
+
end
function interfaces.tolist(t)
@@ -223,3 +366,20 @@ end
-- \stopluacode
--
-- more: \startmore[1] one \startmore[2] two \stopmore one \stopmore
+--
+-- More modern (no need for option or content):
+--
+-- \startluacode
+-- interfaces.definecommand {
+-- name = "test",
+-- arguments = {
+-- "array", -- or list
+-- "hash",
+-- "string",
+-- "number",
+-- },
+-- macro = test,
+-- }
+-- \stopluacode
+--
+
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 428ff4f95..bd131ddaf 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{2019.07.04 12:29}
+\newcontextversion{2019.07.16 18:23}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 26a46a8bc..bc9549d01 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{2019.07.04 12:29}
+\edef\contextversion{2019.07.16 18:23}
\edef\contextkind {beta}
%D Kind of special:
diff --git a/tex/context/base/mkiv/driv-ini.lua b/tex/context/base/mkiv/driv-ini.lua
index f3d62c778..a19ebb359 100644
--- a/tex/context/base/mkiv/driv-ini.lua
+++ b/tex/context/base/mkiv/driv-ini.lua
@@ -19,10 +19,20 @@ local report = logs.reporter("drivers")
local instances = { }
local helpers = { }
+local converters = { }
local prepared = { }
local wrappedup = { }
local cleanedup = { }
local currentdriver = "default"
+local currentinstance = nil
+
+local shipout = tex.shipout
+local texgetbox = tex.getbox
+local texgetcount = tex.getcount
+
+function converters.engine(driver,boxnumber,mode,number,specification)
+ return shipout(boxnumber)
+end
local prepare = nil
local convert = nil
@@ -33,7 +43,9 @@ local outputfilename = nil
drivers = drivers or {
instances = instances,
helpers = helpers,
+ converters = converters,
lmtxversion = 0.10,
+ report = report,
}
local dummy = function() end
@@ -65,26 +77,32 @@ function drivers.install(specification)
report("no flushers for driver %a",name)
return
end
- setmetatableindex(actions,defaulthandlers)
+ -- report("driver %a is installed",name)
+ setmetatableindex(actions, defaulthandlers)
+ setmetatableindex(flushers, function() return dummy end)
instances[name] = specification
end
function drivers.convert(boxnumber)
- callbacks.functions.start_page_number()
- starttiming(drivers)
- convert(boxnumber)
- stoptiming(drivers)
- callbacks.functions.stop_page_number()
+ if currentinstance then
+ callbacks.functions.start_page_number()
+ starttiming(drivers)
+ convert(currentinstance,boxnumber,texgetcount("realpageno"))
+ stoptiming(drivers)
+ callbacks.functions.stop_page_number()
+ end
end
function drivers.outputfilename()
- return outputfilename()
+ if currentinstance then
+ return outputfilename(currentinstance)
+ end
end
luatex.wrapup(function()
- if wrapup and not wrappedup[currentdriver] then
+ if currentinstance and wrapup and not wrappedup[currentdriver] then
starttiming(drivers)
- wrapup()
+ wrapup(currentinstance)
stoptiming(drivers)
wrappedup[currentdriver] = true
cleanedup[currentdriver] = true
@@ -92,9 +110,9 @@ luatex.wrapup(function()
end)
luatex.cleanup(function()
- if cleanup and not cleanedup[currentdriver] then
+ if currentinstance and cleanup and not cleanedup[currentdriver] then
starttiming(drivers)
- cleanup()
+ cleanup(currentinstance)
stoptiming(drivers)
wrappedup[currentdriver] = true
cleanedup[currentdriver] = true
@@ -102,19 +120,31 @@ luatex.cleanup(function()
end)
function drivers.enable(name)
- currentdriver = name or "default"
- local actions = instances[currentdriver].actions
- prepare = actions.prepare
- wrapup = actions.wrapup
- cleanup = actions.cleanup
- convert = actions.convert
- outputfilename = actions.outputfilename
- --
- if prepare and not prepared[currentdriver] then
- starttiming(drivers)
- prepare()
- stoptiming(drivers)
- prepared[currentdriver] = true
+ if name ~= currentdriver then
+ if currentinstance then
+ starttiming(drivers)
+ cleanup(currentinstance)
+ stoptiming(drivers)
+ end
+ currentdriver = name or "default"
+ currentinstance = instances[currentdriver]
+ if currentinstance then
+ local actions = currentinstance.actions
+ prepare = actions.prepare
+ wrapup = actions.wrapup
+ cleanup = actions.cleanup
+ convert = actions.convert
+ outputfilename = actions.outputfilename
+ --
+ if prepare and not prepared[currentdriver] then
+ starttiming(drivers)
+ prepare(currentinstance)
+ stoptiming(drivers)
+ prepared[currentdriver] = true
+ end
+ else
+ report("bad driver")
+ end
end
end
@@ -143,8 +173,8 @@ do
drivers.install {
name = "default",
actions = {
- convert = tex.shipout,
- outputfilename = function()
+ convert = drivers.converters.engine,
+ outputfilename = function(driver)
if not filename then
filename = addsuffix(tex.jobname,"pdf")
end
@@ -158,6 +188,41 @@ do
end
+-- No driver:
+
+do
+
+ drivers.install {
+ name = "none",
+ actions = { },
+ flushers = { },
+ }
+
+end
+
+do
+
+ local function prepare(driver)
+ converter = drivers.converters.lmtx
+ end
+
+ local function convert(driver,boxnumber,pagenumber)
+ converter(driver,texgetbox(boxnumber),"page",pagenumber)
+ end
+
+ drivers.install {
+ name = "empty",
+ actions = {
+ prepare = prepare,
+ convert = convert,
+ },
+ flushers = { },
+ }
+
+end
+
+--
+
setmetatableindex(instances,function() return instances.default end)
-- for now:
diff --git a/tex/context/base/mkiv/driv-shp.lua b/tex/context/base/mkiv/driv-shp.lua
index 19bc75f2a..980dda357 100644
--- a/tex/context/base/mkiv/driv-shp.lua
+++ b/tex/context/base/mkiv/driv-shp.lua
@@ -9,109 +9,111 @@ if not modules then modules = { } end modules ['driv-shp'] = {
local type, next = type, next
local round = math.round
-local setmetatableindex = table.setmetatableindex
-local formatters = string.formatters
-local concat = table.concat
-local keys = table.keys
-local sortedhash = table.sortedhash
-local splitstring = string.split
-local idiv = number.idiv
-local extract = bit32.extract
-local nuts = nodes.nuts
-
-local tonut = nodes.tonut
-local tonode = nodes.tonode
-
-local getdirection = nuts.getdirection
-local getlist = nuts.getlist
-local getoffsets = nuts.getoffsets
-local getorientation = nuts.getorientation
-local getfield = nuts.getfield
-local getwhd = nuts.getwhd
-local getkern = nuts.getkern
-local getheight = nuts.getheight
-local getdepth = nuts.getdepth
-local getwidth = nuts.getwidth
-local getnext = nuts.getnext
-local getsubtype = nuts.getsubtype
-local getid = nuts.getid
-local getleader = nuts.getleader
-local getglue = nuts.getglue
-local getshift = nuts.getshift
-local getdata = nuts.getdata
-local getboxglue = nuts.getboxglue
-local getexpansion = nuts.getexpansion
-
------ getall = node.direct.getall
-
-local setdirection = nuts.setdirection
-local setfield = nuts.setfield
-local setlink = nuts.setlink
-
-local isglyph = nuts.isglyph
-local findtail = nuts.tail
-local nextdir = nuts.traversers.dir
-local nextnode = nuts.traversers.node
-
-local rangedimensions = nuts.rangedimensions
-local effectiveglue = nuts.effective_glue
-
-local nodecodes = nodes.nodecodes
-local whatsitcodes = nodes.whatsitcodes
-local leadercodes = nodes.leadercodes
-local subtypes = nodes.subtypes
-
-local dircodes = nodes.dircodes
-local normaldir_code = dircodes.normal
-
-local dirvalues = nodes.dirvalues
-local lefttoright_code = dirvalues.lefttoright
-local righttoleft_code = dirvalues.righttoleft
-
-local glyph_code = nodecodes.glyph
-local kern_code = nodecodes.kern
-local glue_code = nodecodes.glue
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local dir_code = nodecodes.dir
-local disc_code = nodecodes.disc
-local math_code = nodecodes.math
-local rule_code = nodecodes.rule
-local marginkern_code = nodecodes.marginkern
-local whatsit_code = nodecodes.whatsit
-
-local leader_code = leadercodes.leader
-local cleader_code = leadercodes.cleader
-local xleader_code = leadercodes.xleader
-local gleader_code = leadercodes.gleader
-
-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 texget = tex.get
-
-local fonthashes = fonts.hashes
-local fontdata = fonthashes.identifiers
-local characters = fonthashes.characters
-local parameters = fonthashes.parameters
-
-local report = logs.reporter("drivers")
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+local concat = table.concat
+local keys = table.keys
+local sortedhash = table.sortedhash
+local splitstring = string.split
+local idiv = number.idiv
+local extract = bit32.extract
+local nuts = nodes.nuts
+
+local tonut = nodes.tonut
+local tonode = nodes.tonode
+
+local getdirection = nuts.getdirection
+local getlist = nuts.getlist
+local getoffsets = nuts.getoffsets
+local getorientation = nuts.getorientation
+local getfield = nuts.getfield
+local getwhd = nuts.getwhd
+local getkern = nuts.getkern
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
+local getwidth = nuts.getwidth
+local getnext = nuts.getnext
+local getsubtype = nuts.getsubtype
+local getid = nuts.getid
+local getleader = nuts.getleader
+local getglue = nuts.getglue
+local getshift = nuts.getshift
+local getdata = nuts.getdata
+local getboxglue = nuts.getboxglue
+local getexpansion = nuts.getexpansion
+local getreplace = nuts.getreplace
+local setreplace = nuts.setreplace
+
+local setdirection = nuts.setdirection
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+
+local isglyph = nuts.isglyph
+local findtail = nuts.tail
+local nextdir = nuts.traversers.dir
+local nextnode = nuts.traversers.node
+
+local rangedimensions = node.direct.naturalwidth or nuts.rangedimensions
+local effectiveglue = nuts.effective_glue
+
+local texget = tex.get
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local characters = fonthashes.characters
+local parameters = fonthashes.parameters
+
+local nodecodes = nodes.nodecodes
+local whatsitcodes = nodes.whatsitcodes
+local leadercodes = nodes.leadercodes
+local dircodes = nodes.dircodes
+local dirvalues = nodes.dirvalues
+local subtypes = nodes.subtypes
+
+local <const> normaldir_code = dircodes.normal
+
+local <const> lefttoright_code = dirvalues.lefttoright
+local <const> righttoleft_code = dirvalues.righttoleft
+
+local <const> glyph_code = nodecodes.glyph
+local <const> kern_code = nodecodes.kern
+local <const> glue_code = nodecodes.glue
+local <const> hlist_code = nodecodes.hlist
+local <const> vlist_code = nodecodes.vlist
+local <const> dir_code = nodecodes.dir
+local <const> disc_code = nodecodes.disc
+local <const> math_code = nodecodes.math
+local <const> rule_code = nodecodes.rule
+local <const> marginkern_code = nodecodes.marginkern
+local <const> whatsit_code = nodecodes.whatsit
+----- <const> penalty_code = nodecodes.penalty
+----- <const> boundary_code = nodecodes.boundary
+
+local <const> leaders_code = leadercodes.leaders
+local <const> cleaders_code = leadercodes.cleaders
+local <const> xleaders_code = leadercodes.xleaders
+local <const> gleaders_code = leadercodes.gleaders
+
+local <const> saveposwhatsit_code = whatsitcodes.savepos
+local <const> userdefinedwhatsit_code = whatsitcodes.userdefined
+local <const> openwhatsit_code = whatsitcodes.open
+local <const> writewhatsit_code = whatsitcodes.write
+local <const> closewhatsit_code = whatsitcodes.close
+local <const> lateluawhatsit_code = whatsitcodes.latelua
+local <const> literalwhatsit_code = whatsitcodes.literal
+local <const> setmatrixwhatsit_code = whatsitcodes.setmatrix
+local <const> savewhatsit_code = whatsitcodes.save
+local <const> restorewhatsit_code = whatsitcodes.restore
local getpagedimensions getpagedimensions = function()
getpagedimensions = backends.codeinjections.getpagedimensions
return getpagedimensions()
end
-local drivers = drivers
-local instances = drivers.instances
+local drivers = drivers
+local instances = drivers.instances
+
+local report = logs.reporter("drivers")
---------------------------------------------------------------------------------------
@@ -145,12 +147,12 @@ local pushorientation
local poporientation
local flushcharacter
local flushrule
-local flushpdfliteral
-local flushpdfsetmatrix
-local flushpdfsave
-local flushpdfrestore
+local flushliteral
+local flushsetmatrix
+local flushsave
+local flushrestore
local flushspecial
------ flushpdfimage
+----- flushimage
-- make local
@@ -158,15 +160,6 @@ function drivers.getpos () return round(pos_h), round(pos_v) end
function drivers.gethpos() return round(pos_h) end
function drivers.getvpos() return round(pos_v) end
--- local function synch_pos_with_cur(ref_h, ref_v, h, v)
--- if pos_r == righttoleft_code then
--- pos_h = ref_h - h
--- else
--- pos_h = ref_h + h
--- end
--- pos_v = ref_v - v
--- end
-
-- characters
local flush_character
@@ -261,7 +254,7 @@ local function flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommand
level = level - 1
end
elseif command == "pdf" then
- flushpdfliteral(false,pos_h,pos_v,packet[2],packet[3])
+ flushliteral(false,pos_h,pos_v,packet[2],packet[3])
elseif command == "rule" then
local size_v = packet[2]
local size_h = packet[3]
@@ -308,7 +301,6 @@ local function flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommand
pos_v = saved_v
pos_r = saved_r
- -- synch_pos_with_cur(ref_h, ref_v, pos_h,pos_v)
nesting = nesting - 1
end
@@ -436,34 +428,6 @@ end
local hlist_out, vlist_out do
- -- effective_glue :
- --
- -- local cur_g = 0
- -- local cur_glue = 0.0
- --
- -- local width, stretch, shrink, stretch_order, shrink_order = getglue(current)
- -- if g_sign == 1 then -- stretching
- -- if stretch_order == g_order then
- -- -- rule_wd = width - cur_g
- -- -- cur_glue = cur_glue + stretch
- -- -- cur_g = g_set * cur_glue
- -- -- rule_wd = rule_wd + cur_g
- -- rule_ht = width + g_set * stretch
- -- else
- -- rule_wd = width
- -- end
- -- else
- -- if shrink_order == g_order then
- -- -- rule_wd = width - cur_g
- -- -- cur_glue = cur_glue - shrink
- -- -- cur_g = g_set * cur_glue
- -- -- rule_wd = rule_wd + cur_g
- -- rule_ht = width - g_set * shrink
- -- else
- -- rule_wd = width
- -- end
- -- end
-
local function applyanchor(orientation,x,y,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset)
local ot = extract(orientation, 0,4)
local ay = extract(orientation, 4,4)
@@ -508,8 +472,6 @@ local hlist_out, vlist_out do
-- to be checked: begin- or enddir kan nil zijn, weird
- rangedimensions = node.direct.naturalwidth or rangedimensions
-
local function calculate_width_to_enddir(this_box,begindir) -- can be a helper
local dir_nest = 1
local enddir = begindir
@@ -545,9 +507,6 @@ local hlist_out, vlist_out do
local boxwidth,
boxheight,
boxdepth = getwhd(this_box)
- local g_set,
- g_order,
- g_sign = getboxglue(this_box)
local cur_h = 0
local cur_v = 0
@@ -556,12 +515,14 @@ local hlist_out, vlist_out do
current = getlist(this_box)
end
- while current do
- local char, id = isglyph(current)
- if char then
+ -- we can encounter localpar, boundary and penalty nodes but a special
+ -- iterator over content nodes won't save much
+
+ for current, id, subtype in nextnode, current do
+ if id == glyph_code then
+ local char, font = isglyph(current)
local x_offset, y_offset = getoffsets(current)
if x_offset ~= 0 or y_offset ~= 0 then
- -- synch_pos_with_cur(ref_h, ref_v, cur_h + x_offset, cur_v - y_offset)
if pos_r == righttoleft_code then
pos_h = ref_h - (cur_h + x_offset)
else
@@ -570,99 +531,98 @@ local hlist_out, vlist_out do
pos_v = ref_v - (cur_v - y_offset)
-- synced
end
- local wd, ht, dp = flush_character(current,id,char,false,true,pos_h,pos_v,pos_r)
+ local wd, ht, dp = flush_character(current,font,char,false,true,pos_h,pos_v,pos_r)
cur_h = cur_h + wd
elseif id == glue_code then
- local gluewidth
- if g_sign == 0 then
- gluewidth = getwidth(current)
- else
- gluewidth = effectiveglue(current,this_box)
- end
+ local gluewidth = effectiveglue(current,this_box)
if gluewidth ~= 0 then
- local leader = getleader(current)
- if leader then
- local width, height, depth = getwhd(leader)
- if getid(leader) == rule_code then
- if gluewidth > 0 then
- if height == running then
- height = boxheight
- end
- if depth == running then
- depth = boxdepth
+ if subtype >= leaders_code then
+ local leader = getleader(current)
+ if leader then
+ local width, height, depth = getwhd(leader)
+ if getid(leader) == rule_code then
+ if gluewidth > 0 then
+ if height == running then
+ height = boxheight
+ end
+ if depth == running then
+ depth = boxdepth
+ end
+ local total = height + depth
+ if total > 0 then
+ if pos_r == righttoleft_code then
+ pos_h = pos_h - gluewidth
+ end
+ pos_v = pos_v - depth
+ flushrule(leader,pos_h,pos_v,pos_r,gluewidth,total,getsubtype(leader))
+ end
+ cur_h = cur_h + gluewidth
end
- local total = height + depth
- if total > 0 then
+ elseif width > 0 and gluewidth > 0 then
+ local boxdir = getdirection(leader) or lefttoright_code
+ gluewidth = gluewidth + 10
+ local edge = cur_h + gluewidth
+ local lx = 0
+ -- local subtype = getsubtype(current)
+ if subtype == gleaders_code then
+ local save_h = cur_h
if pos_r == righttoleft_code then
- pos_h = pos_h - gluewidth
+ cur_h = ref_h - shipbox_h - cur_h
+ cur_h = width * (cur_h / width)
+ cur_h = ref_h - shipbox_h - cur_h
+ else
+ cur_h = cur_h + ref_h - shipbox_h
+ cur_h = width * (cur_h / width)
+ cur_h = cur_h - ref_h - shipbox_h
end
- pos_v = pos_v - depth
- flushrule(leader,pos_h,pos_v,pos_r,gluewidth,total)
- end
- cur_h = cur_h + gluewidth
- end
- elseif width > 0 and gluewidth > 0 then
- local boxdir = getdirection(leader) or lefttoright_code
- gluewidth = gluewidth + 10
- local edge = cur_h + gluewidth
- local lx = 0
- local subtype = getsubtype(current)
- if subtype == gleader_code then
- local save_h = cur_h
- if pos_r == righttoleft_code then
- cur_h = ref_h - shipbox_h - cur_h
+ if cur_h < save_h then
+ cur_h = cur_h + width
+ end
+ elseif subtype == leaders_code then
+ local save_h = cur_h
cur_h = width * (cur_h / width)
- cur_h = ref_h - shipbox_h - cur_h
+ if cur_h < save_h then
+ cur_h = cur_h + width
+ end
else
- cur_h = cur_h + ref_h - shipbox_h
- cur_h = width * (cur_h / width)
- cur_h = cur_h - ref_h - shipbox_h
- end
- if cur_h < save_h then
- cur_h = cur_h + width
+ lq = gluewidth / width
+ lr = gluewidth % width
+ if subtype == cleaders_code then
+ cur_h = cur_h + lr / 2
+ else
+ lx = lr / (lq + 1)
+ cur_h = cur_h + (lr - (lq - 1) * lx) / 2
+ end
end
- elseif subtype == leader_code then -- aleader ?
- local save_h = cur_h
- cur_h = width * (cur_h / width)
- if cur_h < save_h then
- cur_h = cur_h + width
+ local shift = getshift(leader)
+ while cur_h + width <= edge do
+ local basepoint_h = 0
+ -- local basepoint_v = shift
+ if boxdir ~= pos_r then
+ basepoint_h = boxwidth
+ end
+ -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h,shift)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - (cur_h + basepoint_h)
+ else
+ pos_h = ref_h + (cur_h + basepoint_h)
+ end
+ pos_v = ref_v - shift
+ -- synced
+ outer_doing_leaders = doing_leaders
+ doing_leaders = true
+ if getid(leader) == vlist_code then
+ vlist_out(leader)
+ else
+ hlist_out(leader)
+ end
+ doing_leaders = outer_doing_leaders
+ cur_h = cur_h + width + lx
end
+ cur_h = edge - 10
else
- lq = gluewidth / width
- lr = gluewidth % width
- if subtype == cleader_code then
- cur_h = cur_h + lr / 2
- else
- lx = lr / (lq + 1)
- cur_h = cur_h + (lr - (lq - 1) * lx) / 2
- end
- end
- local shift = getshift(leader)
- while cur_h + width <= edge do
- local basepoint_h = 0
- -- local basepoint_v = shift
- if boxdir ~= pos_r then
- basepoint_h = boxwidth
- end
- -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h,shift)
- if pos_r == righttoleft_code then
- pos_h = ref_h - (cur_h + basepoint_h)
- else
- pos_h = ref_h + (cur_h + basepoint_h)
- end
- pos_v = ref_v - shift
- -- synced
- outer_doing_leaders = doing_leaders
- doing_leaders = true
- if getid(leader) == vlist_code then
- vlist_out(leader)
- else
- hlist_out(leader)
- end
- doing_leaders = outer_doing_leaders
- cur_h = cur_h + width + lx
+ cur_h = cur_h + gluewidth
end
- cur_h = edge - 10
else
cur_h = cur_h + gluewidth
end
@@ -671,21 +631,14 @@ local hlist_out, vlist_out do
end
end
elseif id == hlist_code or id == vlist_code then
- -- w h d dir l, s, o = getall(current)
local boxdir = getdirection(current) or lefttoright_code
local width, height, depth = getwhd(current)
local list = getlist(current)
if list then
local shift, orientation = getshift(current)
if not orientation then
- --
- -- local width, height, depth, list, boxdir, shift, orientation = getall(current)
- -- if list then
- -- if not orientation then
- --
local basepoint_h = boxdir ~= pos_r and width or 0
-- local basepoint_v = shift
- -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h,shift)
if pos_r == righttoleft_code then
pos_h = ref_h - (cur_h + basepoint_h)
else
@@ -702,7 +655,6 @@ local hlist_out, vlist_out do
local orientation, xoffset, yoffset = getorientation(current)
local basepoint_h = boxdir ~= pos_r and width or 0
-- local basepoint_v = shift
- -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h + xoffset,shift - yoffset)
if pos_r == righttoleft_code then
pos_h = ref_h - (cur_h + basepoint_h + xoffset)
else
@@ -733,7 +685,6 @@ local hlist_out, vlist_out do
basepoint_v = basepoint_v - height
end
end
- -- synch_pos_with_cur(ref_h,ref_v,cur_h+basepoint_h,cur_v + basepoint_v)
if pos_r == righttoleft_code then
pos_h = ref_h - (cur_h + basepoint_h)
else
@@ -752,12 +703,12 @@ local hlist_out, vlist_out do
end
cur_h = cur_h + width
elseif id == disc_code then
- local replace = getfield(current,"replace")
- if replace and getsubtype(current) ~= select_disc then
+ local replace, tail = getreplace(current)
+ if replace and subtype ~= select_disc then
-- we could flatten .. no gain
- setlink(findtail(replace),getnext(current))
+ setlink(tail,getnext(current))
setlink(current,replace)
- setfield(current,"replace")
+ setreplace(current)
end
elseif id == kern_code then
local kern, factor = getkern(current,true)
@@ -769,7 +720,6 @@ local hlist_out, vlist_out do
end
end
elseif id == rule_code then
- -- w h d x y = getall(current)
local width, height, depth = getwhd(current)
if width > 0 then
if height == running then
@@ -794,19 +744,17 @@ local hlist_out, vlist_out do
xoffset = - xoffset
end
pos_v = pos_v - depth
- flushrule(current,pos_h + xoffset,pos_v + yoffset,pos_r,width,total)
+ flushrule(current,pos_h + xoffset,pos_v + yoffset,pos_r,width,total,subtype)
end
cur_h = cur_h + width
end
elseif id == math_code then
- local kern = getkern(current)
- if kern ~= 0 then
- cur_h = cur_h + kern
- elseif g_sign == 0 then
- cur_h = cur_h + getwidth(current)
- else
- cur_h = cur_h + effectiveglue(current,this_box)
- end
+ -- local kern = getkern(current)
+ -- if kern ~= 0 then
+ -- cur_h = cur_h + kern
+ -- else
+ cur_h = cur_h + effectiveglue(current,this_box)
+ -- end
elseif id == dir_code then
-- we normally have proper begin-end pairs
-- a begin without end is (silently) handled
@@ -834,7 +782,6 @@ local hlist_out, vlist_out do
ds.ref_v = ref_v
setdirection(enddir,pos_r)
end
- -- synch_pos_with_cur(ref_h,ref_v,cur_h,cur_v)
if pos_r == righttoleft_code then
pos_h = ref_h - cur_h
else
@@ -849,20 +796,19 @@ local hlist_out, vlist_out do
pos_r = dir
end
elseif id == whatsit_code then
- local subtype = getsubtype(current)
if subtype == literalwhatsit_code then
- flushpdfliteral(current,pos_h,pos_v)
+ flushliteral(current,pos_h,pos_v)
elseif subtype == lateluawhatsit_code then
flushlatelua(current,pos_h,pos_v,cur_h,cur_v)
elseif subtype == setmatrixwhatsit_code then
- flushpdfsetmatrix(current,pos_h,pos_v)
+ flushsetmatrix(current,pos_h,pos_v)
elseif subtype == savewhatsit_code then
- flushpdfsave(current,pos_h,pos_v)
+ flushsave(current,pos_h,pos_v)
elseif subtype == restorewhatsit_code then
- flushpdfrestore(current,pos_h,pos_v)
+ flushrestore(current,pos_h,pos_v)
elseif subtype == saveposwhatsit_code then
- last_position_x = pos_h -- or pdf_h
- last_position_y = pos_v -- or pdf_v
+ last_position_x = pos_h
+ last_position_y = pos_v
elseif subtype == writewhatsit_code then
flushwriteout(current)
elseif subtype == closewhatsit_code then
@@ -873,8 +819,6 @@ local hlist_out, vlist_out do
elseif id == marginkern_code then
cur_h = cur_h + getkern(current)
end
- current = getnext(current)
- -- synch_pos_with_cur(ref_h, ref_v, cur_h, cur_v) -- already done in list so skip
if pos_r == righttoleft_code then
pos_h = ref_h - cur_h
else
@@ -899,16 +843,12 @@ local hlist_out, vlist_out do
local boxwidth,
boxheight,
boxdepth = getwhd(this_box)
- local g_set,
- g_order,
- g_sign = getboxglue(this_box)
local cur_h = 0
local cur_v = - boxheight
local top_edge = cur_v
- -- synch_pos_with_cur(ref_h, ref_v, cur_h, cur_v)
if pos_r == righttoleft_code then
pos_h = ref_h - cur_h
else
@@ -925,104 +865,96 @@ local hlist_out, vlist_out do
-- local id = getid(current)
for current, id, subtype in nextnode, current do
if id == glue_code then
- local glueheight
- if g_sign == 0 then
- glueheight = getwidth(current)
- else
- glueheight = effectiveglue(current,this_box)
- end
- local leader = getleader(current)
- if leader then
- local width, height, depth = getwhd(leader)
- local total = height + depth
- if getid(leader) == rule_code then
- depth = 0 -- hm
- if total > 0 then
- if width == running then
- width = boxwidth
- end
- if width > 0 then
- if pos_r == righttoleft_code then
- cur_h = cur_h - width
- end
- flushrule(leader,pos_h,pos_v - total,pos_r,width,total)
- end
- cur_v = cur_v + total
- end
- else
- if total > 0 and glueheight > 0 then
- glueheight = glueheight + 10
- local edge = cur_v + glueheight
- local ly = 0
- if subtype == gleader_code then
- save_v = cur_v
- cur_v = ref_v - shipbox_v - cur_v
- cur_v = total * (cur_v / total)
- cur_v = ref_v - shipbox_v - cur_v
- if cur_v < save_v then
- cur_v = cur_v + total
- end
- elseif subtype == leader_code then -- aleader
- save_v = cur_v
- cur_v = top_edge + total * ((cur_v - top_edge) / total)
- if cur_v < save_v then
+ local glueheight = effectiveglue(current,this_box)
+ if glueheight ~= 0 then
+ if subtype >= leaders_code then
+ local leader = getleader(current)
+ if leader then
+ local width, height, depth = getwhd(leader)
+ local total = height + depth
+ if getid(leader) == rule_code then
+ depth = 0 -- hm
+ if total > 0 then
+ if width == running then
+ width = boxwidth
+ end
+ if width > 0 then
+ if pos_r == righttoleft_code then
+ cur_h = cur_h - width
+ end
+ flushrule(leader,pos_h,pos_v - total,pos_r,width,total,getsubtype(leader))
+ end
cur_v = cur_v + total
end
- else
- lq = glueheight / total
- lr = glueheight % total
- if subtype == cleaders_code then
- cur_v = cur_v + lr / 2
- else
- ly = lr / (lq + 1)
- cur_v = cur_v + (lr - (lq - 1) * ly) / 2
- end
- end
- local shift = getshift(leader)
- while cur_v + total <= edge do -- todo: <= edge - total
- -- synch_pos_with_cur(ref_h, ref_v, getshift(leader), cur_v + height)
- if pos_r == righttoleft_code then
- pos_h = ref_h - shift
+ elseif total > 0 and glueheight > 0 then
+ glueheight = glueheight + 10
+ local edge = cur_v + glueheight
+ local ly = 0
+ if subtype == gleaders_code then
+ save_v = cur_v
+ cur_v = ref_v - shipbox_v - cur_v
+ cur_v = total * (cur_v / total)
+ cur_v = ref_v - shipbox_v - cur_v
+ if cur_v < save_v then
+ cur_v = cur_v + total
+ end
+ elseif subtype == leaders_code then -- aleader
+ save_v = cur_v
+ cur_v = top_edge + total * ((cur_v - top_edge) / total)
+ if cur_v < save_v then
+ cur_v = cur_v + total
+ end
else
- pos_h = ref_h + shift
+ lq = glueheight / total
+ lr = glueheight % total
+ if subtype == cleaders_code then
+ cur_v = cur_v + lr / 2
+ else
+ ly = lr / (lq + 1)
+ cur_v = cur_v + (lr - (lq - 1) * ly) / 2
+ end
end
- pos_v = ref_v - (cur_v + height)
- -- synced
- outer_doing_leaders = doing_leaders
- doing_leaders = true
- if getid(leader) == vlist_code then
- vlist_out(leader)
- else
- hlist_out(leader)
+ local shift = getshift(leader)
+ while cur_v + total <= edge do -- todo: <= edge - total
+ -- synch_pos_with_cur(ref_h, ref_v, getshift(leader), cur_v + height)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - shift
+ else
+ pos_h = ref_h + shift
+ end
+ pos_v = ref_v - (cur_v + height)
+ -- synced
+ outer_doing_leaders = doing_leaders
+ doing_leaders = true
+ if getid(leader) == vlist_code then
+ vlist_out(leader)
+ else
+ hlist_out(leader)
+ end
+ doing_leaders = outer_doing_leaders
+ cur_v = cur_v + total + ly
end
- doing_leaders = outer_doing_leaders
- cur_v = cur_v + total + ly
+ cur_v = edge - 10
+ else
+ cur_v = cur_v + glueheight
end
- cur_v = edge - 10
- else
- cur_v = cur_v + glueheight
end
+ else
+ cur_v = cur_v + glueheight
end
- else
- cur_v = cur_v + glueheight
end
elseif id == hlist_code or id == vlist_code then
- -- w h d dir l, s, o = getall(current)
local boxdir = getdirection(current) or lefttoright_code
local width, height, depth = getwhd(current)
local list = getlist(current)
if list then
local shift, orientation = getshift(current)
if not orientation then
--- local width, height, depth, list, boxdir, shift, orientation = getall(current)
--- if list then
--- if not orientation then
-- local basepoint_h = shift
-- local basepoint_v = height
if boxdir ~= pos_r then
shift = shift + width
end
- -- synch_pos_with_cur(ref_h,ref_v,shift,cur_v + height)
if pos_r == righttoleft_code then
pos_h = ref_h - shift
else
@@ -1042,7 +974,6 @@ local hlist_out, vlist_out do
if boxdir ~= pos_r then
shift = shift + width
end
- -- synch_pos_with_cur(ref_h,ref_v,shift + xoffset,cur_v + height - yoffset)
if pos_r == righttoleft_code then
pos_h = ref_h - (shift + xoffset)
else
@@ -1067,7 +998,6 @@ local hlist_out, vlist_out do
elseif orientation == 3 then -- weird
basepoint_h = basepoint_h + height
end
- -- synch_pos_with_cur(ref_h,ref_v,basepoint_h,cur_v + basepoint_v)
if pos_r == righttoleft_code then
pos_h = ref_h - basepoint_h
else
@@ -1088,7 +1018,6 @@ local hlist_out, vlist_out do
elseif id == kern_code then
cur_v = cur_v + getkern(current)
elseif id == rule_code then
- -- w h d x y = getall(current)
local width, height, depth = getwhd(current)
local total = height + depth
if total > 0 then
@@ -1108,24 +1037,24 @@ local hlist_out, vlist_out do
cur_h = cur_h - width
xoffset = - xoffset
end
- flushrule(current,pos_h + xoffset,pos_v - total - yoffset,pos_r,width,total)
+ flushrule(current,pos_h + xoffset,pos_v - total - yoffset,pos_r,width,total,subtype)
end
cur_v = cur_v + total
end
elseif id == whatsit_code then
if subtype == literalwhatsit_code then
- flushpdfliteral(current,pos_h,pos_v)
+ flushliteral(current,pos_h,pos_v)
elseif subtype == lateluawhatsit_code then
flushlatelua(current,pos_h,pos_v,cur_h,cur_v)
elseif subtype == setmatrixwhatsit_code then
- flushpdfsetmatrix(current,pos_h,pos_v)
+ flushsetmatrix(current,pos_h,pos_v)
elseif subtype == savewhatsit_code then
- flushpdfsave(current,pos_h,pos_v)
+ flushsave(current,pos_h,pos_v)
elseif subtype == restorewhatsit_code then
- flushpdfrestore(current,pos_h,pos_v)
+ flushrestore(current,pos_h,pos_v)
elseif subtype == saveposwhatsit_code then
- last_position_x = pos_h -- or pdf_h
- last_position_y = pos_v -- or pdf_v
+ last_position_x = pos_h
+ last_position_y = pos_v
elseif subtype == writewhatsit_code then
flushwriteout(current)
elseif subtype == closewhatsit_code then
@@ -1134,7 +1063,6 @@ local hlist_out, vlist_out do
flushopenout(current)
end
end
- -- synch_pos_with_cur(ref_h, ref_v, cur_h, cur_v)
if pos_r == righttoleft_code then
pos_h = ref_h - cur_h
else
@@ -1150,19 +1078,17 @@ local hlist_out, vlist_out do
end
-function lpdf.convert(box,smode,objnum,specification) -- temp name
+function drivers.converters.lmtx(driver,box,smode,objnum,specification)
- if box then
- box = tonut(box)
- else
- report("error in converter, no box")
+ if not driver then
+ report("error in converter, no driver")
return
end
- local driver = instances.pdf
- if driver then
- -- tracing
+ if box then
+ box = tonut(box)
else
+ report("error in converter, no box")
return
end
@@ -1171,7 +1097,8 @@ function lpdf.convert(box,smode,objnum,specification) -- temp name
initialize = actions.initialize
finalize = actions.finalize
- updatefontstate = actions.updatefontstate
+
+ updatefontstate = flushers.updatefontstate
pushorientation = flushers.pushorientation
poporientation = flushers.poporientation
@@ -1180,17 +1107,19 @@ function lpdf.convert(box,smode,objnum,specification) -- temp name
flushrule = flushers.rule
flushsimplerule = flushers.simplerule
flushspecial = flushers.special
- flushpdfliteral = flushers.pdfliteral
- flushpdfsetmatrix = flushers.pdfsetmatrix
- flushpdfsave = flushers.pdfsave
- flushpdfrestore = flushers.pdfrestore
- -- flushpdfimage = flushers.pdfimage
+ flushliteral = flushers.literal
+ flushsetmatrix = flushers.setmatrix
+ flushsave = flushers.save
+ flushrestore = flushers.restore
+ -- flushimage = flushers.image
reset_dir_stack()
reset_state()
shippingmode = smode
+ local details = nil -- must be outside labels
+
local width, height, depth = getwhd(box)
local total = height + depth
@@ -1222,7 +1151,9 @@ function lpdf.convert(box,smode,objnum,specification) -- temp name
-- We have zero offsets in ConTeXt.
local pagewidth, pageheight = getpagedimensions()
- -- local h_offset_par, v_offset_par = texget("hoffset"), texget("voffset")
+
+ -- local h_offset_par = texget("hoffset")
+ -- local v_offset_par = texget("voffset")
-- page_h_origin = trueinch
-- page_v_origin = trueinch
@@ -1252,12 +1183,7 @@ function lpdf.convert(box,smode,objnum,specification) -- temp name
local refpoint_h = 0 -- + page_h_origin + h_offset_par
local refpoint_v = page_size_v -- - page_v_origin - v_offset_par
- -- synch_pos_with_cur(refpoint_h,refpoint_v,0,height)
- if pos_r == righttoleft_code then
- pos_h = refpoint_h
- else
- pos_h = refpoint_h
- end
+ pos_h = refpoint_h
pos_v = refpoint_v - height
-- synced
@@ -1276,12 +1202,16 @@ function lpdf.convert(box,smode,objnum,specification) -- temp name
shipbox_ref_h = pos_h
shipbox_ref_v = pos_v
- initialize {
- shippingmode = smode, -- target
- boundingbox = { 0, 0, page_size_h, page_size_v },
- objectnumber = objnum,
+ details = {
+ shippingmode = smode, -- target
+ boundingbox = { 0, 0, page_size_h, page_size_v },
+ objectnumber = smode ~= "page" and objnum or nil,
+ pagenumber = smode == "page" and objnum or nil,
+ specification = specification,
}
+ initialize(driver,details)
+
lastfont = nil -- this forces a sync each page / object
if getid(box) == vlist_code then
@@ -1292,7 +1222,8 @@ function lpdf.convert(box,smode,objnum,specification) -- temp name
::DONE::
- finalize(objnum,specification)
+ finalize(driver,details)
+
shippingmode = "none"
end
diff --git a/tex/context/base/mkiv/grph-inc.mkiv b/tex/context/base/mkiv/grph-inc.mkiv
index abf9d709a..83681580e 100644
--- a/tex/context/base/mkiv/grph-inc.mkiv
+++ b/tex/context/base/mkiv/grph-inc.mkiv
@@ -982,6 +982,10 @@
\unexpanded\def\inlinefigure[#1]{\dontleavehmode\sbox{\externalfigure[#1][\v!inline]}}
+%D Needs to be done global:
+
+\definelayer[epdfcontent]
+
\protect \endinput
%D Moved here because this already old code is nowhere documents (so I need to check
diff --git a/tex/context/base/mkiv/lpdf-eng.lua b/tex/context/base/mkiv/lpdf-eng.lua
index 6f2e75c46..42435fad5 100644
--- a/tex/context/base/mkiv/lpdf-eng.lua
+++ b/tex/context/base/mkiv/lpdf-eng.lua
@@ -63,7 +63,7 @@ img = table.setmetatableindex (
do
- local function prepare()
+ local function prepare(driver)
if not environment.initex then
-- install new functions in pdf namespace
updaters.apply("backend.update.pdf")
@@ -77,29 +77,23 @@ do
end
end
- local function outputfilename()
+ local function outputfilename(driver)
if not filename then
filename = addsuffix(tex.jobname,"pdf")
end
return filename
end
- function lpdf.flushers()
- return { }
- end
-
- function lpdf.actions()
- return {
- convert = tex.shipout,
- outputfilename = outputfilename,
- prepare = prepare,
- }
- end
-
drivers.install {
name = "pdf",
- flushers = lpdf.flushers(),
- actions = lpdf.actions(),
+ flushers = {
+ -- nothing here
+ },
+ actions = {
+ convert = drivers.converters.engine,
+ outputfilename = outputfilename,
+ prepare = prepare,
+ },
}
end
diff --git a/tex/context/base/mkiv/lpdf-epa.lua b/tex/context/base/mkiv/lpdf-epa.lua
index 7ec331554..45000aebc 100644
--- a/tex/context/base/mkiv/lpdf-epa.lua
+++ b/tex/context/base/mkiv/lpdf-epa.lua
@@ -72,7 +72,7 @@ local maxdimen = 0x3FFFFFFF -- 2^30-1
local bpfactor = number.dimenfactors.bp
-local layerspec = { -- predefining saves time
+local layerspec = {
"epdfcontent"
}
@@ -143,11 +143,18 @@ end
local layerused = false
+-- local function initializelayer(height,width)
+-- if not layerused then
+-- context.definelayer(layerspec, { height = height .. "bp", width = width .. "bp" })
+-- layerused = true
+-- end
+-- end
+
local function initializelayer(height,width)
- if not layerused then
- context.definelayer(layerspec, { height = height .. "bp", width = width .. "bp" })
+-- if not layerused then
+ context.setuplayer(layerspec, { height = height .. "bp", width = width .. "bp" })
layerused = true
- end
+-- end
end
function codeinjections.flushmergelayer()
diff --git a/tex/context/base/mkiv/lpdf-lmt.lua b/tex/context/base/mkiv/lpdf-lmt.lua
index 25a73fe67..8fdbf9a36 100644
--- a/tex/context/base/mkiv/lpdf-lmt.lua
+++ b/tex/context/base/mkiv/lpdf-lmt.lua
@@ -8,6 +8,15 @@ if not modules then modules = { } end modules ['lpdf-lmt'] = {
-- The code below was originally in back-lpd.lua but it makes more sense in
-- this namespace. I will rename variables.
+--
+-- There is no way that a lua based backend can compete with the original one
+-- for relative simple text runs. And we're talking seconds here on say 500
+-- pages with paragraphs alternativng between three fonts and colors. But such
+-- documents are rare so in practice we are quite okay, especially because in
+-- ConTeXt we can gain quite a bit elsewhere. So, when we loose 30% on such
+-- simple documents, we break even on for instance the manual, and gain 30% on
+-- Thomas's turture test (also for other reasons). But .. who knows what magic
+-- I can cook up in due time.
if CONTEXTLMTXMODE == 0 then
return
@@ -33,7 +42,7 @@ local band, extract = bit32.band, bit32.extract
local concat, sortedhash = table.concat, table.sortedhash
local setmetatableindex = table.setmetatableindex
-local bpfactor = number.dimenfactors.bp
+local <const> bpfactor = number.dimenfactors.bp
local md5HEX = md5.HEX
local osuuid = os.uuid
@@ -244,29 +253,20 @@ local function calc_pdfpos(h,v)
if mode == "page" then
cmtx = h - pdf_h
cmty = v - pdf_v
- if h ~= pdf_h or v ~= pdf_v then
- return true
- end
+ return h ~= pdf_h or v ~= pdf_v
elseif mode == "text" then
tmtx = h - saved_text_pos_h
tmty = v - saved_text_pos_v
- if h ~= pdf_h or v ~= pdf_v then
- return true
- end
+ return h ~= pdf_h or v ~= pdf_v
elseif horizontalmode then
tmty = v - saved_text_pos_v
tj_delta = cw - h -- + saved_chararray_pos_h
- if tj_delta ~= 0 or v ~= pdf_v then
- return true
- end
+ return tj_delta ~= 0 or v ~= pdf_v
else
tmtx = h - saved_text_pos_h
tj_delta = cw + v -- - saved_chararray_pos_v
- if tj_delta ~= 0 or h ~= pdf_h then
- return true
- end
+ return tj_delta ~= 0 or h ~= pdf_h
end
- return false
end
local function pdf_set_pos(h,v)
@@ -316,12 +316,14 @@ local function pdf_set_pos_temp(h,v)
end
end
+-- these dummy returns makes using them a bit faster
+
local function pdf_end_string_nl()
if mode == "char" then
end_charmode()
- end_chararray()
+ return end_chararray()
elseif mode == "chararray" then
- end_chararray()
+ return end_chararray()
end
end
@@ -329,13 +331,13 @@ local function pdf_goto_textmode()
if mode == "page" then
-- pdf_set_pos(0,0)
pdf_reset_pos()
- begin_text()
+ return begin_text()
elseif mode ~= "text" then
if mode == "char" then
end_charmode()
- end_chararray()
+ return end_chararray()
else -- if mode == "chararray" then
- end_chararray()
+ return end_chararray()
end
end
end
@@ -345,12 +347,12 @@ local function pdf_goto_pagemode()
if mode == "char" then
end_charmode()
end_chararray()
- end_text()
+ return end_text()
elseif mode == "chararray" then
end_chararray()
- end_text()
+ return end_text()
elseif mode == "text" then
- end_text()
+ return end_text()
end
end
end
@@ -411,6 +413,49 @@ local flushcharacter do
end
end
+ -- This only saves a little on hz because there we switch a lot of
+ -- instances.
+
+ -- local lastslant, lastextend, lastsqueeze, lastformat, lastsize, lastwidth, lastmode, lastused, lastfont
+ --
+ -- local function setup_fontparameters(font,factor,f,e)
+ -- if font ~= lastfont then
+ -- lastslant = (fontparameters.slantfactor or 0) / 1000
+ -- lastextend = (fontparameters.extendfactor or 1000) / 1000
+ -- lastsqueeze = (fontparameters.squeezefactor or 1000) / 1000
+ -- lastformat = fontproperties.format
+ -- lastsize = fontparameters.size * bpfactor
+ -- if format == "opentype" or format == "type1" then
+ -- lastsize = lastsize * 1000 / fontparameters.units -- can we avoid this ?
+ -- end
+ -- lastwidth = fontparameters.width
+ -- lastmode = fontparameters.mode
+ -- lastused = usedfonts[font] -- cache
+ -- lastfont = font
+ -- end
+ -- local expand = 1 + factor / 1000000
+ -- if e then
+ -- tmrx = expand * lastextend * e
+ -- else
+ -- tmrx = expand * lastextend
+ -- end
+ -- tmsy = lastslant
+ -- tmry = lastsqueeze
+ -- need_width = lastwidth
+ -- need_mode = lastmode
+ -- f_cur = lastfont
+ -- f_pdf = lastused
+ -- cur_factor = factor
+ -- cur_f = f
+ -- cur_e = e
+ -- tj_delta = 0
+ -- if f then
+ -- fs = lastsize * f
+ -- else
+ -- fs = lastsize
+ -- end
+ -- end
+
local f_width = formatters["%.6F w"]
local f_mode = formatters["%i Tr"]
local f_font = formatters["/F%i %.6F Tf"]
@@ -455,15 +500,23 @@ local flushcharacter do
cur_tmrx = tmrx
end
- local f_skip = formatters["%.1f"]
+ -- local f_skip = formatters["%.1f"]
-- local f_octal = formatters["\\%o"]
-- local f_char = formatters["%c"]
local f_hex = formatters["%04X"]
local h_hex = setmetatableindex(function(t,k) -- we already have this somewhere
- local v = f_hex(k)
- t[k] = v
- return v
+ if k < 256 then
+ -- not sparse in this range
+ for i=0,255 do
+ t[i] = f_hex(i)
+ end
+ return t[k]
+ else
+ local v = f_hex(k)
+ t[k] = v
+ return v
+ end
end)
flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,naturalwidth,factor,width,f,e)
@@ -535,7 +588,9 @@ local flushcharacter do
cw = cw + naturalwidth
+if not pdfcharacters[index] then
pdfcharacters[index] = true
+end
end
@@ -543,20 +598,19 @@ end
-- literals
-local flushpdfliteral do
+local flushliteral do
- local literalvalues = nodes.literalvalues
+ local <const> nodeproperties = nodes.properties.data
+ local <const> literalvalues = nodes.literalvalues
- local originliteral_code = literalvalues.origin
- local pageliteral_code = literalvalues.page
- local alwaysliteral_code = literalvalues.always
- local rawliteral_code = literalvalues.raw
- local textliteral_code = literalvalues.text
- local fontliteral_code = literalvalues.font
+ local <const> originliteral_code = literalvalues.origin
+ local <const> pageliteral_code = literalvalues.page
+ local <const> alwaysliteral_code = literalvalues.always
+ local <const> rawliteral_code = literalvalues.raw
+ local <const> textliteral_code = literalvalues.text
+ local <const> fontliteral_code = literalvalues.font
- local nodeproperties = nodes.properties.data
-
- flushpdfliteral = function(current,pos_h,pos_v,mode,str)
+ flushliteral = function(current,pos_h,pos_v,mode,str)
if mode then
if not str then
mode, str = originliteral_code, mode
@@ -650,7 +704,7 @@ end
-- grouping & orientation
-local flushpdfsave, flushpdfrestore, flushpdfsetmatrix do
+local flushsave, flushrestore, flushsetmatrix do
local matrices = { }
local positions = { }
@@ -659,7 +713,7 @@ local flushpdfsave, flushpdfrestore, flushpdfsetmatrix do
local f_matrix = formatters["%s 0 0 cm"]
- flushpdfsave = function(current,pos_h,pos_v)
+ flushsave = function(current,pos_h,pos_v)
nofpositions = nofpositions + 1
positions[nofpositions] = { pos_h, pos_v, nofmatrices }
pdf_goto_pagemode()
@@ -667,7 +721,7 @@ local flushpdfsave, flushpdfrestore, flushpdfsetmatrix do
b = b + 1 ; buffer[b] = "q"
end
- flushpdfrestore = function(current,pos_h,pos_v)
+ flushrestore = function(current,pos_h,pos_v)
if nofpositions < 1 then
return
end
@@ -705,7 +759,7 @@ local flushpdfsave, flushpdfrestore, flushpdfsetmatrix do
local nodeproperties = nodes.properties.data
- flushpdfsetmatrix = function(current,pos_h,pos_v)
+ flushsetmatrix = function(current,pos_h,pos_v)
local str
if type(current) == "string" then
str = current
@@ -766,44 +820,45 @@ local flushpdfsave, flushpdfrestore, flushpdfsetmatrix do
end
-- pushorientation = function(orientation,pos_h,pos_v,pos_r)
--- flushpdfsave(false,pos_h,pos_v)
+-- flushsave(false,pos_h,pos_v)
-- if orientation == 1 then
--- flushpdfsetmatrix("0 -1 1 0",pos_h,pos_v)
+-- flushsetmatrix("0 -1 1 0",pos_h,pos_v)
-- elseif orientation == 2 then
--- flushpdfsetmatrix("-1 0 0 -1",pos_h,pos_v)
+-- flushsetmatrix("-1 0 0 -1",pos_h,pos_v)
-- elseif orientation == 3 then
--- flushpdfsetmatrix("0 1 -1 0",pos_h,pos_v)
+-- flushsetmatrix("0 1 -1 0",pos_h,pos_v)
-- end
-- end
-- poporientation = function(orientation,pos_h,pos_v,pos_r)
--- flushpdfrestore(false,pos_h,pos_v)
+-- flushrestore(false,pos_h,pos_v)
-- end
end
-- rules
-local flushedxforms = { } -- actually box resources but can also be direct
+local flushedxforms = { } -- actually box resources but can also be direct
+local localconverter = nil -- will be set
-local flushrule, flushsimplerule, flushpdfimage do
+local flushrule, flushsimplerule, flushimage do
- local rulecodes = nodes.rulecodes
- local newrule = nodes.pool.rule
+ local rulecodes = nodes.rulecodes
+ local newrule = nodes.pool.rule
- local setprop = nuts.setprop
- local getprop = nuts.getprop
+ local setprop = nuts.setprop
+ local getprop = nuts.getprop
- local normalrule_code = rulecodes.normal
- local boxrule_code = rulecodes.box
- local imagerule_code = rulecodes.image
- local emptyrule_code = rulecodes.empty
- local userrule_code = rulecodes.user
- local overrule_code = rulecodes.over
- local underrule_code = rulecodes.under
- local fractionrule_code = rulecodes.fraction
- local radicalrule_code = rulecodes.radical
- local outlinerule_code = rulecodes.outline
+ local <const> normalrule_code = rulecodes.normal
+ local <const> boxrule_code = rulecodes.box
+ local <const> imagerule_code = rulecodes.image
+ local <const> emptyrule_code = rulecodes.empty
+ local <const> userrule_code = rulecodes.user
+ local <const> overrule_code = rulecodes.over
+ local <const> underrule_code = rulecodes.under
+ local <const> fractionrule_code = rulecodes.fraction
+ local <const> radicalrule_code = rulecodes.radical
+ local <const> outlinerule_code = rulecodes.outline
local rule_callback = callbacks.functions.process_rule
@@ -869,7 +924,7 @@ local flushrule, flushsimplerule, flushpdfimage do
}
boxresources[objnum] = l
if immediate then
- lpdf.convert(list,"xform",objnum,l)
+ localconverter(list,"xform",objnum,l)
flushedxforms[objnum] = { true , objnum }
flushlist(list)
else
@@ -959,13 +1014,13 @@ local flushrule, flushsimplerule, flushpdfimage do
-- place image also used in vf but we can use a different one if
-- we need it
- local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream
- local img_none = imagetypes.none
- local img_pdf = imagetypes.pdf
- local img_stream = imagetypes.stream
- local img_memstream = imagetypes.memstream
+ local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream
+ local img_none = imagetypes.none
+ local img_pdf = imagetypes.pdf
+ local img_stream = imagetypes.stream
+ local img_memstream = imagetypes.memstream
- local one_bp = 65536 * bpfactor
+ local <const> one_bp = 65536 * bpfactor
local imageresources, n = { }, 0
@@ -1085,7 +1140,7 @@ local flushrule, flushsimplerule, flushpdfimage do
b = b + 1 ; buffer[b] = s_e
end
- flushpdfimage = function(index,width,height,depth,pos_h,pos_v)
+ flushimage = function(index,width,height,depth,pos_h,pos_v)
-- used in vf characters
@@ -1122,9 +1177,8 @@ local flushrule, flushsimplerule, flushpdfimage do
-- For the moment we need this hack because the engine checks the 'image'
-- command in virtual fonts (so we use lua instead).
- flushrule = function(current,pos_h,pos_v,pos_r,size_h,size_v)
+ flushrule = function(current,pos_h,pos_v,pos_r,size_h,size_v,subtype)
- local subtype = getsubtype(current)
if subtype == emptyrule_code then
return
elseif subtype == boxrule_code then
@@ -1222,7 +1276,7 @@ local wrapup, registerpage do
}
end
- wrapup = function()
+ wrapup = function(driver)
-- hook (to reshuffle pages)
local pagetree = { }
@@ -1300,8 +1354,8 @@ end
pdf_h, pdf_v = 0, 0
-local function initialize(specification)
- reset_variables(specification)
+local function initialize(driver,details)
+ reset_variables(details)
reset_buffer()
end
@@ -1316,12 +1370,15 @@ local f_image = formatters["Im%d"]
local pushmode, popmode
-local function finalize(objnum,specification)
+local function finalize(driver,details)
pushmode()
pdf_goto_pagemode() -- for now
+ local objnum = details.objnum
+ local specification = details.specification
+
local content = concat(buffer,"\n",1,b)
local fonts = nil
@@ -1391,7 +1448,9 @@ local function finalize(objnum,specification)
local margin = specification.margin or 0
local attributes = specification.attributes or ""
local resources = specification.resources or ""
+
local wrapper = nil
+
if xformtype == 0 then
wrapper = pdfdictionary {
Type = pdf_xobject,
@@ -1451,7 +1510,7 @@ local function finalize(objnum,specification)
local objnum = f[2] -- specification.objnum
local specification = boxresources[objnum]
local list = specification.list
- lpdf.convert(list,"xform",f[2],specification)
+ localconverter(list,"xform",f[2],specification)
end
end
@@ -1487,7 +1546,7 @@ local streams = { } -- maybe just parallel to objects (no holes)
local nofobjects = 0
local offset = 0
local f = false
-local flush = false
+----- flush = false
local threshold = 40 -- also #("/Filter /FlateDecode")
local objectstream = true
local compress = true
@@ -1563,13 +1622,14 @@ end
local addtocache, flushcache, cache do
- local data, d = { }, 0
- local list, l = { }, 0
- local coffset = 0
- local maxsize = 32 * 1024 -- uncompressed
- local maxcount = 0xFF
+ local data, d = { }, 0
+ local list, l = { }, 0
+ local coffset = 0
local indices = { }
+ local <const> maxsize = 32 * 1024 -- uncompressed
+ local <const> maxcount = 0xFF
+
addtocache = function(n,str)
local size = #str
if size == 0 then
@@ -1621,9 +1681,9 @@ local addtocache, flushcache, cache do
else
b = f_stream_b_d_u(cache,strobj(),#data)
end
- flush(f,b)
- flush(f,data)
- flush(f,e)
+ f:write(b)
+ f:write(data)
+ f:write(e)
offset = offset + #b + #data + #e
data, d = { }, 0
list, l = { }, 0
@@ -1663,7 +1723,7 @@ local function flushnormalobj(data,n)
if level == 0 then
objects[n] = offset
offset = offset + #data
- flush(f,data)
+ f:write(data)
else
if not lastdeferred then
lastdeferred = n
@@ -1706,9 +1766,9 @@ local function flushstreamobj(data,n,dict,comp,nolength)
else
b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size)
end
- flush(f,b)
- flush(f,data)
- flush(f,e)
+ f:write(b)
+ f:write(data)
+ f:write(e)
objects[n] = offset
offset = offset + #b + #data + #e
else
@@ -1746,7 +1806,7 @@ local function flushdeferred()
if type(o) == "string" then
objects[n] = offset
offset = offset + #o
- flush(f,o)
+ f:write(o)
end
end
lastdeferred = false
@@ -1865,6 +1925,14 @@ updaters.register("backend.update.pdf",function()
pdf.immediateobj = obj
end)
+-- Bah, in lua 5.4 we cannot longer use flush = getmetatable(f).write as efficient
+-- flusher due to some change in the metatable definitions (more indirectness) ...
+-- so maybe we should introduce our own helper for this as now we get a lookup for
+-- each write (and writing isn't already the fastest). A little Lua charm gone as
+-- now the memory variant also needs to use this 'object' model. (Ok, the <const>
+-- is a new charm but for that to work in our advance I need to patch quite some
+-- files.)
+
local openfile, closefile do
local f_used = formatters["%010i 00000 n \010"]
@@ -1878,34 +1946,45 @@ local openfile, closefile do
local inmemory = false
-- local inmemory = environment.arguments.inmemory
- local close = nil
+ -- local close = nil
openfile = function(filename)
if inmemory then
- f = { }
+ -- local n = 0
+ -- f = { }
+ -- flush = function(f,s)
+ -- n = n + 1 f[n] = s
+ -- end
+ -- close = function(f)
+ -- f = concat(f)
+ -- io.savedata(filename,f)
+ -- f = false
+ -- end
local n = 0
- flush = function(f,s)
- n = n + 1 f[n] = s
- end
- close = function(f)
- f = concat(f)
- io.savedata(filename,f)
- f = false
- end
- else
+ f = {
+ write = function(self,s)
+ n = n + 1 f[n] = s
+ end,
+ close = function(self)
+ f = concat(f)
+ io.savedata(filename,f)
+ f = false
+ end,
+ }
+ else
f = io.open(filename,"wb")
if not f then
-- message
os.exit()
end
- flush = getmetatable(f).write
- close = getmetatable(f).close
+ -- flush = getmetatable(f).write
+ -- close = getmetatable(f).close
end
local v = f_pdf(majorversion,minorversion)
-- local b = "%\xCC\xD5\xC1\xD4\xC5\xD8\xD0\xC4\xC6\010" -- LUATEXPDF (+128)
local b = "%\xC3\xCF\xCE\xD4\xC5\xD8\xD4\xD0\xC4\xC6\010" -- CONTEXTPDF (+128)
- flush(f,v)
- flush(f,b)
+ f:write(v)
+ f:write(b)
offset = #v + #b
end
@@ -2051,20 +2130,20 @@ local openfile, closefile do
local comp = zlibcompress(data,3)
if comp then
data = comp
- flush(f,f_stream_b_d_c(nofobjects,xref(),#data))
+ f:write(f_stream_b_d_c(nofobjects,xref(),#data))
else
- flush(f,f_stream_b_d_u(nofobjects,xref(),#data))
+ f:write(f_stream_b_d_u(nofobjects,xref(),#data))
end
else
- flush(f,f_stream_b_d_u(nofobjects,xref(),#data))
+ f:write(f_stream_b_d_u(nofobjects,xref(),#data))
end
- flush(f,data)
- flush(f,s_stream_e)
- flush(f,f_startxref(xrefoffset))
+ f:write(data)
+ f:write(s_stream_e)
+ f:write(f_startxref(xrefoffset))
else
flushdeferred()
xrefoffset = offset
- flush(f,f_xref(nofobjects+1))
+ f:write(f_xref(nofobjects+1))
local trailer = pdfdictionary {
Size = nofobjects+1,
Root = catalog,
@@ -2084,16 +2163,16 @@ local openfile, closefile do
end
end
objects[0] = f_first(lastfree)
- flush(f,concat(objects,"",0,nofobjects))
+ f:write(concat(objects,"",0,nofobjects))
trailer.Size = nofobjects + 1
if trailerid then
- flush(f,f_trailer_id(trailer(),trailerid,trailerid,xrefoffset))
+ f:write(f_trailer_id(trailer(),trailerid,trailerid,xrefoffset))
else
- flush(f,f_trailer_no(trailer(),xrefoffset))
+ f:write(f_trailer_no(trailer(),xrefoffset))
end
end
end
- close(f)
+ f:close()
io.flush()
end
@@ -2114,7 +2193,6 @@ updaters.register("backend.update.pdf",function()
local img_none = imagetypes.none
local rulecodes = nodes.rulecodes
- local imagerule_code = rulecodes.image
local setprop = nodes.nuts.setprop
@@ -2123,7 +2201,8 @@ updaters.register("backend.update.pdf",function()
local lastindex = 0
local indices = { }
- local bpfactor = number.dimenfactors.bp
+ local <const> bpfactor = number.dimenfactors.bp
+ local <const> imagerule_code = rulecodes.image
function codeinjections.newimage(specification)
return specification
@@ -2287,7 +2366,7 @@ updaters.register("backend.update.lpdf",function()
topdf[id] = index
end
-- pdf.print or pdf.literal
- flushpdfimage(index,wd,ht,dp,pos_h,pos_v)
+ flushimage(index,wd,ht,dp,pos_h,pos_v)
end
local function pdfvfimage(wd,ht,dp,data,name)
@@ -2310,15 +2389,20 @@ do
local renamefile = os.rename
-- local copyfile = file.copy
-- local addsuffix = file.addsuffix
+ local texgetbox = tex.getbox
local pdfname = nil
local tmpname = nil
+ local converter = nil
+ local useddriver = nil -- a bit of a hack
- local function outputfilename()
+ local function outputfilename(driver)
return pdfname
end
- local function prepare()
+ -- todo: prevent twice
+
+ local function prepare(driver)
if not environment.initex then
-- install new functions in pdf namespace
updaters.apply("backend.update.pdf")
@@ -2343,21 +2427,29 @@ do
openfile(tmpname)
--
luatex.registerstopactions(1,function()
- lpdf.finalizedocument()
- closefile()
+ if pdfname then
+ lpdf.finalizedocument()
+ closefile()
+ end
end)
--
luatex.registerpageactions(1,function()
- lpdf.finalizepage(true)
+ if pdfname then
+ lpdf.finalizepage(true)
+ end
end)
-- --
lpdf.registerdocumentfinalizer(wrapup,nil,"wrapping up")
+ --
end
--
environment.lmtxmode = CONTEXTLMTXMODE
+ --
+ converter = drivers.converters.lmtx
+ useddriver = driver
end
- local function wrapup()
+ local function wrapup(driver)
if pdfname then
local ok = true
if isfile(pdfname) then
@@ -2380,7 +2472,7 @@ do
end
end
- local function cleanup()
+ local function cleanup(driver)
if tmpname then
closefile(true)
if isfile(tmpname) then
@@ -2391,44 +2483,42 @@ do
end
end
- local function convert(boxnumber)
- lpdf.convert(tex.box[boxnumber],"page")
+ local function convert(driver,boxnumber)
+ converter(driver,texgetbox(boxnumber),"page")
+ end
+
+ localconverter = function(...)
+ converter(useddriver,...)
end
- function lpdf.flushers()
- return {
+ drivers.install {
+ name = "pdf",
+ flushers = {
character = flushcharacter,
rule = flushrule,
simplerule = flushsimplerule,
pushorientation = pushorientation,
poporientation = poporientation,
--
- pdfliteral = flushpdfliteral,
- pdfsetmatrix = flushpdfsetmatrix,
- pdfsave = flushpdfsave,
- pdfrestore = flushpdfrestore,
- pdfimage = flushpdfimage,
- }
- end
-
- function lpdf.actions()
- return {
+ literal = flushliteral,
+ setmatrix = flushsetmatrix,
+ save = flushsave,
+ restore = flushrestore,
+ image = flushimage,
+ --
+ updatefontstate = updatefontstate,
+ },
+ actions = {
prepare = prepare,
wrapup = wrapup,
- convert = convert,
cleanup = cleanup,
--
initialize = initialize,
+ convert = convert,
finalize = finalize,
- updatefontstate = updatefontstate,
+ --
outputfilename = outputfilename,
- }
- end
-
- drivers.install {
- name = "pdf",
- flushers = lpdf.flushers(),
- actions = lpdf.actions(),
+ },
}
end
diff --git a/tex/context/base/mkiv/lpdf-mis.lua b/tex/context/base/mkiv/lpdf-mis.lua
index 0f51ea4f6..c5422b49e 100644
--- a/tex/context/base/mkiv/lpdf-mis.lua
+++ b/tex/context/base/mkiv/lpdf-mis.lua
@@ -196,6 +196,10 @@ function codeinjections.setupidentity(specification)
end
end
+function codeinjections.getidentityvariable(name)
+ return identity[name]
+end
+
local done = false -- using "setupidentity = function() end" fails as the meaning is frozen in register
local function setupidentity()
diff --git a/tex/context/base/mkiv/luat-cnf.lua b/tex/context/base/mkiv/luat-cnf.lua
index c398b75bb..88e7a7353 100644
--- a/tex/context/base/mkiv/luat-cnf.lua
+++ b/tex/context/base/mkiv/luat-cnf.lua
@@ -104,7 +104,7 @@ function texconfig.init()
local tv = type(gv)
if tv == "table" then
for k, v in next, gv do
- keys[k] = tostring(v) -- true -- by tostring we cannot call overloades functions (security)
+ keys[k] = tostring(v) -- true -- by tostring we cannot call overloads functions (security)
end
end
lib[v] = keys
diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua
index 4ec3bd7c2..5222ea84f 100644
--- a/tex/context/base/mkiv/mult-def.lua
+++ b/tex/context/base/mkiv/mult-def.lua
@@ -7340,6 +7340,12 @@ return {
["compressdistance"]={
["en"]="compressdistance",
},
+ ["compressmethod"]={
+ ["en"]="compressmethod",
+ },
+ ["compressstopper"]={
+ ["en"]="compressstopper",
+ },
["concerns"]={
["en"]="concerns",
["nl"]="betreft",
@@ -13122,6 +13128,9 @@ return {
["compressseparator"]={
["en"]="compressseparator",
},
+ ["compressstopper"]={
+ ["en"]="compressstopper",
+ },
["concept"]={
["cs"]="koncept",
["de"]="konzept",
@@ -16108,6 +16117,10 @@ return {
["selectfont"]={
["en"]="selectfont",
},
+ ["separator"]={
+ ["en"]="separator",
+ ["nl"]="scheider",
+ },
["september"]={
["cs"]="zari",
["de"]="september",
diff --git a/tex/context/base/mkiv/mult-def.mkiv b/tex/context/base/mkiv/mult-def.mkiv
index d9404bc16..78fcdf667 100644
--- a/tex/context/base/mkiv/mult-def.mkiv
+++ b/tex/context/base/mkiv/mult-def.mkiv
@@ -37,9 +37,9 @@
% some left-overs
-\def\c!HL {HL}
-\def\c!VL {VL}
-\def\c!NL {NL}
+\def\c!HL{HL}
+\def\c!VL{VL}
+\def\c!NL{NL}
% stop todo
diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua
index 2770db21f..5cd5fb373 100644
--- a/tex/context/base/mkiv/mult-prm.lua
+++ b/tex/context/base/mkiv/mult-prm.lua
@@ -254,6 +254,7 @@ return {
"fixupboxesmode",
"fontid",
"formatname",
+ "frozen",
"futureexpand",
"futureexpandis",
"gleaders",
diff --git a/tex/context/base/mkiv/node-fin.lua b/tex/context/base/mkiv/node-fin.lua
index dc681d165..5f2940f45 100644
--- a/tex/context/base/mkiv/node-fin.lua
+++ b/tex/context/base/mkiv/node-fin.lua
@@ -25,6 +25,7 @@ local getattr = nuts.getattr
local getwidth = nuts.getwidth
local getwhd = nuts.getwhd
local getorientation = nuts.getorientation
+local has_dimensions = nuts.has_dimensions
local setlist = nuts.setlist
local setleader = nuts.setleader
@@ -182,7 +183,7 @@ local function process(attribute,head,inheritance,default) -- one attribute
local leader = nil
for stack, id in nextnode, head do
if id == glyph_code or id == disc_code then
- check = true -- disc no longer needed as we flatten replace
+ check = true
elseif id == glue_code then
leader = getleader(stack)
if leader then
@@ -235,8 +236,7 @@ local function process(attribute,head,inheritance,default) -- one attribute
-- end nested --
end
elseif id == rule_code then
- local wd, ht, dp = getwhd(stack)
- check = wd ~= 0 or (ht+dp) ~= 0
+ check = has_dimensions(stack)
end
-- much faster this way than using a check() and nested() function
if check then
@@ -309,7 +309,7 @@ local function selective(attribute,head,inheritance,default) -- two attributes
local leader = nil
for stack, id, subtype in nextnode, head do
if id == glyph_code or id == disc_code then
- check = true -- disc no longer needed as we flatten replace
+ check = true
elseif id == glue_code then
leader = getleader(stack)
if leader then
@@ -374,8 +374,7 @@ local function selective(attribute,head,inheritance,default) -- two attributes
-- so no redundant color stuff (only here, layers for instance should obey)
check = false
else
- local wd, ht, dp = getwhd(stack)
- check = wd ~= 0 or (ht+dp) ~= 0
+ check = has_dimensions(stack)
end
end
if check then
@@ -485,8 +484,7 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance,
end
end
elseif id == rule_code then
- local wd, ht, dp = getwhd(stack)
- check = wd ~= 0 or (ht+dp) ~= 0
+ check = has_dimensions(stack)
end
if check then
local a = getattr(stack,attribute)
@@ -571,8 +569,7 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance,
end
end
elseif id == rule_code then
- local wd, ht, dp = getwhd(current)
- check = wd ~= 0 or (ht+dp) ~= 0
+ check = has_dimensions(current)
end
if check then
diff --git a/tex/context/base/mkiv/node-fnt.lua b/tex/context/base/mkiv/node-fnt.lua
index 25254009f..1b245639b 100644
--- a/tex/context/base/mkiv/node-fnt.lua
+++ b/tex/context/base/mkiv/node-fnt.lua
@@ -210,12 +210,12 @@ do
local usedfonts
local attrfonts
- local basefonts
+ local basefonts -- could be reused
local basefont
local prevfont
local prevattr
local variants
- local redundant
+ local redundant -- could be reused
local firstnone
local lastfont
local lastproc
diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua
index b097fb8b1..f3877d5c9 100644
--- a/tex/context/base/mkiv/node-nut.lua
+++ b/tex/context/base/mkiv/node-nut.lua
@@ -203,6 +203,7 @@ nuts.vpack = direct.vpack
nuts.writable_spec = direct.writable_spec
nuts.write = direct.write
nuts.mlist_to_hlist = direct.mlist_to_hlist
+nuts.has_dimensions = direct.has_dimensions
if not nuts.mlist_to_hlist then
@@ -219,6 +220,17 @@ if not nuts.mlist_to_hlist then
end
+if not nuts.has_dimensions then
+
+ local getwhd = direct.getwhd
+
+ function nuts.has_dimensions(n)
+ local wd, ht, dp = getwhd(n)
+ return wd ~= 0 or (ht + dp) ~= 0
+ end
+
+end
+
local getfield = direct.getfield
local setfield = direct.setfield
@@ -254,6 +266,13 @@ nuts.setdisc = direct.setdisc
nuts.getdiscretionary = direct.getdisc
nuts.setdiscretionary = direct.setdisc
+nuts.getpre = direct.getpre
+nuts.setpre = direct.setpre
+nuts.getpost = direct.getpost
+nuts.setpost = direct.setpost
+nuts.getreplace = direct.getreplace
+nuts.setreplace = direct.setreplace
+
local getdata = direct.getdata
local setdata = direct.setdata
@@ -382,6 +401,23 @@ local remove = (CONTEXTLMTXMODE > 0 and LUATEXFUNCTIONALITY >= 20190704) and d_r
return head, current
end
+-- for now
+
+if not nuts.getpre then
+
+ local d_getdisc = direct.getdisc
+ local d_setfield = direct.setfield
+
+ function nuts.getpre(d) local h, _, _, t, _, _ = d_getdisc(d,true) return h, t end
+ function nuts.getpost(d) local _, h, _, _, t, _ = d_getdisc(d,true) return h, t end
+ function nuts.getreplace(d) local _, _, h, _, _, t = d_getdisc(d,true) return h, t end
+
+ function nuts.setpre(d,n) d_setfield("pre", n) end
+ function nuts.setpost(d,n) d_setfield("post", n) end
+ function nuts.setreplace(d,n) d_setfield("replace",n) end
+
+end
+
-- alias
nuts.getsurround = nuts.getkern
diff --git a/tex/context/base/mkiv/node-ref.lua b/tex/context/base/mkiv/node-ref.lua
index e12bd95bd..21fc4ce4d 100644
--- a/tex/context/base/mkiv/node-ref.lua
+++ b/tex/context/base/mkiv/node-ref.lua
@@ -166,33 +166,33 @@ local function dimensions(parent,start,stop) -- in principle we could move some
-- todo: if no prev and no next and parent
-- todo: we need a a list_dimensions for a vlist
if getid(parent) == vlist_code then
- if false then
- local l = getlist(parent)
- local c = l
- local ok = false
- while c do
- if c == start then
- ok = true
- end
- if ok and getid(c) == hlist_code then
- break
- else
- c = getnext(c)
- end
- end
- if ok and c then
- if trace_areas then
- report_area("dimensions taken of first line in vlist")
- end
- local w, h, d = getwhd(c)
- return w, h, d, c
- else
- if trace_areas then
- report_area("dimensions taken of vlist (probably wrong)")
- end
- return hlist_dimensions(start,stop,parent)
- end
- else
+ -- if false then
+ -- local l = getlist(parent)
+ -- local c = l
+ -- local ok = false
+ -- while c do
+ -- if c == start then
+ -- ok = true
+ -- end
+ -- if ok and getid(c) == hlist_code then
+ -- break
+ -- else
+ -- c = getnext(c)
+ -- end
+ -- end
+ -- if ok and c then
+ -- if trace_areas then
+ -- report_area("dimensions taken of first line in vlist")
+ -- end
+ -- local w, h, d = getwhd(c)
+ -- return w, h, d, c
+ -- else
+ -- if trace_areas then
+ -- report_area("dimensions taken of vlist (probably wrong)")
+ -- end
+ -- return hlist_dimensions(start,stop,parent)
+ -- end
+ -- else
--
-- we can as well calculate here because we only have kerns and glue
--
@@ -200,7 +200,7 @@ local function dimensions(parent,start,stop) -- in principle we could move some
local last = nil
local current = start
local noflines = 0
- while current do
+ while current do -- can be loop
local id = getid(current)
if id == hlist_code or id == vlist_code or id == rule_code then
if noflines == 0 then
@@ -239,7 +239,7 @@ local function dimensions(parent,start,stop) -- in principle we could move some
return hlist_dimensions(start,stop,parent)
end
end
- end
+ -- end
else
if trace_areas then
report_area("dimensions taken of range starting with %a using parent",nodecodes[id])
@@ -929,7 +929,6 @@ local function makedestination(width,height,depth,reference)
end
end
-
function nodes.destinations.handler(head)
if head and topofstack > 0 then
return (inject_areas(head,attribute,makedestination,stack,done))
diff --git a/tex/context/base/mkiv/page-run.lua b/tex/context/base/mkiv/page-run.lua
index 88a7d6664..53331fc0e 100644
--- a/tex/context/base/mkiv/page-run.lua
+++ b/tex/context/base/mkiv/page-run.lua
@@ -212,7 +212,7 @@ function commands.showusage()
report(" save size : %s of %s", status.max_save_stack, status.save_size)
report("")
report(" luabytecode bytes : %s in %s registers", status.luabytecode_bytes, status.luabytecodes)
- report(" luastate bytes : %s", status.luastate_bytes)
+ report(" luastate bytes : %s of %s", status.luastate_bytes, status.luastate_bytes_max or "unknown")
report("")
report(" callbacks : %s", status.callbacks)
report(" indirect callbacks : %s", status.indirect_callbacks)
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 472dee79a..aa20128db 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 4b9db0b9a..3e5df5ff2 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-doc.lua b/tex/context/base/mkiv/strc-doc.lua
index 4b2ac04b7..aa5fe352e 100644
--- a/tex/context/base/mkiv/strc-doc.lua
+++ b/tex/context/base/mkiv/strc-doc.lua
@@ -672,8 +672,15 @@ local function process(index,numbers,ownnumbers,criterium,separatorset,conversio
end
end
-function sections.typesetnumber(entry,kind,...) -- kind='section','number','prefix'
- if entry and entry.hidenumber ~= true then -- can be nil
+-- kind : section number prefix
+
+function sections.typesetnumber(entry,kind,...)
+ --
+ -- Maybe the hiding becomes an option .. after all this test was there
+ -- for a reason, but for now we have this:
+ --
+ -- if entry and entry.hidenumber ~= true then
+ if entry then
local separatorset = ""
local conversionset = ""
local conversion = ""
diff --git a/tex/context/base/mkiv/strc-lnt.mkvi b/tex/context/base/mkiv/strc-lnt.mkvi
index 4a6f14245..ad8c80d93 100644
--- a/tex/context/base/mkiv/strc-lnt.mkvi
+++ b/tex/context/base/mkiv/strc-lnt.mkvi
@@ -160,13 +160,6 @@
% compress=yes|no
% compressmethod=separator|stopper
-\def\c!compressdistance{compressdistance}
-\def\c!compressmethod {compressmethod}
-\def\c!compressstopper {compressstopper} % c
-\def\v!compressstopper {compressstopper} % v
-
-\def\v!separator {separator} % v
-
\setvalue{\??linenotescompressmethod\v!separator}%
{\edef\p_compressseparator{\noteparameter\c!compressseparator}%
\scratchskip\noteparameter\c!compressdistance\relax
diff --git a/tex/context/base/mkiv/strc-reg.lua b/tex/context/base/mkiv/strc-reg.lua
index be3436bd4..88b738b6d 100644
--- a/tex/context/base/mkiv/strc-reg.lua
+++ b/tex/context/base/mkiv/strc-reg.lua
@@ -761,6 +761,8 @@ local seeindex = 0
-- meerdere loops, seewords, dan words, anders seewords
+-- todo: split seeword
+
local function crosslinkseewords(result,check) -- all words
-- collect all seewords
local seewords = { }
@@ -778,23 +780,68 @@ local function crosslinkseewords(result,check) -- all words
end
end
end
+
-- mark seeparents
+
+ -- local seeparents = { }
+ -- for i=1,#result do
+ -- local data = result[i]
+ -- local word = data.list[1]
+ -- local okay = word and word[1]
+ -- if okay then
+ -- local seeindex = seewords[okay]
+ -- if seeindex then
+ -- seeparents[okay] = data
+ -- data.references.seeparent = seeindex
+ -- if trace_registers then
+ -- report_registers("see parent %03i: %s",seeindex,okay)
+ -- end
+ -- end
+ -- end
+ -- end
+
+ local entries = { }
+ local keywords = { }
local seeparents = { }
for i=1,#result do
local data = result[i]
- local word = data.list[1]
- word = word and word[1]
- if word then
- local seeindex = seewords[word]
+ local word = data.list
+ local size = #word
+ if data.seeword then
+ -- beware: a seeword has an extra entry for sorting purposes
+ size = size - 1
+ end
+ for i=1,size do
+ local w = word[i]
+ local e = w[1]
+ local k = w[2] or e
+ entries [i] = e
+ keywords[i] = k
+ end
+ -- first try the keys
+ local okay, seeindex
+ for n=size,1,-1 do
+ okay = concat(keywords,"+",1,n)
+ seeindex = seewords[okay]
+ -- first try the entries
if seeindex then
- seeparents[word] = data
- data.references.seeparent = seeindex
- if trace_registers then
- report_registers("see parent %03i: %s",seeindex,word)
- end
+ break
+ end
+ okay = concat(entries,"+",1,n)
+ seeindex = seewords[okay]
+ if seeindex then
+ break
+ end
+ end
+ if seeindex then
+ seeparents[okay] = data
+ data.references.seeparent = seeindex
+ if trace_registers then
+ report_registers("see parent %03i: %s",seeindex,okay)
end
end
end
+
-- mark seewords and extend sort list
for i=1,#result do
local data = result[i]
diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv
index 24397ecbf..281c4a218 100644
--- a/tex/context/base/mkiv/syst-ini.mkiv
+++ b/tex/context/base/mkiv/syst-ini.mkiv
@@ -1098,21 +1098,27 @@
\let\pagebottomoffset\voffset \let\normalpagebottomoffset\voffset
\fi
-%D Handy.
+%D Handy (this will change, again).
-\suppresslongerror \plusone
-\suppressoutererror \plusone
-\suppressmathparerror \plusone
-\suppressifcsnameerror\plusone
+\ifdefined\suppresslongerror \suppresslongerror \plusone \fi
+\ifdefined\suppressoutererror \suppressoutererror \plusone \fi
+\ifdefined\suppressmathparerror \suppressmathparerror \plusone \fi
+\ifdefined\suppressifcsnameerror \suppressifcsnameerror \plusone \fi
+\ifdefined\suppressfontnotfounderror\suppressfontnotfounderror\zerocount\fi
-\let \suppresslongerror \relax
-\newcount\suppresslongerror \let\normalsuppresslongerror \suppresslongerror
-\let \suppressoutererror \suppresslongerror \let\normalsuppressoutererror \suppresslongerror
-\let \suppressmathparerror \suppresslongerror \let\normalsuppressmathparerror \suppresslongerror
-\let \suppressifcsnameerror\suppresslongerror \let\normalsuppressifcsnameerror\suppresslongerror
+\let \suppresslongerror \relax
+\newcount\suppresslongerror \let\normalsuppresslongerror \suppresslongerror
+\let \suppressoutererror \suppresslongerror \let\normalsuppressoutererror \suppresslongerror
+\let \suppressmathparerror \suppresslongerror \let\normalsuppressmathparerror \suppresslongerror
+\let \suppressifcsnameerror \suppresslongerror \let\normalsuppressifcsnameerror \suppresslongerror
+\let \suppressfontnotfounderror\suppresslongerror \let\normalsuppressfontnotfounderror\suppresslongerror
\matheqnogapstep\zerocount % for now
+%D Experiment:
+
+\ifdefined\frozen \else \def\frozen{} \let\normalfrozen\frozen \fi
+
%D Now we define a few helpers that we need in a very early stage. We have no
%D message system yet but redundant definitions are fatal anyway.
diff --git a/tex/context/base/mkiv/toks-ini.lua b/tex/context/base/mkiv/toks-ini.lua
index b7657625b..af93d3bc1 100644
--- a/tex/context/base/mkiv/toks-ini.lua
+++ b/tex/context/base/mkiv/toks-ini.lua
@@ -42,13 +42,21 @@ local scan_glue = token.scan_glue
local scan_keyword = token.scan_keyword
local scan_keyword_cs = token.scan_keyword_cs or scan_keyword
local scan_token = token.scan_token
+local scan_list = token.scan_list
local scan_word = token.scan_word
+local scan_key = token.scan_key
+local scan_value = token.scan_value
+local scan_char = token.scan_char
local scan_number = token.scan_number
local scan_csname = token.scan_csname
local scan_real = token.scan_real
local scan_float = token.scan_float
local get_next = token.get_next
+local get_next_token = token.get_next_token
+local skip_next = token.skip_next
+local peek_next_char = token.peek_next_char
+local is_next_char = token.is_next_char
local set_macro = token.set_macro
local get_macro = token.get_macro
@@ -134,6 +142,7 @@ tokens.scanners = { -- these expand
token = scan_token,
toks = scan_toks,
tokens = scan_toks,
+ list = scan_list,
dimen = scan_dimen,
dimension = scan_dimen,
glue = scan_glue,
@@ -149,11 +158,17 @@ tokens.scanners = { -- these expand
code = scan_code,
tokencode = scan_token_code,
word = scan_word,
+ key = scan_key,
+ value = scan_value,
+ char = scan_char,
number = scan_number,
boolean = scan_boolean,
keyword = scan_keyword,
keywordcs = scan_keyword_cs,
csname = scan_csname,
+ peek = peek_next_char,
+ skip = skip_next,
+ ischar = is_next_char,
}
tokens.getters = { -- these don't expand
@@ -225,6 +240,7 @@ if setinspector then
active = t.active,
expandable = t.expandable,
protected = t.protected,
+ frozen = t.frozen,
mode = t.mode,
index = t.index,
cmdname = cmdname,
diff --git a/tex/context/base/mkiv/toks-scn.lua b/tex/context/base/mkiv/toks-scn.lua
index f259bcee5..b707500e7 100644
--- a/tex/context/base/mkiv/toks-scn.lua
+++ b/tex/context/base/mkiv/toks-scn.lua
@@ -29,6 +29,7 @@ local scannumber = scanners.number
local scankeyword = scanners.keyword
local scankeywordcs = scanners.keywordcs
local scanword = scanners.word
+local scankey = scanners.key
local scancode = scanners.code
local scanboolean = scanners.boolean
local scandimen = scanners.dimen
@@ -180,6 +181,7 @@ local shortcuts = {
scankeyword = scankeyword,
scankeywordcs = scankeywordcs,
scanword = scanword,
+ -- scankey = scankey,
scancode = scancode,
scanboolean = scanboolean,
scandimen = scandimen,
diff --git a/tex/context/base/mkiv/trac-deb.lua b/tex/context/base/mkiv/trac-deb.lua
index bd406b0e5..4d754ec68 100644
--- a/tex/context/base/mkiv/trac-deb.lua
+++ b/tex/context/base/mkiv/trac-deb.lua
@@ -315,7 +315,7 @@ directives.register("system.errorcontext", function(v)
register('show_error_message', nop)
register('show_warning_message',function() processwarning(v) end)
register('show_error_hook', function() processerror(v) end)
- register('show_lua_error_hook', nop)
+ register('show_lua_error_hook', function() processerror(v) end)
else
register('show_error_message', nil)
register('show_error_hook', nil)
@@ -371,7 +371,8 @@ function lmx.showerror(lmxname)
end
function lmx.overloaderror()
- callback.register('show_error_hook', function() lmx.showerror() end) -- prevents arguments being passed
+ callback.register('show_error_hook', function() lmx.showerror() end) -- prevents arguments being passed
+ callback.register('show_lua_error_hook', function() lmx.showerror() end) -- prevents arguments being passed
end
directives.register("system.showerror", lmx.overloaderror)
diff --git a/tex/context/base/mkiv/trac-inf.lua b/tex/context/base/mkiv/trac-inf.lua
index 0a4537e31..24ebc5249 100644
--- a/tex/context/base/mkiv/trac-inf.lua
+++ b/tex/context/base/mkiv/trac-inf.lua
@@ -262,7 +262,11 @@ end
function statistics.memused() -- no math.round yet -)
local round = math.round or math.floor
- return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000), round(status.luastate_bytes/1000000))
+ return format("%s MB, ctx: %s MB, max: %s MB)",
+ round(collectgarbage("count")/1000),
+ round(status.luastate_bytes/1000000),
+ status.luastate_bytes_max and round(status.luastate_bytes_max/1000000) or "unknown"
+ )
end
starttiming(statistics)
diff --git a/tex/context/base/mkiv/typo-cap.lua b/tex/context/base/mkiv/typo-cap.lua
index 7e8003c62..64bb66dab 100644
--- a/tex/context/base/mkiv/typo-cap.lua
+++ b/tex/context/base/mkiv/typo-cap.lua
@@ -315,6 +315,9 @@ register(variables.camel, camel) -- 10
register(variables.cap, variables.capital) -- clone
register(variables.Cap, variables.Capital) -- clone
+-- this can be more clever: when we unset we can actually
+-- use the same attr ref if needed
+
function cases.handler(head) -- not real fast but also not used on much data
local start = head
local lastfont = { }
@@ -341,9 +344,10 @@ function cases.handler(head) -- not real fast but also not used on much data
end
local action = actions[n] -- map back to low number
if action then
- start = action(start,attr,lastfont,n,count)
+ local quit
+ start, quit = action(start,attr,lastfont,n,count)
if trace_casing then
- report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,ok)
+ report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,quit and "-" or "+")
end
elseif trace_casing then
report_casing("unknown case trigger %a",n)
diff --git a/tex/context/base/mkiv/typo-pag.lua b/tex/context/base/mkiv/typo-pag.lua
index 05513e20c..ea4b1574c 100644
--- a/tex/context/base/mkiv/typo-pag.lua
+++ b/tex/context/base/mkiv/typo-pag.lua
@@ -108,93 +108,94 @@ function parbuilders.registertogether(line,specification) -- might change
end
end
-local function keeptogether(start,a)
- if start then
- local specification = cache[a]
- if a then
- local current = getnext(start)
- local previous = start
- local total = getdepth(previous)
- local slack = specification.slack
- local threshold = specification.depth - slack
+local function keeptogether(start,a,specification)
+ local current = getnext(start)
+ local previous = start
+ local total = getdepth(previous)
+ local slack = specification.slack
+ local threshold = specification.depth - slack
+ if trace_keeptogether then
+ report_keeptogether("%s, index %s, total %p, threshold %p, slack %p","list",a,total,threshold,slack)
+ end
+ while current do
+ local id = getid(current)
+ if id == vlist_code or id == hlist_code then
+ local wd, ht, dp = getwhd(current)
+ total = total + ht + dp
+ if trace_keeptogether then
+ report_keeptogether("%s, index %s, total %p, threshold %p","list",a,total,threshold)
+ end
+ if total <= threshold then
+ if getid(previous) == penalty_code then
+ setpenalty(previous,10000)
+ else
+ insert_node_after(head,previous,new_penalty(10000))
+ end
+ else
+ break
+ end
+ elseif id == glue_code then
+ -- hm, breakpoint, maybe turn this into kern
+ total = total + getwidth(current)
if trace_keeptogether then
- report_keeptogether("%s, index %s, total %p, threshold %p, slack %p","list",a,total,threshold,slack)
+ report_keeptogether("%s, index %s, total %p, threshold %p","glue",a,total,threshold)
end
- while current do
- local id = getid(current)
- if id == vlist_code or id == hlist_code then
- local wd, ht, dp = getwhd(current)
- total = total + ht + dp
- if trace_keeptogether then
- report_keeptogether("%s, index %s, total %p, threshold %p","list",a,total,threshold)
- end
- if total <= threshold then
- if getid(previous) == penalty_code then
- setpenalty(previous,10000)
- else
- insert_node_after(head,previous,new_penalty(10000))
- end
- else
- break
- end
- elseif id == glue_code then
- -- hm, breakpoint, maybe turn this into kern
- total = total + getwidth(current)
- if trace_keeptogether then
- report_keeptogether("%s, index %s, total %p, threshold %p","glue",a,total,threshold)
- end
- if total <= threshold then
- if getid(previous) == penalty_code then
- setpenalty(previous,10000)
- else
- insert_node_after(head,previous,new_penalty(10000))
- end
- else
- break
- end
- elseif id == kern_code then
- total = total + getkern(current)
- if trace_keeptogether then
- report_keeptogether("%s, index %s, total %s, threshold %s","kern",a,total,threshold)
- end
- if total <= threshold then
- if getid(previous) == penalty_code then
- setpenalty(previous,10000)
- else
- insert_node_after(head,previous,new_penalty(10000))
- end
- else
- break
- end
- elseif id == penalty_code then
- if total <= threshold then
- if getid(previous) == penalty_code then
- setpenalty(previous,10000)
- end
- setpenalty(current,10000)
- else
- break
- end
+ if total <= threshold then
+ if getid(previous) == penalty_code then
+ setpenalty(previous,10000)
+ else
+ insert_node_after(head,previous,new_penalty(10000))
end
- previous = current
- current = getnext(current)
+ else
+ break
+ end
+ elseif id == kern_code then
+ total = total + getkern(current)
+ if trace_keeptogether then
+ report_keeptogether("%s, index %s, total %s, threshold %s","kern",a,total,threshold)
+ end
+ if total <= threshold then
+ if getid(previous) == penalty_code then
+ setpenalty(previous,10000)
+ else
+ insert_node_after(head,previous,new_penalty(10000))
+ end
+ else
+ break
+ end
+ elseif id == penalty_code then
+ if total <= threshold then
+ if getid(previous) == penalty_code then
+ setpenalty(previous,10000)
+ end
+ setpenalty(current,10000)
+ else
+ break
end
end
+ previous = current
+ current = getnext(current)
end
end
-- also look at first non glue/kern node e.g for a dropped caps
function parbuilders.keeptogether(head)
- local done = false
+ local done = false -- can go
local current = head
while current do
if getid(current) == hlist_code then
local a = takeattr(current,a_keeptogether)
if a and a > 0 then
- keeptogether(current,a)
- cache[a] = nil
- done = true
+ local specification = cache[a]
+ if specification then
+ keeptogether(current,a,specification)
+ -- this is tricky ... we need a better resetter, maybe some
+ -- injected latelua or a gc method on a property (interesting
+ -- experiment)
+ cache[a] = nil
+ done = true
+ end
end
end
current = getnext(current)
diff --git a/tex/context/base/mkiv/util-jsn.lua b/tex/context/base/mkiv/util-jsn.lua
index 68c6a712e..8da351897 100644
--- a/tex/context/base/mkiv/util-jsn.lua
+++ b/tex/context/base/mkiv/util-jsn.lua
@@ -122,11 +122,14 @@ do
local f_key_val_num = f_key_val_seq
local f_key_val_yes = formatters[ "\n" .. '%w"%s" : true' ]
local f_key_val_nop = formatters[ "\n" .. '%w"%s" : false' ]
+ local f_key_val_null = formatters[ "\n" .. '%w"%s" : null' ]
local f_val_num = formatters[ "\n" .. '%w%s' ]
local f_val_str = formatters[ "\n" .. '%w"%s"' ]
local f_val_yes = formatters[ "\n" .. '%wtrue' ]
local f_val_nop = formatters[ "\n" .. '%wfalse' ]
+ local f_val_null = formatters[ "\n" .. '%wnull' ]
+ local f_val_empty = formatters[ "\n" .. '%w{ }' ]
local f_val_seq = f_val_num
-- no empty tables because unknown if table or hash
@@ -158,8 +161,10 @@ do
n = n + 1 t[n] = '"'
elseif tv == "boolean" then
n = n + 1 t[n] = v and "true" or "false"
- else
+ elseif v then
n = n + 1 t[n] = tostring(v)
+ else
+ n = n + 1 t[n] = "null"
end
end
n = n + 1 t[n] = " ]"
@@ -217,8 +222,11 @@ do
if st then
n = n + 1 t[n] = f_val_seq(depth,st)
else
- tojsonpp(v,k,depth,level+1,0)
+ tojsonpp(v,nil,depth,level+1,#v)
end
+ else
+ n = n + 1
+ t[n] = f_val_empty(depth)
end
elseif tv == "boolean" then
n = n + 1
@@ -227,6 +235,9 @@ do
else
t[n] = f_val_nop(depth,v)
end
+ else
+ n = n + 1
+ t[n] = f_val_null(depth)
end
end
elseif next(root) then
@@ -244,12 +255,12 @@ do
n = n + 1 t[n] = f_key_val_num(depth,k,v)
elseif tk == "string" then
k = lpegmatch(escaper,k) or k
- n = n + 1 t[n] = f_key_val_str(depth,k,v)
+ n = n + 1 t[n] = f_key_val_num(depth,k,v)
end
elseif tv == "string" then
if tk == "number" then
v = lpegmatch(escaper,v) or v
- n = n + 1 t[n] = f_key_val_num(depth,k,v)
+ n = n + 1 t[n] = f_key_val_str(depth,k,v)
elseif tk == "string" then
k = lpegmatch(escaper,k) or k
v = lpegmatch(escaper,v) or v
@@ -287,6 +298,15 @@ do
t[n] = f_key_val_nop(depth,k)
end
end
+ else
+ if tk == "number" then
+ n = n + 1
+ t[n] = f_key_val_null(depth,k)
+ elseif tk == "string" then
+ k = lpegmatch(escaper,k) or k
+ n = n + 1
+ t[n] = f_key_val_null(depth,k)
+ end
end
end
end
@@ -348,6 +368,8 @@ do
n = n + 1 ; t[n] = value
elseif kind == "boolean" then
n = n + 1 ; t[n] = tostring(value)
+ else
+ n = n + 1 ; t[n] = "null"
end
return t, n
end
@@ -377,10 +399,9 @@ do
n = 0
if pretty then
tojsonpp(value,name,0,0,#value)
--- value = concat(t,"\n",1,n)
value = concat(t,"",1,n)
else
- tojson(value,0)
+ t, n = tojson(value,0)
value = concat(t,"",1,n)
end
t = nil