diff options
author | Taco Hoekwater <taco@elvenkind.com> | 2011-06-01 08:54:21 +0000 |
---|---|---|
committer | Taco Hoekwater <taco@elvenkind.com> | 2011-06-01 08:54:21 +0000 |
commit | d7ccb42582f85acf30568913610ccf4d602023fb (patch) | |
tree | 7292e3545a420676878e7451b68892d360c62cb6 /Master/texmf-dist/tex/context/base/mlib-pdf.lua | |
parent | 2d62a6fe9b80def59c392268022f1f9a2d6e358f (diff) |
commit context 2011.05.18
git-svn-id: svn://tug.org/texlive/trunk@22719 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mlib-pdf.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mlib-pdf.lua | 275 |
1 files changed, 129 insertions, 146 deletions
diff --git a/Master/texmf-dist/tex/context/base/mlib-pdf.lua b/Master/texmf-dist/tex/context/base/mlib-pdf.lua index 352070408c1..8000d5a282e 100644 --- a/Master/texmf-dist/tex/context/base/mlib-pdf.lua +++ b/Master/texmf-dist/tex/context/base/mlib-pdf.lua @@ -7,14 +7,22 @@ if not modules then modules = { } end modules ['mlib-pdf'] = { } local format, concat, gsub = string.format, table.concat, string.gsub -local texsprint = tex.sprint local abs, sqrt, round = math.abs, math.sqrt, math.round +local setmetatable = setmetatable +local Cf, C, Cg, Ct, P, S, lpegmatch = lpeg.Cf, lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S, lpeg.match -local copy_node, write_node = node.copy, node.write +local allocate = utilities.storage.allocate -local ctxcatcodes = tex.ctxcatcodes +local report_metapost = logs.reporter("metapost") + +local mplib, context = mplib, context + +local copy_node = node.copy +local write_node = node.write metapost = metapost or { } +local metapost = metapost + metapost.multipass = false metapost.n = 0 metapost.optimize = true -- false @@ -61,19 +69,19 @@ metapost.flushers.pdf = { } local savedliterals = nil -local mpsliteral = nodes.register(node.new("whatsit",8)) +local mpsliteral = nodes.pool.register(node.new("whatsit",8)) -- pdfliteral -function metapost.flush_literal(d) -- \def\MPLIBtoPDF#1{\ctxlua{metapost.flush_literal(#1)}} +function metapost.flushliteral(d) -- \def\MPLIBtoPDF#1{\ctxlua{metapost.flush_literal(#1)}} if savedliterals then local literal = copy_node(mpsliteral) literal.data = savedliterals[d] write_node(literal) else - logs.report("metapost","problem flushing literal %s",d) + report_metapost("problem flushing literal %s",d) end end -function metapost.flush_reset() +function metapost.flushreset() -- will become obsolete and internal savedliterals = nil end @@ -83,10 +91,10 @@ function metapost.flushers.pdf.comment(message) if savedliterals then local last = #savedliterals + 1 savedliterals[last] = message - texsprint(ctxcatcodes,"\\MPLIBtoPDF{",last,"}") + context.MPLIBtoPDF(last) else savedliterals = { message } - texsprint(ctxcatcodes,"\\MPLIBtoPDF{1}") + context.MPLIBtoPDF(1) end end end @@ -94,14 +102,14 @@ end function metapost.flushers.pdf.startfigure(n,llx,lly,urx,ury,message) savedliterals = nil metapost.n = metapost.n + 1 - texsprint(ctxcatcodes,format("\\startMPLIBtoPDF{%s}{%s}{%s}{%s}",llx,lly,urx,ury)) + context.startMPLIBtoPDF(llx,lly,urx,ury) if message then metapost.flushers.pdf.comment(message) end end function metapost.flushers.pdf.stopfigure(message) if message then metapost.flushers.pdf.comment(message) end - texsprint(ctxcatcodes,"\\stopMPLIBtoPDF") - texsprint(ctxcatcodes,"\\ctxlua{metapost.flush_reset()}") -- maybe just at the beginning + context.stopMPLIBtoPDF() + context.MPLIBflushreset() -- maybe just at the beginning end function metapost.flushers.pdf.flushfigure(pdfliterals) -- table @@ -110,33 +118,30 @@ function metapost.flushers.pdf.flushfigure(pdfliterals) -- table if savedliterals then local last = #savedliterals + 1 savedliterals[last] = pdfliterals - texsprint(ctxcatcodes,"\\MPLIBtoPDF{",last,"}") + context.MPLIBtoPDF(last) else savedliterals = { pdfliterals } - texsprint(ctxcatcodes,"\\MPLIBtoPDF{1}") + context.MPLIBtoPDF(1) end end end function metapost.flushers.pdf.textfigure(font,size,text,width,height,depth) -- we could save the factor text = gsub(text,".","\\hbox{%1}") -- kerning happens in metapost (i have to check if this is true for mplib) - texsprint(ctxcatcodes,format("\\MPLIBtextext{%s}{%s}{%s}{%s}{%s}",font,size,text,0,-number.dimenfactors.bp*depth)) + context.MPLIBtextext(font,size,text,0,-number.dimenfactors.bp*depth) end 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) - if mplib.pen_info then - local t = mplib.pen_info(object) - rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty - divider = sx*sy - rx*ry - return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width - else - rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1 - return false, 1 - end + local t = pen_info(object) + rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty + divider = sx*sy - rx*ry + return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width end local function mpconcat(px, py) -- no tx, ty here / we can move this one inline if needed @@ -155,84 +160,109 @@ local function curved(ith,pth) end local function flushnormalpath(path, t, open) - t = t or { } - local pth, ith + local pth, ith, nt + if t then + nt = #t + else + t = { } + nt = 0 + end for i=1,#path do + nt = nt + 1 pth = path[i] if not ith then - t[#t+1] = format("%f %f m",pth.x_coord,pth.y_coord) + t[nt] = format("%f %f m",pth.x_coord,pth.y_coord) elseif curved(ith,pth) then - t[#t+1] = format("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord) + t[nt] = format("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord) else - t[#t+1] = format("%f %f l",pth.x_coord,pth.y_coord) + t[nt] = format("%f %f l",pth.x_coord,pth.y_coord) end ith = pth end if not open then + nt = nt + 1 local one = path[1] if curved(pth,one) then - t[#t+1] = format("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord ) + t[nt] = format("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord ) else - t[#t+1] = format("%f %f l",one.x_coord,one.y_coord) + t[nt] = format("%f %f l",one.x_coord,one.y_coord) end elseif #path == 1 then -- special case .. draw point local one = path[1] - t[#t+1] = format("%f %f l",one.x_coord,one.y_coord) + nt = nt + 1 + t[nt] = format("%f %f l",one.x_coord,one.y_coord) end return t end local function flushconcatpath(path, t, open) - t = t or { } - t[#t+1] = format("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty) - local pth, ith + local pth, ith, nt + if t then + nt = #t + else + t = { } + nt = 0 + end + nt = nt + 1 + t[nt] = format("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty) for i=1,#path do + nt = nt + 1 pth = path[i] if not ith then - t[#t+1] = format("%f %f m",mpconcat(pth.x_coord,pth.y_coord)) + t[nt] = format("%f %f m",mpconcat(pth.x_coord,pth.y_coord)) elseif curved(ith,pth) then local a, b = mpconcat(ith.right_x,ith.right_y) local c, d = mpconcat(pth.left_x,pth.left_y) - t[#t+1] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(pth.x_coord,pth.y_coord)) + t[nt] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(pth.x_coord,pth.y_coord)) else - t[#t+1] = format("%f %f l",mpconcat(pth.x_coord, pth.y_coord)) + t[nt] = format("%f %f l",mpconcat(pth.x_coord, pth.y_coord)) end ith = pth end if not open then + nt = nt + 1 local one = path[1] if curved(pth,one) then local a, b = mpconcat(pth.right_x,pth.right_y) local c, d = mpconcat(one.left_x,one.left_y) - t[#t+1] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(one.x_coord, one.y_coord)) + t[nt] = format("%f %f %f %f %f %f c",a,b,c,d,mpconcat(one.x_coord, one.y_coord)) else - t[#t+1] = format("%f %f l",mpconcat(one.x_coord,one.y_coord)) + t[nt] = format("%f %f l",mpconcat(one.x_coord,one.y_coord)) end elseif #path == 1 then -- special case .. draw point + nt = nt + 1 local one = path[1] - t[#t+1] = format("%f %f l",mpconcat(one.x_coord,one.y_coord)) + t[nt] = format("%f %f l",mpconcat(one.x_coord,one.y_coord)) end return t end metapost.flushnormalpath = flushnormalpath -metapost.specials = metapost.specials or { } +-- The flusher is pdf based, if another backend is used, we need to overload the +-- flusher; this is beta code, the organization will change (already upgraded in +-- sync with mplib) +-- +-- We can avoid the before table but I like symmetry. There is of course a small +-- performance penalty, but so is passing extra arguments (result, flusher, after) +-- and returning stuff. --- we have two extension handlers, one for pre and postscripts, and one for colors +local function ignore() end --- the flusher is pdf based, if another backend is used, we need to overload the --- flusher; this is beta code, the organization will change - -function metapost.flush(result,flusher,askedfig) -- pdf flusher, table en dan concat is sneller, 1 literal +function metapost.flush(result,flusher,askedfig) if result then local figures = result.fig if figures then flusher = flusher or metapost.flushers.pdf - local colorconverter = metapost.colorconverter() -- function ! - local colorhandler = metapost.colorhandler + local resetplugins = metapost.resetplugins or ignore + local processplugins = metapost.processplugins or ignore + local pluginactions = metapost.pluginactions or ignore + local startfigure = flusher.startfigure + local stopfigure = flusher.stopfigure + local flushfigure = flusher.flushfigure + local textfigure = flusher.textfigure for f=1, #figures do local figure = figures[f] local objects = getobjects(result,figure,f) @@ -248,19 +278,18 @@ function metapost.flush(result,flusher,askedfig) -- pdf flusher, table en dan co metapost.ury = ury if urx < llx then -- invalid - flusher.startfigure(fignum,0,0,0,0,"invalid",figure) - flusher.stopfigure() + startfigure(fignum,0,0,0,0,"invalid",figure) + stopfigure() else - flusher.startfigure(fignum,llx,lly,urx,ury,"begin",figure) + startfigure(fignum,llx,lly,urx,ury,"begin",figure) t[#t+1] = "q" if objects then + resetplugins() -- we should move the colorinitializer here t[#t+1] = metapost.colorinitializer() - -- once we have multiple prescripts we can do more tricky things like - -- text and special colors at the same time for o=1,#objects do local object = objects[o] local objecttype = object.type - if objecttype == "start_bounds" or objecttype == "stop_bounds" then + if objecttype == "start_bounds" or objecttype == "stop_bounds" or objecttype == "special" then -- skip elseif objecttype == "start_clip" then t[#t+1] = "q" @@ -269,74 +298,44 @@ function metapost.flush(result,flusher,askedfig) -- pdf flusher, table en dan co elseif objecttype == "stop_clip" then t[#t+1] = "Q" miterlimit, linecap, linejoin, dashed = -1, -1, -1, false - elseif objecttype == "special" then - metapost.specials.register(object.prescript) elseif objecttype == "text" then t[#t+1] = "q" local ot = object.transform -- 3,4,5,6,1,2 t[#t+1] = format("%f %f %f %f %f %f cm",ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) -- TH: format("%f %f m %f %f %f %f 0 0 cm",unpack(ot)) - flusher.flushfigure(t) -- flush accumulated literals + flushfigure(t) -- flush accumulated literals t = { } - flusher.textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth) + textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth) t[#t+1] = "Q" else - -- alternatively we can pass on the stack, could be a helper - -- can be optimized with locals - local currentobject = { -- not needed when no extensions - type = object.type, - miterlimit = object.miterlimit, - linejoin = object.linejoin, - linecap = object.linecap, - color = object.color, - dash = object.dash, - path = object.path, - htap = object.htap, - pen = object.pen, - prescript = object.prescript, - postscript = object.postscript, - } - -- - local before, inbetween, after = nil, nil, nil - -- - local cs, cr = currentobject.color, nil - -- todo document why ... - if cs and colorhandler and #cs > 0 and round(cs[1]*10000) == 123 then -- test in function - currentobject, cr = colorhandler(cs,currentobject,t,colorconverter) - objecttype = currentobject.type - end - -- - local prescript = currentobject.prescript - if prescript and prescript ~= "" then - -- move test to function - local special = metapost.specials[prescript] - if special then - currentobject, before, inbetween, after = special(currentobject.postscript,currentobject,t,flusher) - objecttype = currentobject.type - end + -- we use an indirect table as we want to overload + -- entries but this is not possible in userdata + local original = object + local object = { } + setmetatable(object, { + __index = original + }) + -- first we analyze + local before, after = processplugins(object) + local objecttype = object.type -- can have changed + if before then + t = pluginactions(before,t,flushfigure) end - -- - cs = currentobject.color - if cs and #cs > 0 then - t[#t+1], cr = colorconverter(cs) - end - -- - if before then currentobject, t = before() end - local ml = currentobject.miterlimit + local ml = object.miterlimit if ml and ml ~= miterlimit then miterlimit = ml t[#t+1] = format("%f M",ml) end - local lj = currentobject.linejoin + local lj = object.linejoin if lj and lj ~= linejoin then linejoin = lj t[#t+1] = format("%i j",lj) end - local lc = currentobject.linecap + local lc = object.linecap if lc and lc ~= linecap then linecap = lc t[#t+1] = format("%i J",lc) end - local dl = currentobject.dash + local dl = object.dash if dl then local d = format("[%s] %i d",concat(dl.dashes or {}," "),dl.offset) if d ~= dashed then @@ -347,14 +346,13 @@ function metapost.flush(result,flusher,askedfig) -- pdf flusher, table en dan co t[#t+1] = "[] 0 d" dashed = false end - if inbetween then currentobject, t = inbetween() end - local path = currentobject.path + 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 = currentobject.pen + local pen = object.pen if pen then if pen.type == 'elliptical' then - transformed, penwidth = pen_characteristics(object) -- boolean, value + transformed, penwidth = pen_characteristics(original) -- boolean, value t[#t+1] = format("%f w",penwidth) -- todo: only if changed if objecttype == 'fill' then objecttype = 'both' @@ -383,7 +381,7 @@ function metapost.flush(result,flusher,askedfig) -- pdf flusher, table en dan co if transformed then t[#t+1] = "Q" end - local path = currentobject.htap + local path = object.htap if path then if transformed then t[#t+1] = "q" @@ -404,16 +402,19 @@ function metapost.flush(result,flusher,askedfig) -- pdf flusher, table en dan co t[#t+1] = "Q" end end - if cr then - t[#t+1] = cr + if after then + t = pluginactions(after,t,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 end - if after then currentobject, t = after() end end - end + end end t[#t+1] = "Q" - flusher.flushfigure(t) - flusher.stopfigure("end") + flushfigure(t) + stopfigure("end") end if askedfig then break @@ -428,6 +429,7 @@ function metapost.parse(result,askedfig) if result then local figures = result.fig if figures then + local analyzeplugins = metapost.analyzeplugins for f=1, #figures do local figure = figures[f] local fignum = figure:charcode() or 0 @@ -440,17 +442,14 @@ function metapost.parse(result,askedfig) metapost.ury = ury local objects = getobjects(result,figure,f) if objects then + -- for o=1,#objects do + -- local object = objects[o] + -- local prescript = object.prescript + -- if prescript then + -- analyzeplugins(object) + -- end for o=1,#objects do - local object = objects[o] - if object.type == "outline" then - local prescript = object.prescript - if prescript then - local special = metapost.specials[prescript] - if special then - special(object.postscript,object) - end - end - end + analyzeplugins(objects[o]) end end break @@ -467,15 +466,17 @@ local t = { } local flusher = { startfigure = function() t = { } - texsprint(ctxcatcodes,"\\startnointerference") + context.startnointerference() end, flushfigure = function(literals) + local n = #t for i=1, #literals do - t[#t+1] = literals[i] + n = n + 1 + t[n] = literals[i] end end, stopfigure = function() - texsprint(ctxcatcodes,"\\stopnointerference") + context.stopnointerference() end } @@ -499,7 +500,7 @@ function metapost.totable(result) local field = fields[f] tt[field] = object[field] end - t[#t+1] = tt + t[o] = tt end local b = figure:boundingbox() return { @@ -510,21 +511,3 @@ function metapost.totable(result) return nil end end - --- will be overloaded later - -function metapost.colorconverter() - return function(cr) - local n = #cr - if n == 4 then - local c, m, y, k = cr[1], cr[2], cr[3], cr[4] - return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G" - elseif n == 3 then - local r, g, b = cr[1], cr[2], cr[3] - return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G" - else - local s = cr[1] - return format("%.3f g %.3f G",s,s), "0 g 0 G" - end - end -end |