diff options
author | Hans Hagen <pragma@wxs.nl> | 2018-06-08 10:23:49 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg42.2a@gmail.com> | 2018-06-08 10:23:49 +0200 |
commit | 86bfea5faac983d15c47eec27f43ec56e75c69ef (patch) | |
tree | 69a37851a9b8beeb625110f4fc51ff1ef188d7e4 /tex/context/base/mkiv/mlib-pdf.lua | |
parent | c2d2236242c95f4753e7b197d576102c6fc20446 (diff) | |
download | context-86bfea5faac983d15c47eec27f43ec56e75c69ef.tar.gz |
2018-06-08 09:38:00
Diffstat (limited to 'tex/context/base/mkiv/mlib-pdf.lua')
-rw-r--r-- | tex/context/base/mkiv/mlib-pdf.lua | 391 |
1 files changed, 206 insertions, 185 deletions
diff --git a/tex/context/base/mkiv/mlib-pdf.lua b/tex/context/base/mkiv/mlib-pdf.lua index 453d00aef..d93e1b879 100644 --- a/tex/context/base/mkiv/mlib-pdf.lua +++ b/tex/context/base/mkiv/mlib-pdf.lua @@ -8,7 +8,8 @@ if not modules then modules = { } end modules ['mlib-pdf'] = { -- maybe %s is better than %f -local format, concat, gsub = string.format, table.concat, string.gsub +local gsub = string.gsub +local concat, insert, remove = table.concat, table.insert, table.remove 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 @@ -102,14 +103,14 @@ local function getobjects(result,figure,index) end end -function metapost.convert(result, trialrun, flusher, multipass, askedfig) +function metapost.convert(result, trialrun, flusher, multipass, askedfig, incontext) 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 + metapost.flush(result,flusher,askedfig,incontext) -- saves a run else return false end @@ -117,7 +118,7 @@ function metapost.convert(result, trialrun, flusher, multipass, askedfig) if save_table then table.save(save_table,metapost.totable(result,1)) -- direct end - metapost.flush(result,flusher,askedfig) + metapost.flush(result,flusher,askedfig,incontext) end return true -- done end @@ -374,7 +375,9 @@ function metapost.processspecial(str) end end -local function setproperties(figure) +local stack = { } + +local function pushproperties(figure) local boundingbox = figure:boundingbox() local properties = { llx = boundingbox[1], @@ -388,15 +391,20 @@ local function setproperties(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(result,flusher,askedfig) +function metapost.flush(result,flusher,askedfig,incontext) if result then local figures = result.fig if figures then @@ -413,7 +421,7 @@ function metapost.flush(result,flusher,askedfig) metapost.comment = flusher.comment or nocomment for index=1,#figures do local figure = figures[index] - local properties = setproperties(figure) + local properties = pushproperties(figure) if askedfig == "direct" or askedfig == "all" or askedfig == properties.number then local objects = getobjects(result,figure,index) local result = { } @@ -427,217 +435,229 @@ function metapost.flush(result,flusher,askedfig) startfigure(properties.number,0,0,0,0,"invalid",figure) stopfigure() else - 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 + + -- 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) 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 - 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) + -- 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 both then - if dashed ~= false then -- was just dashed test - result[#result+1] = "[] 0 d" - dashed = false + -- + 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 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 - end - elseif dashed ~= false then -- was just dashed test - result[#result+1] = "[] 0 d" - dashed = false + local objecttype = object.type -- can have changed + if before then + result = pluginactions(before,result,flushfigure) end - 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' + 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 -- 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) + 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 end + elseif dashed ~= false then -- was just dashed test + result[#result+1] = "[] 0 d" + dashed = false end - savedpath = nil 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 - 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 + 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 -- calculated by mplib itself + objecttype = 'fill' + end end - end - if transformed then - 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) + 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) + 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 - flushnormalpath(path,result,open) + 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 - savedhtap = nil - evenodd = true end if transformed then - flushconcatpath(path,result,open) - else - flushnormalpath(path,result,open) + result[#result+1] = "Q" 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 + 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 + 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 end - if transformed then - result[#result+1] = "Q" + if after then + result = pluginactions(after,result,flushfigure) end end - if after then - result = pluginactions(after,result,flushfigure) + 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 - 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 @@ -653,7 +673,7 @@ function metapost.parse(result,askedfig) local analyzeplugins = metapost.analyzeplugins -- each object for index=1,#figures do local figure = figures[index] - local properties = setproperties(figure) + local properties = pushproperties(figure) if askedfig == "direct" or askedfig == "all" or askedfig == properties.number then local objects = getobjects(result,figure,index) if objects then @@ -667,6 +687,7 @@ function metapost.parse(result,askedfig) break end end + popproperties() end return multipass end |