summaryrefslogtreecommitdiff
path: root/tex/context/base/mlib-pps.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mlib-pps.lua')
-rw-r--r--tex/context/base/mlib-pps.lua343
1 files changed, 144 insertions, 199 deletions
diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua
index 9f6cedad1..93bddc2dd 100644
--- a/tex/context/base/mlib-pps.lua
+++ b/tex/context/base/mlib-pps.lua
@@ -6,20 +6,20 @@ if not modules then modules = { } end modules ['mlib-pps'] = {
license = "see context related readme files",
}
--- todo: pass multipass nicer
+-- todo: make a hashed textext variant where we only process the text once (normally
+-- we cannot assume that no macros are involved which influence a next textext
local format, gmatch, match, split = string.format, string.gmatch, string.match, string.split
local tonumber, type = tonumber, type
local round = math.round
-local insert, remove, concat = table.insert, table.remove, table.concat
+local insert, concat = table.insert, table.concat
local Cs, Cf, C, Cg, Ct, P, S, V, Carg = lpeg.Cs, lpeg.Cf, lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S, lpeg.V, lpeg.Carg
local lpegmatch = lpeg.match
local formatters = string.formatters
local mplib, metapost, lpdf, context = mplib, metapost, lpdf, context
-local texgetbox = tex.getbox
-local texsetbox = tex.setbox
+local texbox = tex.box
local copy_list = node.copy_list
local free_list = node.flush_list
local setmetatableindex = table.setmetatableindex
@@ -211,65 +211,52 @@ local function checkandconvert(ca,cb)
end
end
-local stack = { } -- quick hack, we will pass topofstack around
-local top = nil
-local nofruns = 0 -- askedfig: "all", "first", number
+local current_format, current_graphic, current_initializations
-local function startjob(texmode)
- top = {
- textexts = { }, -- all boxes, optionally with a different color
- texslots = { }, -- references to textexts in order or usage
- texorder = { }, -- references to textexts by mp index
- textrial = 0,
- texfinal = 0,
- -- used by tx plugin
- texhash = { },
- texlast = 0,
- texmode = texmode, -- some day we can then skip all pre/postscripts
- }
- insert(stack,top)
- if trace_runs then
- report_metapost("starting run at level %i",#stack)
- end
- return top
-end
+metapost.multipass = false
+
+local textexts = { } -- all boxes, optionally with a different color
+local texslots = { } -- references to textexts in order or usage
+local texorder = { } -- references to textexts by mp index
+local textrial = 0
+local texfinal = 0
+local scratchbox = 0
-local function stopjob()
- if top then
- for n, tn in next, top.textexts do
+local function freeboxes()
+ for n, box in next, textexts do
+ local tn = textexts[n]
+ if tn then
free_list(tn)
+ -- texbox[scratchbox] = tn
+ -- texbox[scratchbox] = nil -- this frees too
if trace_textexts then
report_textexts("freeing box %s",n)
end
end
- if trace_runs then
- report_metapost("stopping run at level %i",#stack)
- end
- remove(stack)
- top = stack[#stack]
- return top
end
+ textexts = { }
+ texslots = { }
+ texorder = { }
+ textrial = 0
+ texfinal = 0
end
-function metapost.settextexts () end -- obsolete
-function metapost.resettextexts() end -- obsolete
-
--- end of new
+metapost.resettextexts = freeboxes
function metapost.settext(box,slot)
- top.textexts[slot] = copy_list(texgetbox(box))
- texsetbox(box,nil)
+ textexts[slot] = copy_list(texbox[box])
+ texbox[box] = nil
-- this will become
- -- top.textexts[slot] = texgetbox(box)
+ -- textexts[slot] = texbox[box]
-- unsetbox(box)
end
function metapost.gettext(box,slot)
- texsetbox(box,copy_list(top.textexts[slot]))
+ texbox[box] = copy_list(textexts[slot])
if trace_textexts then
report_textexts("putting text %s in box %s",slot,box)
end
- -- top.textexts[slot] = nil -- no, pictures can be placed several times
+ -- textexts[slot] = nil -- no, pictures can be placed several times
end
-- rather generic pdf, so use this elsewhere too it no longer pays
@@ -502,10 +489,7 @@ local do_safeguard = ";"
local f_text_data = formatters["mfun_tt_w[%i] := %f ; mfun_tt_h[%i] := %f ; mfun_tt_d[%i] := %f ;"]
function metapost.textextsdata()
- local texorder = top.texorder
- local textexts = top.textexts
- local collected = { }
- local nofcollected = 0
+ local t, nt, n = { }, 0, 0
for n=1,#texorder do
local box = textexts[texorder[n]]
if box then
@@ -513,23 +497,25 @@ function metapost.textextsdata()
if trace_textexts then
report_textexts("passed data item %s: (%p,%p,%p)",n,wd,ht,dp)
end
- nofcollected = nofcollected + 1
- collected[nofcollected] = f_text_data(n,wd,n,ht,n,dp)
+ nt = nt + 1
+ t[nt] = f_text_data(n,wd,n,ht,n,dp)
else
break
end
end
- return collected
+-- inspect(t)
+ return t
end
-metapost.intermediate = metapost.intermediate or { }
-metapost.intermediate.actions = metapost.intermediate.actions or { }
+metapost.intermediate = metapost.intermediate or {}
+metapost.intermediate.actions = metapost.intermediate.actions or {}
+metapost.intermediate.needed = false
metapost.method = 1 -- 1:dumb 2:clever
-- maybe we can latelua the texts some day
-local processmetapost = metapost.process
+local nofruns = 0 -- askedfig: "all", "first", number
local function checkaskedfig(askedfig) -- return askedfig, wrappit
if not askedfig then
@@ -548,42 +534,18 @@ local function checkaskedfig(askedfig) -- return askedfig, wrappit
end
end
-local function extrapass()
- if trace_runs then
- report_metapost("second run of job %s, asked figure %a",top.nofruns,top.askedfig)
- end
- processmetapost(top.mpx, {
- top.wrappit and do_begin_fig or "",
- no_trial_run,
- concat(metapost.textextsdata()," ;\n"),
- top.initializations,
- do_safeguard,
- top.data,
- top.wrappit and do_end_fig or "",
- }, false, nil, false, true, top.askedfig)
- -- context.MPLIBresettexts() -- must happen afterwards
-end
-
-function metapost.graphic_base_pass(specification) -- name will change (see mlib-ctx.lua)
- local top = startjob(true)
- --
- local mpx = specification.mpx -- mandate
- local data = specification.data or ""
- local definitions = specification.definitions or ""
- -- local extensions = metapost.getextensions(specification.instance,specification.useextensions)
- local extensions = specification.extensions or ""
- local inclusions = specification.inclusions or ""
+function metapost.graphic_base_pass(specification)
+ local mpx = specification.mpx -- mandate
+ local data = specification.data or ""
+ local definitions = specification.definitions or ""
+-- local extensions = metapost.getextensions(specification.instance,specification.useextensions)
+ local extensions = specification.extensions or ""
+ local inclusions = specification.inclusions or ""
local initializations = specification.initializations or ""
- local askedfig = specification.figure -- no default else no wrapper
+ local askedfig = specification.figure -- no default else no wrapper
--
+ nofruns = nofruns + 1
local askedfig, wrappit = checkaskedfig(askedfig)
- --
- nofruns = nofruns + 1
- --
- top.askedfig = askedfig
- top.wrappit = wrappit
- top.nofruns = nofruns
- --
local done_1, done_2, done_3, forced_1, forced_2, forced_3
data, done_1, forced_1 = checktexts(data)
-- we had preamble = extensions + inclusions
@@ -597,12 +559,12 @@ function metapost.graphic_base_pass(specification) -- name will change (see mlib
else
inclusions, done_3, forced_3 = checktexts(inclusions)
end
- top.intermediate = false
- top.multipass = false -- no needed here
- top.mpx = mpx
- top.data = data
- top.initializations = initializations
- local method = metapost.method
+ metapost.intermediate.needed = false
+ metapost.multipass = false -- no needed here
+ current_format = mpx
+ current_graphic = data
+ current_initializations = initializations
+ local method = metapost.method
if trace_runs then
if method == 1 then
report_metapost("forcing two runs due to library configuration")
@@ -623,19 +585,19 @@ function metapost.graphic_base_pass(specification) -- name will change (see mlib
report_metapost("first run of job %s, asked figure %a",nofruns,askedfig)
end
-- first true means: trialrun, second true means: avoid extra run if no multipass
- local flushed = processmetapost(mpx, {
+ local flushed = metapost.process(mpx, {
definitions,
extensions,
inclusions,
wrappit and do_begin_fig or "",
do_first_run,
do_trial_run,
- initializations,
+ current_initializations,
do_safeguard,
- data,
+ current_graphic,
wrappit and do_end_fig or "",
}, true, nil, not (forced_1 or forced_2 or forced_3), false, askedfig)
- if top.intermediate then
+ if metapost.intermediate.needed then
for _, action in next, metapost.intermediate.actions do
action()
end
@@ -643,35 +605,44 @@ function metapost.graphic_base_pass(specification) -- name will change (see mlib
if not flushed or not metapost.optimize then
-- tricky, we can only ask once for objects and therefore
-- we really need a second run when not optimized
- -- context.MPLIBextrapass(askedfig)
- context(extrapass)
+ context.MPLIBextrapass(askedfig)
end
else
if trace_runs then
report_metapost("running job %s, asked figure %a",nofruns,askedfig)
end
- processmetapost(mpx, {
+ metapost.process(mpx, {
preamble,
wrappit and do_begin_fig or "",
do_first_run,
no_trial_run,
- initializations,
+ current_initializations,
do_safeguard,
- data,
+ current_graphic,
wrappit and do_end_fig or "",
}, false, nil, false, false, askedfig)
end
- context(stopjob)
end
-function metapost.process(...)
- startjob(false)
- processmetapost(...)
- stopjob()
+function metapost.graphic_extra_pass(askedfig)
+ if trace_runs then
+ report_metapost("second run of job %s, asked figure %a",nofruns,askedfig)
+ end
+ local askedfig, wrappit = checkaskedfig(askedfig)
+ metapost.process(current_format, {
+ wrappit and do_begin_fig or "",
+ no_trial_run,
+ concat(metapost.textextsdata()," ;\n"),
+ current_initializations,
+ do_safeguard,
+ current_graphic,
+ wrappit and do_end_fig or "",
+ }, false, nil, false, true, askedfig)
+ context.MPLIBresettexts() -- must happen afterwards
end
local start = [[\starttext]]
-local preamble = [[\def\MPLIBgraphictext#1{\startTEXpage[scale=10000]#1\stopTEXpage}]]
+local preamble = [[\long\def\MPLIBgraphictext#1{\startTEXpage[scale=10000]#1\stopTEXpage}]]
local stop = [[\stoptext]]
function makempy.processgraphics(graphics)
@@ -687,20 +658,15 @@ function makempy.processgraphics(graphics)
os.execute(command)
if io.exists(pdffile) then
command = format("pstoedit -ssp -dt -f mpost %s %s", pdffile, mpyfile)
- logs.newline()
- report_metapost("running: %s",command)
- logs.newline()
os.execute(command)
local result, r = { }, 0
if io.exists(mpyfile) then
local data = io.loaddata(mpyfile)
- if data and #data > 0 then
- for figure in gmatch(data,"beginfig(.-)endfig") do
- r = r + 1
- result[r] = formatters["begingraphictextfig%sendgraphictextfig ;\n"](figure)
- end
- io.savedata(mpyfile,concat(result,""))
+ for figure in gmatch(data,"beginfig(.-)endfig") do
+ r = r + 1
+ result[r] = formatters["begingraphictextfig%sendgraphictextfig ;\n"](figure)
end
+ io.savedata(mpyfile,concat(result,""))
end
end
stoptiming(makempy)
@@ -721,9 +687,9 @@ local resetteractions = sequencers.new { arguments = "t" }
local analyzeractions = sequencers.new { arguments = "object,prescript" }
local processoractions = sequencers.new { arguments = "object,prescript,before,after" }
-appendgroup(resetteractions, "system")
-appendgroup(analyzeractions, "system")
-appendgroup(processoractions,"system")
+appendgroup(resetteractions, "system")
+appendgroup(analyzeractions, "system")
+appendgroup(processoractions, "system")
-- later entries come first
@@ -762,56 +728,48 @@ end
-- end
function metapost.pluginactions(what,t,flushfigure) -- before/after object, depending on what
- if top.texmode then
- for i=1,#what do
- local wi = what[i]
- if type(wi) == "function" then
- -- assume injection
- flushfigure(t) -- to be checked: too many 0 g 0 G
- t = { }
- wi()
- else
- t[#t+1] = wi
- end
+ for i=1,#what do
+ local wi = what[i]
+ if type(wi) == "function" then
+ -- assume injection
+ flushfigure(t) -- to be checked: too many 0 g 0 G
+ t = { }
+ wi()
+ else
+ t[#t+1] = wi
end
- return t
end
+ return t
end
function metapost.resetplugins(t) -- intialize plugins, before figure
- if top.texmode then
- -- plugins can have been added
- resetter = resetteractions.runner
- analyzer = analyzeractions.runner
- processor = processoractions.runner
- -- let's apply one runner
- resetter(t)
- end
+ -- plugins can have been added
+ resetter = resetteractions .runner
+ analyzer = analyzeractions .runner
+ processor = processoractions .runner
+ -- let's apply one runner
+ resetter(t)
end
function metapost.analyzeplugins(object) -- each object (first pass)
- if top.texmode then
- local prescript = object.prescript -- specifications
- if prescript and #prescript > 0 then
- return analyzer(object,splitprescript(prescript))
- end
+ local prescript = object.prescript -- specifications
+ if prescript and #prescript > 0 then
+ return analyzer(object,splitprescript(prescript))
end
end
function metapost.processplugins(object) -- each object (second pass)
- if top.texmode then
- local prescript = object.prescript -- specifications
- if prescript and #prescript > 0 then
- local before = { }
- local after = { }
- processor(object,splitprescript(prescript),before,after)
- return #before > 0 and before, #after > 0 and after
- else
- local c = object.color
- if c and #c > 0 then
- local b, a = colorconverter(c)
- return { b }, { a }
- end
+ local prescript = object.prescript -- specifications
+ if prescript and #prescript > 0 then
+ local before = { }
+ local after = { }
+ processor(object,splitprescript(prescript),before,after)
+ return #before > 0 and before, #after > 0 and after
+ else
+ local c = object.color
+ if c and #c > 0 then
+ local b, a = colorconverter(c)
+ return { b }, { a }
end
end
end
@@ -841,37 +799,29 @@ local function cl_reset(t)
t[#t+1] = metapost.colorinitializer() -- only color
end
+local tx_hash = { }
+local tx_last = 0
+
local function tx_reset()
- if top then
- top.texhash = { }
- top.texlast = 0
- end
+ tx_hash = { }
+ tx_last = 0
end
local fmt = formatters["%s %s %s % t"]
-local pat = lpeg.tsplitat(":")
local function tx_analyze(object,prescript) -- todo: hash content and reuse them
local tx_stage = prescript.tx_stage
if tx_stage == "trial" then
- local tx_trial = top.textrial + 1
- top.textrial = tx_trial
+ textrial = textrial + 1
local tx_number = tonumber(prescript.tx_number)
local s = object.postscript or ""
local c = object.color -- only simple ones, no transparency
- if #c == 0 then
- local txc = prescript.tx_color
- if txc then
- c = lpegmatch(pat,txc)
- end
- end
local a = prescript.tr_alternative
local t = prescript.tr_transparency
- local h = fmt(tx_number,a or "-",t or "-",c or "-")
- local n = top.texhash[h] -- todo: hashed variant with s (nicer for similar labels)
+ local h = fmt(tx_number,a or "?",t or "?",c)
+ local n = tx_hash[h] -- todo: hashed variant with s (nicer for similar labels)
if not n then
- local tx_last = top.texlast + 1
- top.texlast = tx_last
+ tx_last = tx_last + 1
if not c then
-- no color
elseif #c == 1 then
@@ -894,35 +844,31 @@ local function tx_analyze(object,prescript) -- todo: hash content and reuse them
end
end
context.MPLIBsettext(tx_last,s)
- top.multipass = true
- metapost.multipass = true -- ugly
- top.texhash[h] = tx_last
- top.texslots[tx_trial] = tx_last
- top.texorder[tx_number] = tx_last
+ metapost.multipass = true
+ tx_hash[h] = tx_last
+ texslots[textrial] = tx_last
+ texorder[tx_number] = tx_last
if trace_textexts then
- report_textexts("stage %a, usage %a, number %a, new %a, hash %a",tx_stage,tx_trial,tx_number,tx_last,h)
+ report_textexts("stage %a, usage %a, number %a, new %a, hash %a",tx_stage,textrial,tx_number,tx_last,h)
end
else
- top.texslots[tx_trial] = n
+ texslots[textrial] = n
if trace_textexts then
- report_textexts("stage %a, usage %a, number %a, new %a, hash %a",tx_stage,tx_trial,tx_number,n,h)
+ report_textexts("stage %a, usage %a, number %a, new %a, hash %a",tx_stage,textrial,tx_number,n,h)
end
end
elseif tx_stage == "extra" then
- local tx_trial = top.textrial + 1
- top.textrial = tx_trial
+ textrial = textrial + 1
local tx_number = tonumber(prescript.tx_number)
- if not top.texorder[tx_number] then
+ if not texorder[tx_number] then
local s = object.postscript or ""
- local tx_last = top.texlast + 1
- top.texlast = tx_last
+ tx_last = tx_last + 1
context.MPLIBsettext(tx_last,s)
- top.multipass = true
- metapost.multipass = true -- ugly
- top.texslots[tx_trial] = tx_last
- top.texorder[tx_number] = tx_last
+ metapost.multipass = true
+ texslots[textrial] = tx_last
+ texorder[tx_number] = tx_last
if trace_textexts then
- report_textexts("stage %a, usage %a, number %a, extra %a",tx_stage,tx_trial,tx_number,tx_last)
+ report_textexts("stage %a, usage %a, number %a, extra %a",tx_stage,textrial,tx_number,tx_last)
end
end
end
@@ -934,13 +880,13 @@ local function tx_process(object,prescript,before,after)
tx_number = tonumber(tx_number)
local tx_stage = prescript.tx_stage
if tx_stage == "final" then
- top.texfinal = top.texfinal + 1
- local n = top.texslots[top.texfinal]
+ texfinal = texfinal + 1
+ local n = texslots[texfinal]
if trace_textexts then
- report_textexts("stage %a, usage %a, number %a, use %a",tx_stage,top.texfinal,tx_number,n)
+ report_textexts("stage %a, usage %a, number %a, use %a",tx_stage,texfinal,tx_number,n)
end
local sx, rx, ry, sy, tx, ty = cm(object) -- needs to be frozen outside the function
- local box = top.textexts[n]
+ local box = textexts[n]
if box then
before[#before+1] = function()
-- flush always happens, we can have a special flush function injected before
@@ -982,9 +928,8 @@ local function gt_analyze(object,prescript)
local gt_stage = prescript.gt_stage
if gt_stage == "trial" then
graphics[#graphics+1] = formatters["\\MPLIBgraphictext{%s}"](object.postscript or "")
- top.intermediate = true
- top.multipass = true
- metapost.multipass = true -- ugly
+ metapost.intermediate.needed = true
+ metapost.multipass = true
end
end