summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mlib-pps.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mlib-pps.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/mlib-pps.lua293
1 files changed, 210 insertions, 83 deletions
diff --git a/Master/texmf-dist/tex/context/base/mlib-pps.lua b/Master/texmf-dist/tex/context/base/mlib-pps.lua
index 27269a14e49..7821b3dbf24 100644
--- a/Master/texmf-dist/tex/context/base/mlib-pps.lua
+++ b/Master/texmf-dist/tex/context/base/mlib-pps.lua
@@ -6,14 +6,9 @@ if not modules then modules = { } end modules ['mlib-pps'] = {
license = "see context related readme files",
}
--- pps: prescript, postscripts and specials (although specials are dropped)
---
--- current limitation: if we have textext as well as a special color then due to
--- prescript/postscript overload we can have problems
---
-- todo: report max textexts
-local format, gmatch, match = string.format, string.gmatch, string.match
+local format, gmatch, match, split = string.format, string.gmatch, string.match, string.split
local tonumber, type = tonumber, type
local round = math.round
local insert, concat = table.insert, table.concat
@@ -31,6 +26,7 @@ local sortedhash = table.sortedhash
local starttiming = statistics.starttiming
local stoptiming = statistics.stoptiming
+local trace_runs = false trackers.register("metapost.runs", function(v) trace_runs = v end)
local trace_textexts = false trackers.register("metapost.textexts", function(v) trace_textexts = v end)
local trace_scripts = false trackers.register("metapost.scripts", function(v) trace_scripts = v end)
@@ -103,9 +99,9 @@ end
--~
-local specificationsplitter = Ct(lpeg.splitat(" "))
-local colorsplitter = Ct(lpeg.splitter(":",tonumber)) -- no need for :
-local domainsplitter = Ct(lpeg.splitter(" ",tonumber))
+local specificationsplitter = lpeg.tsplitat(" ")
+local colorsplitter = lpeg.tsplitter(":",tonumber) -- no need for :
+local domainsplitter = lpeg.tsplitter(" ",tonumber)
local centersplitter = domainsplitter
local coordinatesplitter = domainsplitter
@@ -142,11 +138,13 @@ local function spotcolorconverter(parent, n, d, p)
return pdfcolor(colors.model,registercolor(nil,'spot',parent,n,d,p)), outercolor
end
+local commasplitter = lpeg.tsplitat(",")
+
local function checkandconvertspot(n_a,f_a,c_a,v_a,n_b,f_b,c_b,v_b)
-- must be the same but we don't check
local name = format("MpSh%s",nofshades)
- local ca = string.split(v_a,",")
- local cb = string.split(v_b,",")
+ local ca = lpegmatch(commasplitter,v_a)
+ local cb = lpegmatch(commasplitter,v_b)
if #ca == 0 or #cb == 0 then
return { 0 }, { 1 }, "DeviceGray", name
else
@@ -463,14 +461,14 @@ local function sxsy(wd,ht,dp) -- helper for text
return (wd ~= 0 and factor/wd) or 0, (hd ~= 0 and factor/hd) or 0
end
-local no_trial_run = "_trial_run_ := false ;"
-local do_trial_run = "if unknown _trial_run_ : boolean _trial_run_ fi ; _trial_run_ := true ;"
-local text_data_template = "_tt_w_[%i]:=%f;_tt_h_[%i]:=%f;_tt_d_[%i]:=%f;"
-local do_begin_fig = "; beginfig(1); "
+local no_trial_run = "mfun_trial_run := false ;"
+local do_trial_run = "if unknown mfun_trial_run : boolean mfun_trial_run fi ; mfun_trial_run := true ;"
+local text_data_template = "mfun_tt_w[%i] := %f ; mfun_tt_h[%i] := %f ; mfun_tt_d[%i] := %f ;"
+local do_begin_fig = "; beginfig(1) ; "
local do_end_fig = "; endfig ;"
local do_safeguard = ";"
-function metapost.texttextsdata()
+function metapost.textextsdata()
local t, nt, n = { }, 0, 0
for n, box in next, textexts do
if box then
@@ -495,8 +493,28 @@ metapost.method = 1 -- 1:dumb 2:clever
-- maybe we can latelua the texts some day
+local nofruns = 0 -- askedfig: "all", "first", number
+
+local function checkaskedfig(askedfig) -- return askedfig, wrappit
+ if not askedfig then
+ return "direct", true
+ elseif askedfig == "all" then
+ return "all", false
+ elseif askedfig == "direct" then
+ return "all", true
+ else
+ askedfig = tonumber(askedfig)
+ if askedfig then
+ return askedfig, false
+ else
+ return "direct", true
+ end
+ end
+end
+
function metapost.graphic_base_pass(mpsformat,str,initializations,preamble,askedfig)
- local nofig = (askedfig and "") or false
+ nofruns = nofruns + 1
+ local askedfig, wrappit = checkaskedfig(askedfig)
local done_1, done_2, forced_1, forced_2
str, done_1, forced_1 = checktexts(str)
if not preamble or preamble == "" then
@@ -508,16 +526,18 @@ function metapost.graphic_base_pass(mpsformat,str,initializations,preamble,asked
metapost.multipass = false -- no needed here
current_format, current_graphic, current_initializations = mpsformat, str, initializations or ""
if metapost.method == 1 or (metapost.method == 2 and (done_1 or done_2)) then
+ if trace_runs then
+ report_metapost("first run of job %s (asked: %s)",nofruns,tostring(askedfig))
+ end
-- first true means: trialrun, second true means: avoid extra run if no multipass
local flushed = metapost.process(mpsformat, {
preamble,
- nofig or do_begin_fig,
+ wrappit and do_begin_fig or "",
do_trial_run,
current_initializations,
do_safeguard,
current_graphic,
- nofig or do_end_fig
- -- }, true, nil, true )
+ wrappit and do_end_fig or "",
}, true, nil, not (forced_1 or forced_2), false, askedfig)
if metapost.intermediate.needed then
for _, action in next, metapost.intermediate.actions do
@@ -527,32 +547,38 @@ function metapost.graphic_base_pass(mpsformat,str,initializations,preamble,asked
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 or "false")
+ context.MPLIBextrapass(askedfig)
end
else
+ if trace_runs then
+ report_metapost("running job %s (asked: %s)",nofruns,tostring(askedfig))
+ end
metapost.process(mpsformat, {
preamble,
- nofig or do_begin_fig,
+ wrappit and do_begin_fig or "",
no_trial_run,
current_initializations,
do_safeguard,
current_graphic,
- nofig or do_end_fig
+ wrappit and do_end_fig or "",
}, false, nil, false, false, askedfig )
end
end
function metapost.graphic_extra_pass(askedfig)
- local nofig = (askedfig and "") or false
+ if trace_runs then
+ report_metapost("second run of job %s (asked: %s)",nofruns,tostring(askedfig))
+ end
+ local askedfig, wrappit = checkaskedfig(askedfig)
metapost.process(current_format, {
- nofig or do_begin_fig,
+ wrappit and do_begin_fig or "",
no_trial_run,
- concat(metapost.texttextsdata()," ;\n"),
+ concat(metapost.textextsdata()," ;\n"),
current_initializations,
do_safeguard,
current_graphic,
- nofig or do_end_fig
- }, false, nil, false, true, askedfig )
+ wrappit and do_end_fig or "",
+ }, false, nil, false, true, askedfig)
context.MPLIBresettexts() -- must happen afterwards
end
@@ -594,17 +620,17 @@ local sequencers = utilities.sequencers
local appendgroup = sequencers.appendgroup
local appendaction = sequencers.appendaction
-local resetter = nil
-local analyzer = nil
-local processor = nil
+local resetter = nil
+local analyzer = nil
+local processor = nil
-local resetteractions = sequencers.reset { arguments = "" }
-local analyzeractions = sequencers.reset { arguments = "object,prescript" }
-local processoractions = sequencers.reset { arguments = "object,prescript,before,after" }
+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
@@ -628,12 +654,12 @@ local function splitscript(script)
return hash
end
-function metapost.pluginactions(what,t,flushfigure) -- to be checked: too many 0 g 0 G
+function metapost.pluginactions(what,t,flushfigure) -- before/after object, depending on what
for i=1,#what do
local wi = what[i]
if type(wi) == "function" then
-- assume injection
- flushfigure(t)
+ flushfigure(t) -- to be checked: too many 0 g 0 G
t = { }
wi()
else
@@ -643,18 +669,23 @@ function metapost.pluginactions(what,t,flushfigure) -- to be checked: too many 0
return t
end
-function metapost.resetplugins()
- resetter()
+function metapost.resetplugins(t) -- intialize plugins, before figure
+ -- 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)
+function metapost.analyzeplugins(object) -- each object (first pass)
local prescript = object.prescript -- specifications
if prescript and #prescript > 0 then
return analyzer(object,splitscript(prescript))
end
end
-function metapost.processplugins(object) -- maybe environment table
+function metapost.processplugins(object) -- each object (second pass)
local prescript = object.prescript -- specifications
if prescript and #prescript > 0 then
local before = { }
@@ -674,7 +705,7 @@ end
local basepoints = number.dimenfactors["bp"]
-local cm = function(object)
+local function cm(object)
local op = object.path
local first, second, fourth = op[1], op[2], op[4]
local tx, ty = first.x_coord , first.y_coord
@@ -685,6 +716,12 @@ local cm = function(object)
return sx,rx,ry,sy,tx,ty
end
+-- color
+
+local function cl_reset(t)
+ t[#t+1] = metapost.colorinitializer() -- only color
+end
+
-- text
local tx_done = { }
@@ -710,24 +747,24 @@ local function tx_analyze(object,prescript) -- todo: hash content and reuse them
-- no color
elseif #c == 1 then
if a and t then
- s = format("\\colored[s=%f,a=%f,t=%f]%s",c[1],a,t,s)
+ s = format("\\directcolored[s=%f,a=%f,t=%f]%s",c[1],a,t,s)
else
- s = format("\\colored[s=%f]%s",c[1],s)
+ s = format("\\directcolored[s=%f]%s",c[1],s)
end
elseif #c == 3 then
if a and t then
- s = format("\\colored[r=%f,g=%f,b=%f,a=%f,t=%f]%s",c[1],c[2],c[3],a,t,s)
+ s = format("\\directcolored[r=%f,g=%f,b=%f,a=%f,t=%f]%s",c[1],c[2],c[3],a,t,s)
else
- s = format("\\colored[r=%f,g=%f,b=%f]%s",c[1],c[2],c[3],s)
+ s = format("\\directcolored[r=%f,g=%f,b=%f]%s",c[1],c[2],c[3],s)
end
elseif #c == 4 then
if a and t then
- s = format("\\colored[c=%f,m=%f,y=%f,k=%f,a=%f,t=%f]%s",c[1],c[2],c[3],c[4],a,t,s)
+ s = format("\\directcolored[c=%f,m=%f,y=%f,k=%f,a=%f,t=%f]%s",c[1],c[2],c[3],c[4],a,t,s)
else
- s = format("\\colored[c=%f,m=%f,y=%f,k=%f]%s",c[1],c[2],c[3],c[4],s)
+ s = format("\\directcolored[c=%f,m=%f,y=%f,k=%f]%s",c[1],c[2],c[3],c[4],s)
end
end
- context.MPLIBsettext(tx_number,s)
+ context.MPLIBsettext(tx_number,s) -- combine colored in here, saves call
metapost.multipass = true
end
end
@@ -742,17 +779,19 @@ local function tx_process(object,prescript,before,after)
if trace_textexts then
report_textexts("processing %s (second pass)",tx_number)
end
- before[#before+1] = format("q %f %f %f %f %f %f cm",cm(object))
+ -- before[#before+1] = format("q %f %f %f %f %f %f cm",cm(object))
+ local sx,rx,ry,sy,tx,ty = cm(object)
before[#before+1] = function()
-- flush always happens, we can have a special flush function injected before
local box = textexts[tx_number]
if box then
- context.MPLIBgettextscaled(tx_number,sxsy(box.width,box.height,box.depth))
+ -- context.MPLIBgettextscaled(tx_number,sxsy(box.width,box.height,box.depth))
+ context.MPLIBgettextscaledcm(tx_number,sx,rx,ry,sy,tx,ty,sxsy(box.width,box.height,box.depth))
else
report_textexts("unknown %s",tx_number)
end
end
- before[#before+1] = "Q"
+ -- before[#before+1] = "Q"
if not trace_textexts then
object.path = false -- else: keep it
end
@@ -806,17 +845,24 @@ local function sh_process(object,prescript,before,after)
local value_a, components_a, fractions_a, name_a
local value_b, components_b, fractions_b, name_b
for i=1,#prescript do
+ -- { "sh_color_a", "1" },
+ -- { "sh_color", "into" },
+ -- { "sh_radius_b", "0" },
+ -- { "sh_radius_a", "141.73225" },
+ -- { "sh_center_b", "425.19676 141.73225" },
+ -- { "sh_center_a", "425.19676 0" },
+ -- { "sh_factor", "1" },
local tag = prescript[i][1]
if not name_a and tag == "sh_color_a" then
- value_a = prescript[i-4][2]
- components_a = prescript[i-3][2]
- fractions_a = prescript[i-2][2]
- name_a = prescript[i-1][2]
+ value_a = prescript[i-5][2]
+ components_a = prescript[i-4][2]
+ fractions_a = prescript[i-3][2]
+ name_a = prescript[i-2][2]
elseif not name_b and tag == "sh_color_b" then
- value_b = prescript[i-4][2]
- components_b = prescript[i-3][2]
- fractions_b = prescript[i-2][2]
- name_b = prescript[i-1][2]
+ value_b = prescript[i-5][2]
+ components_b = prescript[i-4][2]
+ fractions_b = prescript[i-3][2]
+ name_b = prescript[i-2][2]
end
if name_a and name_b then
break
@@ -846,7 +892,10 @@ local function sh_process(object,prescript,before,after)
-- fatal error
end
before[#before+1], after[#after+1] = "q /Pattern cs", format("W n /%s sh Q",name)
- object.color, object.type, object.grouped = false, false, true -- not nil, otherwise mt
+ -- false, not nil, else mt triggered
+ object.colored = false
+ object.type = false
+ object.grouped = true
end
end
@@ -886,6 +935,7 @@ local function ps_process(object,prescript,before,after)
before[#before+1] = function()
context.MPLIBpositionwhd(ps_label,x,y,w,h)
end
+ object.path = false
end
end
@@ -894,7 +944,7 @@ end
local function fg_process(object,prescript,before,after)
local fg_name = prescript.fg_name
if fg_name then
- before[#before+1] = format("q %f %f %f %f %f %f cm",cm(object))
+ before[#before+1] = format("q %f %f %f %f %f %f cm",cm(object)) -- beware: does not use the cm stack
before[#before+1] = function()
context.MPLIBfigure(fg_name,prescript.fg_mask or "")
end
@@ -911,35 +961,77 @@ local value = Cs ( (
+ P(","))^1
)
+-- should be codeinjections
+
+local t_list = attributes.list[attributes.private('transparency')]
+local c_list = attributes.list[attributes.private('color')]
+
local function tr_process(object,prescript,before,after)
-- before can be shortcut to t
local tr_alternative = prescript.tr_alternative
if tr_alternative then
tr_alternative = tonumber(tr_alternative)
local tr_transparency = tonumber(prescript.tr_transparency)
- before[#before+1], after[#after+1] = format("/Tr%s gs",registertransparency(nil,tr_alternative,tr_transparency,true)), "/Tr0 gs" -- outertransparency
+ before[#before+1] = format("/Tr%s gs",registertransparency(nil,tr_alternative,tr_transparency,true))
+ after[#after+1] = "/Tr0 gs" -- outertransparency
end
local cs = object.color
if cs and #cs > 0 then
- local sp_name = prescript.sp_name
- local b, a
- if sp_name then
+ local c_b, c_a
+ local sp_type = prescript.sp_type
+ if not sp_type then
+ c_b, c_a = colorconverter(cs)
+ elseif sp_type == "spot" or sp_type == "multitone" then
+ local sp_name = prescript.sp_name or "black"
local sp_fractions = prescript.sp_fractions or 1
local sp_components = prescript.sp_components or ""
local sp_value = prescript.sp_value or "1"
local cf = cs[1]
if cf ~= 1 then
-- beware, we do scale the spotcolors but not the alternative representation
- sp_value = lpeg.match(value,sp_value,1,cf) or sp_value
+ sp_value = lpegmatch(value,sp_value,1,cf) or sp_value
end
- -- should be codeinjections
- b, a = spotcolorconverter(sp_name,sp_fractions,sp_components,sp_value)
- else
- -- should be codeinjections
- b, a = colorconverter(cs)
+ c_b, c_a = spotcolorconverter(sp_name,sp_fractions,sp_components,sp_value)
+ elseif sp_type == "named" then
+ -- we might move this to another namespace .. also, named can be a spotcolor
+ -- so we need to check for that too ... also we need to resolve indirect
+ -- colors so we might need the second pass for this (draw dots with \MPcolor)
+ local sp_name = prescript.sp_name or "black"
+ if not tr_alternative then
+ -- todo: sp_name is not yet registered at this time
+ local t = t_list[sp_name] -- string or attribute
+ local v = t and attributes.transparencies.value(t)
+ if v then
+ before[#before+1] = format("/Tr%s gs",registertransparency(nil,v[1],v[2],true))
+ after[#after+1] = "/Tr0 gs" -- outertransparency
+ end
+ end
+ local c = c_list[sp_name] -- string or attribute
+ local v = c and attributes.colors.value(c)
+ if v then
+ -- all=1 gray=2 rgb=3 cmyk=4
+ local colorspace = v[1]
+ local f = cs[1]
+ if colorspace == 2 then
+ local s = f*v[2]
+ c_b, c_a = checked_color_pair(format("%.3f g %.3f G",s,s))
+ elseif colorspace == 3 then
+ local r, g, b = f*v[3], f*v[4], f*v[5]
+ c_b, c_a = checked_color_pair(format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b))
+ elseif colorspace == 4 or colorspace == 1 then
+ local c, m, y, k = f*v[6], f*v[7], f*v[8], f*v[9]
+ c_b, c_a = checked_color_pair(format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k))
+ else
+ local s = f*v[2]
+ c_b, c_a = checked_color_pair(format("%.3f g %.3f G",s,s))
+ end
+ end
+ --
+ end
+ if c_a and c_b then
+ before[#before+1] = c_b
+ after[#after+1] = c_a
end
- before[#before+1] = b
- after[#after+1] = a
end
end
@@ -953,12 +1045,47 @@ local function la_process(object,prescript,before,after)
end
end
+-- groups
+
+local types = {
+ isolated
+}
+
+local function gr_process(object,prescript,before,after)
+ local gr_state = prescript.gr_state
+ if gr_state then
+ if gr_state == "start" then
+ local gr_type = utilities.parsers.settings_to_hash(prescript.gr_type)
+ before[#before+1] = function()
+ context.MPLIBstartgroup(
+ gr_type.isolated and 1 or 0,
+ gr_type.knockout and 1 or 0,
+ prescript.gr_llx,
+ prescript.gr_lly,
+ prescript.gr_urx,
+ prescript.gr_ury
+ )
+ end
+ elseif gr_state == "stop" then
+ after[#after+1] = function()
+ context.MPLIBstopgroup()
+ end
+ end
+ object.path = false
+ object.color = false
+ object.grouped = true
+ end
+end
+
-- definitions
-appendaction(resetteractions,"system",tx_reset)
+appendaction(resetteractions, "system",cl_reset)
+appendaction(resetteractions, "system",tx_reset)
+
+appendaction(processoractions,"system",gr_process)
-appendaction(analyzeractions,"system",tx_analyze)
-appendaction(analyzeractions,"system",gt_analyze)
+appendaction(analyzeractions, "system",tx_analyze)
+appendaction(analyzeractions, "system",gt_analyze)
appendaction(processoractions,"system",sh_process)
-- (processoractions,"system",gt_process)
@@ -970,8 +1097,8 @@ appendaction(processoractions,"system",tr_process) -- last, as color can be rese
appendaction(processoractions,"system",la_process)
--- no auto here
+-- we're nice and set them already
-resetter = sequencers.compile(resetteractions )
-analyzer = sequencers.compile(analyzeractions )
-processor = sequencers.compile(processoractions)
+resetter = resetteractions .runner
+analyzer = analyzeractions .runner
+processor = processoractions.runner