diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mlib-pdf.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mlib-pdf.lua | 295 |
1 files changed, 152 insertions, 143 deletions
diff --git a/Master/texmf-dist/tex/context/base/mlib-pdf.lua b/Master/texmf-dist/tex/context/base/mlib-pdf.lua index d25dde88469..8de09f42a60 100644 --- a/Master/texmf-dist/tex/context/base/mlib-pdf.lua +++ b/Master/texmf-dist/tex/context/base/mlib-pdf.lua @@ -19,13 +19,19 @@ local report_metapost = logs.reporter("metapost") local trace_variables = false trackers.register("metapost.variables",function(v) trace_variables = v end) -local mplib, context = mplib, context +local mplib = mplib +local context = context local allocate = utilities.storage.allocate local copy_node = node.copy local write_node = node.write +local pen_info = mplib.pen_info +local object_fields = mplib.fields + +local save_table = false + metapost = metapost or { } local metapost = metapost @@ -33,7 +39,6 @@ metapost.flushers = metapost.flushers or { } local pdfflusher = { } metapost.flushers.pdf = pdfflusher -metapost.multipass = false -- to be stacked metapost.n = 0 metapost.optimize = true -- false @@ -53,9 +58,19 @@ local f_J = formatters["%i J"] local f_d = formatters["[%s] %F d"] local f_w = formatters["%F w"] -local pdfliteral = function(s) +directives.register("metapost.savetable",function(v) + if type(v) == "string" then + save_table = file.addsuffix(v,"mpl") + elseif v then + save_table = file.addsuffix(environment.jobname .. "-graphic","mpl") + else + save_table = false + end +end) + +local pdfliteral = function(pdfcode) local literal = copy_node(mpsliteral) - literal.data = s + literal.data = pdfcode return literal end @@ -64,18 +79,19 @@ end -- get a new result table and the stored objects are forgotten. Otherwise they -- are reused. -local function getobjects(result,figure,f) +local function getobjects(result,figure,index) if metapost.optimize then - local objects = result.objects - if not objects then - result.objects = { } + local robjects = result.objects + if not robjects then + robjects = { } + result.objects = robjects end - objects = result.objects[f] - if not objects then - objects = figure:objects() - result.objects[f] = objects + local fobjects = robjects[index or 1] + if not fobjects then + fobjects = figure:objects() + robjects[index] = fobjects end - return objects + return fobjects else return figure:objects() end @@ -83,15 +99,20 @@ end function metapost.convert(result, trialrun, flusher, multipass, askedfig) if trialrun then - metapost.multipass = false - metapost.parse(result, askedfig) - if multipass and not metapost.multipass and metapost.optimize then - metapost.flush(result, flusher, askedfig) -- saves a run + 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 - metapost.flush(result, flusher, askedfig) + if save_table then + table.save(save_table,metapost.totable(result,1)) -- direct + end + metapost.flush(result,flusher,askedfig) end return true -- done end @@ -168,8 +189,6 @@ local bend_tolerance = 131/65536 local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1 -local pen_info = mplib.pen_info - local function pen_characteristics(object) local t = pen_info(object) rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty @@ -323,32 +342,8 @@ local variable = local pattern_lst = (variable * newline^0)^0 -metapost.variables = { } -- to be stacked -metapost.llx = 0 -- to be stacked -metapost.lly = 0 -- to be stacked -metapost.urx = 0 -- to be stacked -metapost.ury = 0 -- to be stacked - -function commands.mprunvar(key,n) -- should be defined in another lib - local value = metapost.variables[key] - if value ~= nil then - local tvalue = type(value) - if tvalue == "table" then - local ntype = type(n) - if ntype == "number" then - context(value[n]) - elseif ntype == "string" then - context(concat(value,n)) - else - context(concat(value," ")) - end - elseif tvalue == "number" or tvalue == "boolean" then - context(tostring(value)) - elseif tvalue == "string" then - context(value) - end - end -end +metapost.variables = { } -- to be stacked +metapost.properties = { } -- to be stacked function metapost.untagvariable(str,variables) -- will be redone if variables == false then @@ -374,6 +369,30 @@ function metapost.processspecial(str) end end +local function setproperties(figure) + local boundingbox = figure:boundingbox() + local properties = { + llx = boundingbox[1], + lly = boundingbox[2], + urx = boundingbox[3], + ury = boundingbox[4], + slot = figure:charcode(), + width = figure:width(), + height = figure:height(), + depth = figure:depth(), + italic = figure:italcorr(), + number = figure:charcode() or 0, + } + metapost.properties = properties + return properties +end + +local function setvariables(figure) + local variables = { } + metapost.variables = variables + return variables +end + function metapost.flush(result,flusher,askedfig) if result then local figures = result.fig @@ -388,42 +407,27 @@ function metapost.flush(result,flusher,askedfig) local flushfigure = flusher.flushfigure local textfigure = flusher.textfigure local processspecial = flusher.processspecial or metapost.processspecial - for f=1,#figures do - local figure = figures[f] - local objects = getobjects(result,figure,f) - local fignum = figure:charcode() or 0 - if askedfig == "direct" or askedfig == "all" or askedfig == fignum then - local t = { } + local variables = setvariables(figure) -- also resets then in case of not found + 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) + local result = { } local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false - local bbox = figure:boundingbox() - local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] - local variables = { } - metapost.variables = variables - metapost.properties = { - llx = llx, - lly = lly, - urx = urx, - ury = ury, - slot = figure:charcode(), - width = figure:width(), - height = figure:height(), - depth = figure:depth(), - italic = figure:italcorr(), - } - -- replaced by the above - metapost.llx = llx - metapost.lly = lly - metapost.urx = urx - metapost.ury = ury + local llx = properties.llx + local lly = properties.lly + local urx = properties.urx + local ury = properties.ury if urx < llx then -- invalid - startfigure(fignum,0,0,0,0,"invalid",figure) + startfigure(properties.number,0,0,0,0,"invalid",figure) stopfigure() else - startfigure(fignum,llx,lly,urx,ury,"begin",figure) - t[#t+1] = "q" + startfigure(properties.number,llx,lly,urx,ury,"begin",figure) + result[#result+1] = "q" if objects then - resetplugins(t) -- we should move the colorinitializer here + resetplugins(result) -- we should move the colorinitializer here for o=1,#objects do local object = objects[o] local objecttype = object.type @@ -434,20 +438,21 @@ function metapost.flush(result,flusher,askedfig) processspecial(object.prescript) end elseif objecttype == "start_clip" then - t[#t+1] = "q" - flushnormalpath(object.path,t,false) - t[#t+1] = "W n" + 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 - t[#t+1] = "Q" - miterlimit, linecap, linejoin, dashed = -1, -1, -1, false + result[#result+1] = "Q" + miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false elseif objecttype == "text" then - t[#t+1] = "q" + result[#result+1] = "q" local ot = object.transform -- 3,4,5,6,1,2 - t[#t+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(t) -- flush accumulated literals - t = { } + 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) - t[#t+1] = "Q" + result[#result+1] = "Q" else -- we use an indirect table as we want to overload -- entries but this is not possible in userdata @@ -463,32 +468,32 @@ function metapost.flush(result,flusher,askedfig) local before, after = processplugins(object) local objecttype = object.type -- can have changed if before then - t = pluginactions(before,t,flushfigure) + result = pluginactions(before,result,flushfigure) end local ml = object.miterlimit if ml and ml ~= miterlimit then miterlimit = ml - t[#t+1] = f_M(ml) + result[#result+1] = f_M(ml) end local lj = object.linejoin if lj and lj ~= linejoin then linejoin = lj - t[#t+1] = f_j(lj) + result[#result+1] = f_j(lj) end local lc = object.linecap if lc and lc ~= linecap then linecap = lc - t[#t+1] = f_J(lc) + result[#result+1] = f_J(lc) end local dl = object.dash if dl then local d = f_d(concat(dl.dashes or {}," "),dl.offset) if d ~= dashed then dashed = d - t[#t+1] = dashed + result[#result+1] = d end - elseif dashed then - t[#t+1] = "[] 0 d" + elseif dashed ~= false then -- was just dashed test + result[#result+1] = "[] 0 d" dashed = false end local path = object.path -- newpath @@ -498,7 +503,7 @@ function metapost.flush(result,flusher,askedfig) if pen then if pen.type == 'elliptical' then transformed, penwidth = pen_characteristics(original) -- boolean, value - t[#t+1] = f_w(penwidth) -- todo: only if changed + result[#result+1] = f_w(penwidth) -- todo: only if changed if objecttype == 'fill' then objecttype = 'both' end @@ -507,58 +512,59 @@ function metapost.flush(result,flusher,askedfig) end end if transformed then - t[#t+1] = "q" + result[#result+1] = "q" end + local evenodd = not object.istext and object.postscript == "evenodd" if path then if transformed then - flushconcatpath(path,t,open) + flushconcatpath(path,result,open) else - flushnormalpath(path,t,open) + flushnormalpath(path,result,open) end if objecttype == "fill" then - t[#t+1] = "h f" + result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo elseif objecttype == "outline" then - t[#t+1] = open and "S" or "h S" + result[#result+1] = open and "S" or "h S" elseif objecttype == "both" then - t[#t+1] = "h B" + result[#result+1] = evenodd and "h B*" or "h B"-- B* = eo -- b includes closepath end end if transformed then - t[#t+1] = "Q" + result[#result+1] = "Q" end local path = object.htap if path then if transformed then - t[#t+1] = "q" + result[#result+1] = "q" end if transformed then - flushconcatpath(path,t,open) + flushconcatpath(path,result,open) else - flushnormalpath(path,t,open) + flushnormalpath(path,result,open) end if objecttype == "fill" then - t[#t+1] = "h f" + result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo elseif objecttype == "outline" then - t[#t+1] = open and "S" or "h S" + result[#result+1] = open and "S" or "h S" elseif objecttype == "both" then - t[#t+1] = "h B" + result[#result+1] = evenodd and "h B*" or "h B"-- B* = eo -- b includes closepath end if transformed then - t[#t+1] = "Q" + result[#result+1] = "Q" end end if after then - t = pluginactions(after,t,flushfigure) + result = pluginactions(after,result,flushfigure) end if object.grouped then -- can be qQ'd so changes can end up in groups - miterlimit, linecap, linejoin, dashed = -1, -1, -1, false + miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false end end end end - t[#t+1] = "Q" - flushfigure(t) + result[#result+1] = "Q" + flushfigure(result) stopfigure("end") end if askedfig ~= "all" then @@ -574,20 +580,18 @@ 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 f=1,#figures do - local figure = figures[f] - local fignum = figure:charcode() or 0 - if askedfig == "direct" or askedfig == "all" or askedfig == fignum then - local bbox = figure:boundingbox() - metapost.llx = bbox[1] - metapost.lly = bbox[2] - metapost.urx = bbox[3] - metapost.ury = bbox[4] - local objects = getobjects(result,figure,f) + 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 - analyzeplugins(objects[o]) + if analyzeplugins(objects[o]) then + multipass = true + end end end if askedfig ~= "all" then @@ -595,24 +599,24 @@ function metapost.parse(result,askedfig) end end end + return multipass end end end -- tracing: -local t = { } +local result = { } local flusher = { startfigure = function() - t = { } + result = { } context.startnointerference() end, flushfigure = function(literals) - local n = #t - for i=1, #literals do - n = n + 1 - t[n] = literals[i] + local n = #result + for i=1,#literals do + result[n+i] = literals[i] end end, stopfigure = function() @@ -622,30 +626,35 @@ local flusher = { function metapost.pdfliterals(result) metapost.flush(result,flusher) - return t + return result end --- so far - -function metapost.totable(result) - local figure = result and result.fig and result.fig[1] +function metapost.totable(result,askedfig) + local askedfig = askedfig or 1 + local figure = result and result.fig and result.fig[1] if figure then - local t = { } - local objects = figure:objects() + local results = { } + -- local objects = figure:objects() + local objects = getobjects(result,figure,askedfig) for o=1,#objects do local object = objects[o] - local tt = { } - local fields = mplib.fields(object) + local result = { } + local fields = object_fields(object) -- hm, is this the whole list, if so, we can get it once for f=1,#fields do local field = fields[f] - tt[field] = object[field] + result[field] = object[field] end - t[o] = tt + results[o] = result end - local b = figure:boundingbox() + local boundingbox = figure:boundingbox() return { - boundingbox = { llx = b[1], lly = b[2], urx = b[3], ury = b[4] }, - objects = t + boundingbox = { + llx = boundingbox[1], + lly = boundingbox[2], + urx = boundingbox[3], + ury = boundingbox[4], + }, + objects = results } else return nil |