diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mlib-pps.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mlib-pps.lua | 293 |
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 |