diff options
author | Norbert Preining <preining@logic.at> | 2019-02-24 15:12:57 +0000 |
---|---|---|
committer | Norbert Preining <preining@logic.at> | 2019-02-24 15:12:57 +0000 |
commit | 1314fbe93790c501dc436a5cf99f106b9e5c0f63 (patch) | |
tree | 04dc7734c8be8ffe385d41f4388826ef5857b6f9 /Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua | |
parent | eb80ce7b34f59896a1dfee5ca422495394d6677f (diff) |
Revert "ConTeXt version 2019.02.22 19:35"
This reverts commit 5c6357cdb820b4f628d036ba7b2248f221d50c0b.
git-svn-id: svn://tug.org/texlive/trunk@50112 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua | 598 |
1 files changed, 310 insertions, 288 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua b/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua index 92fde5e1369..75f810fb33b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/mlib-pdf.lua @@ -6,8 +6,9 @@ if not modules then modules = { } end modules ['mlib-pdf'] = { license = "see context related readme files", } -local gsub = string.gsub -local concat, insert, remove = table.concat, table.insert, table.remove +-- maybe %s is better than %f + +local format, concat, gsub = string.format, table.concat, string.gsub local abs, sqrt, round = math.abs, math.sqrt, math.round local setmetatable, rawset, tostring, tonumber, type = setmetatable, rawset, tostring, tonumber, type local P, S, C, Ct, Cc, Cg, Cf, Carg = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Carg @@ -40,34 +41,23 @@ local pdfflusher = { } metapost.flushers.pdf = pdfflusher metapost.n = 0 +metapost.optimize = true -- false local experiment = true -- uses context(node) that already does delayed nodes local savedliterals = nil -- needs checking -local mpsliteral = nodes.pool.originliteral - -local f_f = formatters["%.6F"] -local f_m = formatters["%.6F %.6F m"] -local f_c = formatters["%.6F %.6F %.6F %.6F %.6F %.6F c"] -local f_l = formatters["%.6F %.6F l"] -local f_cm = formatters["%.6F %.6F %.6F %.6F %.6F %.6F cm"] -local f_M = formatters["%.6F M"] +local mpsliteral = nodes.pool.register(node.new("whatsit",nodes.whatsitcodes.pdfliteral)) -- pdfliteral.mode = 1 + +local f_f = formatters["%F"] + +local f_m = formatters["%F %F m"] +local f_c = formatters["%F %F %F %F %F %F c"] +local f_l = formatters["%F %F l"] +local f_cm = formatters["%F %F %F %F %F %F cm"] +local f_M = formatters["%F M"] local f_j = formatters["%i j"] local f_J = formatters["%i J"] -local f_d = formatters["[%s] %.6F d"] -local f_w = formatters["%.3F w"] - -directives.register("metapost.stripzeros",function() - f_f = formatters["%.6N"] - f_m = formatters["%.6N %.6N m"] - f_c = formatters["%.6N %.6N %.6N %.6N %.6N %.6N c"] - f_l = formatters["%.6N %.6N l"] - f_cm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N cm"] - f_M = formatters["%.6N M"] - f_j = formatters["%i j"] - f_J = formatters["%i J"] - f_d = formatters["[%s] %.6N d"] - f_w = formatters["%.3N w"] -end) +local f_d = formatters["[%s] %F d"] +local f_w = formatters["%F w"] directives.register("metapost.savetable",function(v) if type(v) == "string" then @@ -83,28 +73,60 @@ trackers.register("metapost.forcestroke",function(v) force_stroke = v end) +local pdfliteral = function(pdfcode) + local literal = copy_node(mpsliteral) + literal.data = pdfcode + return literal +end + -- Because in MKiV we always have two passes, we save the objects. When an extra -- mp run is done (due to for instance texts identifier in the parse pass), we -- get a new result table and the stored objects are forgotten. Otherwise they -- are reused. local function getobjects(result,figure,index) - return figure:objects() + if metapost.optimize then + local robjects = result.objects + if not robjects then + robjects = { } + result.objects = robjects + end + local fobjects = robjects[index or 1] + if not fobjects then + fobjects = figure:objects() + robjects[index] = fobjects + end + return fobjects + else + return figure:objects() + end end -function metapost.convert(specification,result) - local flusher = specification.flusher - local askedfig = specification.askedfig - if save_table then - table.save(save_table,metapost.totable(result,1)) -- direct +function metapost.convert(result, trialrun, flusher, multipass, askedfig) + if trialrun then + local multipassindeed = metapost.parse(result,askedfig) + if multipass and not multipassindeed and metapost.optimize then + if save_table then + table.save(save_table,metapost.totable(result,1)) -- direct + end + metapost.flush(result,flusher,askedfig) -- saves a run + else + return false + end + else + if save_table then + table.save(save_table,metapost.totable(result,1)) -- direct + end + metapost.flush(result,flusher,askedfig) end - metapost.flush(specification,result) return true -- done end function metapost.flushliteral(d) if savedliterals then - write_node(mpsliteral(savedliterals[d])) + local literal = copy_node(mpsliteral) + literal.data = savedliterals[d] + write_node(literal) else report_metapost("problem flushing literal %a",d) end @@ -118,7 +140,7 @@ function pdfflusher.comment(message) if message then message = formatters["%% mps graphic %s: %s"](metapost.n,message) if experiment then - context(mpsliteral(message)) + context(pdfliteral(message)) elseif savedliterals then local last = #savedliterals + 1 savedliterals[last] = message @@ -147,7 +169,7 @@ function pdfflusher.flushfigure(pdfliterals) -- table if #pdfliterals > 0 then pdfliterals = concat(pdfliterals,"\n") if experiment then - context(mpsliteral(pdfliterals)) + context(pdfliteral(pdfliterals)) else if savedliterals then local last = #savedliterals + 1 @@ -298,6 +320,15 @@ local p_boolean = P("false") * Cc(false) + P("true") * Cc(true) local p_set = Ct(number^1) local p_path = Ct(Ct(number * number^-5)^1) +-- local variable = +-- P("1:") * key * p_number +-- + P("2:") * key * p_string +-- + P("3:") * key * p_boolean +-- + S("4568") * P(":") * key * p_set +-- + P("7:") * key * p_path +-- +-- local pattern_key = Cf ( Carg(1) * (Cg(variable * newline^0)^0), rawset) + local variable = P("1:") * p_number + P("2:") * p_string @@ -343,9 +374,7 @@ function metapost.processspecial(str) end end -local stack = { } - -local function pushproperties(figure) +local function setproperties(figure) local boundingbox = figure:boundingbox() local properties = { llx = boundingbox[1], @@ -359,321 +388,313 @@ local function pushproperties(figure) italic = figure:italcorr(), number = figure:charcode() or 0, } - insert(stack,properties) metapost.properties = properties return properties end -local function popproperties() - metapost.properties = remove(stack) -end - local function nocomment() end metapost.comment = nocomment -function metapost.flush(specification,result) +function metapost.flush(result,flusher,askedfig) if result then - local flusher = specification.flusher - local askedfig = specification.askedfig - local incontext = specification.incontext - local figures = result.fig + local figures = result.fig if figures then flusher = flusher or pdfflusher - local resetplugins = metapost.resetplugins or ignore -- before figure - local processplugins = metapost.processplugins or ignore -- each object + local resetplugins = metapost.resetplugins or ignore -- before figure + local processplugins = metapost.processplugins or ignore -- each object local synchronizeplugins = metapost.synchronizeplugins or ignore - local pluginactions = metapost.pluginactions or ignore -- before / after - local startfigure = flusher.startfigure - local stopfigure = flusher.stopfigure - local flushfigure = flusher.flushfigure - local textfigure = flusher.textfigure - local processspecial = flusher.processspecial or metapost.processspecial - metapost.comment = flusher.comment or nocomment + local pluginactions = metapost.pluginactions or ignore -- before / after + local startfigure = flusher.startfigure + local stopfigure = flusher.stopfigure + local flushfigure = flusher.flushfigure + local textfigure = flusher.textfigure + local processspecial = flusher.processspecial or metapost.processspecial + metapost.comment = flusher.comment or nocomment for index=1,#figures do - local figure = figures[index] - local properties = pushproperties(figure) + local figure = figures[index] + local properties = setproperties(figure) if askedfig == "direct" or askedfig == "all" or askedfig == properties.number then - local objects = getobjects(result,figure,index) - local result = { } - local miterlimit = -1 - local linecap = -1 - local linejoin = -1 - local dashed = false - local llx = properties.llx - local lly = properties.lly - local urx = properties.urx - local ury = properties.ury + local objects = getobjects(result,figure,index) + local result = { } + local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false + local llx = properties.llx + local lly = properties.lly + local urx = properties.urx + local ury = properties.ury if urx < llx then -- invalid startfigure(properties.number,0,0,0,0,"invalid",figure) stopfigure() else - - -- we need to be indirect if we want the one-pass solution - - local function processfigure() - result[#result+1] = "q" - if objects then - -- resetplugins(result) -- we should move the colorinitializer here - local savedpath = nil - local savedhtap = nil - for o=1,#objects do - local object = objects[o] - local objecttype = object.type - if objecttype == "text" then - result[#result+1] = "q" - local ot = object.transform -- 3,4,5,6,1,2 - result[#result+1] = f_cm(ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) - flushfigure(result) -- flush accumulated literals - result = { } - textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth) - result[#result+1] = "Q" - elseif objecttype == "special" then - if processspecial then - processspecial(object.prescript) + startfigure(properties.number,llx,lly,urx,ury,"begin",figure) + result[#result+1] = "q" + if objects then + resetplugins(result) -- we should move the colorinitializer here + local savedpath = nil + local savedhtap = nil + for o=1,#objects do + local object = objects[o] + local objecttype = object.type + if objecttype == "text" then + result[#result+1] = "q" + local ot = object.transform -- 3,4,5,6,1,2 + result[#result+1] = f_cm(ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) -- TH: formatters["%F %F m %F %F %F %F 0 0 cm"](unpack(ot)) + flushfigure(result) -- flush accumulated literals + result = { } + textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth) + result[#result+1] = "Q" + elseif objecttype == "special" then + if processspecial then + processspecial(object.prescript) + end + elseif objecttype == "start_clip" then + local evenodd = not object.istext and object.postscript == "evenodd" + result[#result+1] = "q" + flushnormalpath(object.path,result,false) + result[#result+1] = evenodd and "W* n" or "W n" + elseif objecttype == "stop_clip" then + result[#result+1] = "Q" + miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false + elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then + -- skip + else + -- we use an indirect table as we want to overload + -- entries but this is not possible in userdata + -- + -- can be optimized if no path + -- + local original = object + local object = { } + setmetatable(object, { + __index = original + }) + -- first we analyze + local before, after = processplugins(object) + local evenodd, collect, both = false, false, false + local postscript = object.postscript + if not object.istext then + if postscript == "evenodd" then + evenodd = true + elseif postscript == "collect" then + collect = true + elseif postscript == "both" then + both = true + elseif postscript == "eoboth" then + evenodd = true + both = true + end + end + -- + if collect then + if not savedpath then + savedpath = { object.path or false } + savedhtap = { object.htap or false } + else + savedpath[#savedpath+1] = object.path or false + savedhtap[#savedhtap+1] = object.htap or false end - elseif objecttype == "start_clip" then - local evenodd = not object.istext and object.postscript == "evenodd" - result[#result+1] = "q" - flushnormalpath(object.path,result,false) - result[#result+1] = evenodd and "W* n" or "W n" - elseif objecttype == "stop_clip" then - result[#result+1] = "Q" - miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false - elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then - -- skip else - -- we use an indirect table as we want to overload - -- entries but this is not possible in userdata - -- - -- can be optimized if no path - -- - local original = object - local object = { } - setmetatable(object, { - __index = original - }) - local before, - after = processplugins(object) - local evenodd = false - local collect = false - local both = false - local postscript = object.postscript - if not object.istext then - if postscript == "evenodd" then - evenodd = true - elseif postscript == "collect" then - collect = true - elseif postscript == "both" then - both = true - elseif postscript == "eoboth" then - evenodd = true - both = true - end + local objecttype = object.type -- can have changed + if before then + result = pluginactions(before,result,flushfigure) end - -- - if collect then - if not savedpath then - savedpath = { object.path or false } - savedhtap = { object.htap or false } - else - savedpath[#savedpath+1] = object.path or false - savedhtap[#savedhtap+1] = object.htap or false + local ml = object.miterlimit + if ml and ml ~= miterlimit then + miterlimit = ml + result[#result+1] = f_M(ml) + end + local lj = object.linejoin + if lj and lj ~= linejoin then + linejoin = lj + result[#result+1] = f_j(lj) + end + local lc = object.linecap + if lc and lc ~= linecap then + linecap = lc + result[#result+1] = f_J(lc) + end + if both then + if dashed ~= false then -- was just dashed test + result[#result+1] = "[] 0 d" + dashed = false end else - local objecttype = object.type -- can have changed - if before then - result = pluginactions(before,result,flushfigure) - end - local ml = object.miterlimit - if ml and ml ~= miterlimit then - miterlimit = ml - result[#result+1] = f_M(ml) - end - local lj = object.linejoin - if lj and lj ~= linejoin then - linejoin = lj - result[#result+1] = f_j(lj) - end - local lc = object.linecap - if lc and lc ~= linecap then - linecap = lc - result[#result+1] = f_J(lc) + local dl = object.dash + if dl then + local d = f_d(concat(dl.dashes or {}," "),dl.offset) + if d ~= dashed then + dashed = d + result[#result+1] = d + end + elseif dashed ~= false then -- was just dashed test + result[#result+1] = "[] 0 d" + dashed = false end - if both then - if dashed ~= false then -- was just dashed test - result[#result+1] = "[] 0 d" - dashed = false + end + local path = object.path -- newpath + local transformed, penwidth = false, 1 + local open = path and path[1].left_type and path[#path].right_type -- at this moment only "end_point" + local pen = object.pen + if pen then + if pen.type == 'elliptical' then + transformed, penwidth = pen_characteristics(original) -- boolean, value + result[#result+1] = f_w(penwidth) -- todo: only if changed + if objecttype == 'fill' then + objecttype = 'both' end - else - local dl = object.dash - if dl then - local d = f_d(concat(dl.dashes or {}," "),dl.offset) - if d ~= dashed then - dashed = d - result[#result+1] = d + else -- calculated by mplib itself + objecttype = 'fill' + end + end + if transformed then + result[#result+1] = "q" + end + if path then + if savedpath then + for i=1,#savedpath do + local path = savedpath[i] + if transformed then + flushconcatpath(path,result,open) + else + flushnormalpath(path,result,open) end - elseif dashed ~= false then -- was just dashed test - result[#result+1] = "[] 0 d" - dashed = false end - end - local path = object.path -- newpath - local transformed = false - local penwidth = 1 - local open = path and path[1].left_type and path[#path].right_type -- at this moment only "end_point" - local pen = object.pen - if pen then - if pen.type == "elliptical" then - transformed, penwidth = pen_characteristics(original) -- boolean, value - result[#result+1] = f_w(penwidth) -- todo: only if changed - if objecttype == "fill" then - objecttype = "both" - end - else -- calculated by mplib itself - objecttype = "fill" - end + savedpath = nil end if transformed then - result[#result+1] = "q" + flushconcatpath(path,result,open) + else + flushnormalpath(path,result,open) end - if path then - if savedpath then - for i=1,#savedpath do - local path = savedpath[i] - if transformed then - flushconcatpath(path,result,open) - else - flushnormalpath(path,result,open) - end - end - savedpath = nil - end - if transformed then - flushconcatpath(path,result,open) + if force_stroke then + result[#result+1] = open and "S" or "h S" + elseif objecttype == "fill" then + result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo + elseif objecttype == "outline" then + if both then + result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo else - flushnormalpath(path,result,open) - end - if force_stroke then result[#result+1] = open and "S" or "h S" - elseif objecttype == "fill" then - result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo - elseif objecttype == "outline" then - if both then - result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo - else - result[#result+1] = open and "S" or "h S" - end - elseif objecttype == "both" then - result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath end + elseif objecttype == "both" then + result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath end + end + if transformed then + result[#result+1] = "Q" + end + local path = object.htap + if path then if transformed then - result[#result+1] = "Q" + result[#result+1] = "q" end - local path = object.htap - if path then - if transformed then - result[#result+1] = "q" - end - if savedhtap then - for i=1,#savedhtap do - local path = savedhtap[i] - if transformed then - flushconcatpath(path,result,open) - else - flushnormalpath(path,result,open) - end + if savedhtap then + for i=1,#savedhtap do + local path = savedhtap[i] + if transformed then + flushconcatpath(path,result,open) + else + flushnormalpath(path,result,open) end - savedhtap = nil - evenodd = true - end - if transformed then - flushconcatpath(path,result,open) - else - flushnormalpath(path,result,open) - end - if force_stroke then - result[#result+1] = open and "S" or "h S" - elseif objecttype == "fill" then - result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo - elseif objecttype == "outline" then - result[#result+1] = open and "S" or "h S" - elseif objecttype == "both" then - result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath - end - if transformed then - result[#result+1] = "Q" end + savedhtap = nil + evenodd = true + end + if transformed then + flushconcatpath(path,result,open) + else + flushnormalpath(path,result,open) end - if after then - result = pluginactions(after,result,flushfigure) + if force_stroke then + result[#result+1] = open and "S" or "h S" + elseif objecttype == "fill" then + result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo + elseif objecttype == "outline" then + result[#result+1] = open and "S" or "h S" + elseif objecttype == "both" then + result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath + end + if transformed then + result[#result+1] = "Q" end end - if object.grouped then - -- can be qQ'd so changes can end up in groups - miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false + if after then + result = pluginactions(after,result,flushfigure) end end + if object.grouped then + -- can be qQ'd so changes can end up in groups + miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false + end end end - result[#result+1] = "Q" - flushfigure(result) - end - startfigure(properties.number,llx,lly,urx,ury,"begin",figure) - if incontext then - context(function() processfigure() end) - else - processfigure() end + result[#result+1] = "Q" + flushfigure(result) stopfigure("end") - end if askedfig ~= "all" then break end end - popproperties() end metapost.comment = nocomment - resetplugins(result) -- we should move the colorinitializer here end end end --- tracing: - -do - - local result = { } - - local flusher = { - startfigure = function() - result = { } - context.startnointerference() - end, - flushfigure = function(literals) - local n = #result - for i=1,#literals do - result[n+i] = literals[i] +function metapost.parse(result,askedfig) + if result then + local figures = result.fig + if figures then + local multipass = false + local analyzeplugins = metapost.analyzeplugins -- each object + for index=1,#figures do + local figure = figures[index] + local properties = setproperties(figure) + if askedfig == "direct" or askedfig == "all" or askedfig == properties.number then + local objects = getobjects(result,figure,index) + if objects then + for o=1,#objects do + if analyzeplugins(objects[o]) then + multipass = true + end + end + end + if askedfig ~= "all" then + break + end + end end - end, - stopfigure = function() - context.stopnointerference() + return multipass end - } + end +end - local specification = { - flusher = flusher, - -- incontext = true, - } +-- tracing: - function metapost.pdfliterals(result) - metapost.flush(specification,result) - return result +local result = { } + +local flusher = { + startfigure = function() + result = { } + context.startnointerference() + end, + flushfigure = function(literals) + local n = #result + for i=1,#literals do + result[n+i] = literals[i] + end + end, + stopfigure = function() + context.stopnointerference() end +} +function metapost.pdfliterals(result) + metapost.flush(result,flusher) + return result end function metapost.totable(result,askedfig) @@ -681,6 +702,7 @@ function metapost.totable(result,askedfig) local figure = result and result.fig and result.fig[1] if figure then local results = { } + -- local objects = figure:objects() local objects = getobjects(result,figure,askedfig) for o=1,#objects do local object = objects[o] |