summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mlib-pdf.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mlib-pdf.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/mlib-pdf.lua656
1 files changed, 329 insertions, 327 deletions
diff --git a/Master/texmf-dist/tex/context/base/mlib-pdf.lua b/Master/texmf-dist/tex/context/base/mlib-pdf.lua
index 344052607a3..38b61b0ba97 100644
--- a/Master/texmf-dist/tex/context/base/mlib-pdf.lua
+++ b/Master/texmf-dist/tex/context/base/mlib-pdf.lua
@@ -6,172 +6,148 @@ if not modules then modules = { } end modules ['mlib-pdf'] = {
license = "see context related readme files",
}
-local format, join = string.format, table.concat
-local sprint = tex.sprint
+local format, concat = string.format, table.concat
+local texsprint = tex.sprint
local abs, sqrt, round = math.abs, math.sqrt, math.round
+local copy_node, write_node = node.copy, node.write
+
+local ctxcatcodes = tex.ctxcatcodes
+
metapost = metapost or { }
metapost.multipass = false
metapost.n = 0
+metapost.optimize = true -- false
+
+--~ 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,f)
+ if metapost.optimize then
+ local objects = result.objects
+ if not objects then
+ result.objects = { }
+ end
+ objects = result.objects[f]
+ if not objects then
+ objects = figure:objects()
+ result.objects[f] = objects
+ end
+ return objects
+ else
+ return figure:objects()
+ end
+end
-function metapost.convert(result, trialrun, flusher, multipass)
+function metapost.convert(result, trialrun, flusher, multipass, askedfig)
if trialrun then
metapost.multipass = false
- metapost.parse(result, flusher)
- if multipass and not metapost.multipass then
- metapost.flush(result, flusher) -- saves a run
+ metapost.parse(result, askedfig)
+ if multipass and not metapost.multipass and metapost.optimize then
+ metapost.flush(result, flusher, askedfig) -- saves a run
else
return false
end
else
- metapost.flush(result, flusher)
+ metapost.flush(result, flusher, askedfig)
end
return true -- done
end
-function metapost.comment(message)
- if message then
- sprint(tex.ctxcatcodes,format("\\MPLIBtoPDF{\\letterpercent\\space mps graphic %s: %s}", metapost.n, message))
+metapost.flushers = { }
+metapost.flushers.pdf = { }
+
+local savedliterals = nil
+
+local mpsliteral = nodes.register(node.new("whatsit",8))
+
+function metapost.flush_literal(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)
end
end
-metapost.flushers = { }
-metapost.flushers.pdf = { }
+function metapost.flush_reset()
+ savedliterals = nil
+end
+
+function metapost.flushers.pdf.comment(message)
+ if message then
+ message = format("%% mps graphic %s: %s", metapost.n, message)
+ if savedliterals then
+ local last = #savedliterals + 1
+ savedliterals[last] = message
+ texsprint(ctxcatcodes,"\\MPLIBtoPDF{",last,"}")
+ else
+ savedliterals = { message }
+ texsprint(ctxcatcodes,"\\MPLIBtoPDF{1}")
+ end
+ end
+end
function metapost.flushers.pdf.startfigure(n,llx,lly,urx,ury,message)
+ savedliterals = nil
metapost.n = metapost.n + 1
- sprint(tex.ctxcatcodes,format("\\startMPLIBtoPDF{%s}{%s}{%s}{%s}",llx,lly,urx,ury))
- if message then metapost.comment(message) end
+ texsprint(ctxcatcodes,format("\\startMPLIBtoPDF{%s}{%s}{%s}{%s}",llx,lly,urx,ury))
+ if message then metapost.flushers.pdf.comment(message) end
end
function metapost.flushers.pdf.stopfigure(message)
- if message then metapost.comment(message) end
- sprint(tex.ctxcatcodes,"\\stopMPLIBtoPDF")
+ if message then metapost.flushers.pdf.comment(message) end
+ texsprint(ctxcatcodes,"\\stopMPLIBtoPDF")
+ texsprint(ctxcatcodes,"\\ctxlua{metapost.flush_reset()}") -- maybe just at the beginning
end
function metapost.flushers.pdf.flushfigure(pdfliterals) -- table
if #pdfliterals > 0 then
- sprint(tex.ctxcatcodes,"\\MPLIBtoPDF{",join(pdfliterals,"\n"),"}")
+ pdfliterals = concat(pdfliterals,"\n")
+ if savedliterals then
+ local last = #savedliterals + 1
+ savedliterals[last] = pdfliterals
+ texsprint(ctxcatcodes,"\\MPLIBtoPDF{",last,"}")
+ else
+ savedliterals = { pdfliterals }
+ texsprint(ctxcatcodes,"\\MPLIBtoPDF{1}")
+ end
end
end
function metapost.flushers.pdf.textfigure(font,size,text,width,height,depth) -- we could save the factor
text = text:gsub(".","\\hbox{%1}") -- kerning happens in metapost (i have to check if this is true for mplib)
- sprint(tex.ctxcatcodes,format("\\MPLIBtextext{%s}{%s}{%s}{%s}{%s}",font,size,text,0,-number.dimenfactors.bp*depth))
+ texsprint(ctxcatcodes,format("\\MPLIBtextext{%s}{%s}{%s}{%s}{%s}",font,size,text,0,-number.dimenfactors.bp*depth))
end
--- the pen calculations are taken from metapost, first converted by
--- taco from c to lua, and then optimized by hans, so all errors are his
-
-local function pyth(a,b)
- return sqrt(a*a + b*b) -- much faster than sqrt(a^2 + b^2)
-end
-
-local aspect_bound = 10/65536
-local aspect_default = 1/65536
local bend_tolerance = 131/65536
-local eps = 0.0001
-
-local function coord_range_x(h, dz) -- direction x
- local zlo, zhi = 0, 0
- for i=1, #h do
- local p = h[i]
- local z = p.x_coord
- if z < zlo then zlo = z elseif z > zhi then zhi = z end
- z = p.right_x
- if z < zlo then zlo = z elseif z > zhi then zhi = z end
- z = p.left_x
- if z < zlo then zlo = z elseif z > zhi then zhi = z end
- end
- return (zhi - zlo <= dz and aspect_bound) or aspect_default
-end
-
-local function coord_range_y(h, dz) -- direction y
- local zlo, zhi = 0, 0
- for i=1, #h do
- local p = h[i]
- local z = p.y_coord
- if z < zlo then zlo = z elseif z > zhi then zhi = z end
- z = p.right_y
- if z < zlo then zlo = z elseif z > zhi then zhi = z end
- z = p.left_y
- if z < zlo then zlo = z elseif z > zhi then zhi = z end
- end
- return (zhi - zlo <= dz and aspect_bound) or aspect_default
-end
local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
local function pen_characteristics(object)
- local p = object.pen[1]
- local x_coord, y_coord, left_x, left_y, right_x, right_y = p.x_coord, p.y_coord, p.left_x, p.left_y, p.right_x, p.right_y
- local wx, wy, width
- if right_x == x_coord and left_y == y_coord then
- wx = abs(left_x - x_coord)
- wy = abs(right_y - y_coord)
- else
- wx = pyth(left_x - x_coord, right_x - x_coord)
- wy = pyth(left_y - y_coord, right_y - y_coord)
- end
- if wy/coord_range_x(object.path, wx) >= wx/coord_range_y(object.path, wy) then
- width = wy
- else
- width = wx
- end
- sx, rx, ry, sy, tx, ty = left_x, left_y, right_x, right_y, x_coord, y_coord
- sx, rx, ry, sy = (sx-tx), (rx-ty), (ry-tx), (sy-ty) -- combine with previous
- if width ~= 1 then
- if width == 0 then
- sx, sy = 1, 1
- else
- rx, ry, sx, sy = rx/width, ry/width, sx/width, sy/width
- end
- end
- -- sx rx ry sy tx ty -> 1 0 0 1 0 0 is ok, but 0 0 0 0 0 0 not
- if true then
- if abs(sx) < eps then sx = eps end
- if abs(sy) < eps then sy = eps end
+ 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
- -- this block looks complicated but it only captures invalid transforms
- -- to be checked rx vs sx and so
- local det = sx/sy - ry/rx
- local aspect = 4*aspect_bound + aspect_default
- if abs(det) < aspect then
- local s
- if det >= 0 then
- s, aspect = 1, aspect - det
- else
- s, aspect = -1, -aspect - det -- - ?
- end
- local absrx, absry, abssy, abssx = abs(rx), abs(ry), abs(sy), abs(sx)
- if abssx + abssy >= absry + absrx then -- was yy
- if abssx > abssy then
- sy = sy + (aspect + s*abssx) / sx
- else
- sx = sx + (aspect + s*abssy) / sy
- end
- else
- if absry > absrx then
- rx = rx + (aspect + s*absry) / ry
- else
- ry = ry + (aspect + s*absrx) / rx
- end
- end
- end
+ rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
+ return false, 1
end
- divider = sx*sy - rx*ry
- return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), width
end
-local function concat(px, py) -- no tx, ty here
+local function mpconcat(px, py) -- no tx, ty here / we can move this one inline if needed
return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
end
local function curved(ith,pth)
local d = pth.left_x - ith.right_x
- if abs(ith.right_x-ith.x_coord-d) <= bend_tolerance and abs(pth.x_coord-pth.left_x-d) <= bend_tolerance then
+ if abs(ith.right_x - ith.x_coord - d) <= bend_tolerance and abs(pth.x_coord - pth.left_x - d) <= bend_tolerance then
d = pth.left_y - ith.right_y
- if abs(ith.right_y-ith.y_coord-d) <= bend_tolerance and abs(pth.y_coord-pth.left_y-d) <= bend_tolerance then
+ if abs(ith.right_y - ith.y_coord - d) <= bend_tolerance and abs(pth.y_coord - pth.left_y - d) <= bend_tolerance then
return false
end
end
@@ -196,8 +172,12 @@ local function flushnormalpath(path, t, open)
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 )
else
- t[#t+1] = format("%f %f l",one.x_coord,one.y_coord)
+ t[#t+1] = 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)
end
return t
end
@@ -208,29 +188,35 @@ local function flushconcatpath(path, t, open)
for i=1,#path do
pth = path[i]
if not ith then
- t[#t+1] = format("%f %f m",concat(pth.x_coord,pth.y_coord))
+ t[#t+1] = format("%f %f m",mpconcat(pth.x_coord,pth.y_coord))
elseif curved(ith,pth) then
- local a, b = concat(ith.right_x,ith.right_y)
- local c, d = concat(pth.left_x,pth.left_y)
- t[#t+1] = format("%f %f %f %f %f %f c",a,b,c,d,concat(pth.x_coord, pth.y_coord))
+ 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))
else
- t[#t+1] = format("%f %f l",concat(pth.x_coord, pth.y_coord))
+ t[#t+1] = format("%f %f l",mpconcat(pth.x_coord, pth.y_coord))
end
ith = pth
end
if not open then
local one = path[1]
if curved(pth,one) then
- local a, b = concat(pth.right_x,pth.right_y)
- local c, d = concat(one.left_x,one.left_y)
- t[#t+1] = format("%f %f %f %f %f %f c",a,b,c,d,concat(one.x_coord, one.y_coord))
+ 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))
else
- t[#t+1] = format("%f %f l",concat(one.x_coord,one.y_coord))
+ t[#t+1] = format("%f %f l",mpconcat(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",mpconcat(one.x_coord,one.y_coord))
end
return t
end
+metapost.flushnormalpath = flushnormalpath
+
metapost.specials = metapost.specials or { }
-- we have two extension handlers, one for pre and postscripts, and one for colors
@@ -238,7 +224,7 @@ 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
-function metapost.flush(result,flusher) -- pdf flusher, table en dan concat is sneller, 1 literal
+function metapost.flush(result,flusher,askedfig) -- pdf flusher, table en dan concat is sneller, 1 literal
if result then
local figures = result.fig
if figures then
@@ -247,254 +233,268 @@ function metapost.flush(result,flusher) -- pdf flusher, table en dan concat is s
local colorhandler = metapost.colorhandler
for f=1, #figures do
local figure = figures[f]
---~ local objects = figure:objects()
-local objects = result.objects
-if not objects then
- objects = figure:objects()
- result.objects = objects
-end
- local fignum = tonumber((figure:filename()):match("([%d]+)$") or 0)
- local t = { }
- 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] -- faster than unpack
- if urx < llx then
- -- invalid
- flusher.startfigure(fignum,0,0,0,0,"invalid")
- flusher.stopfigure()
- else
- flusher.startfigure(fignum,llx,lly,urx,ury,"begin")
- t[#t+1] = "q"
- if objects then
- for o=1,#objects do
- local object = objects[o]
- local objecttype = object.type
- if objecttype == "start_bounds" or objecttype == "stop_bounds" then
- -- skip
- elseif objecttype == "start_clip" then
- t[#t+1] = "q"
- flushnormalpath(object.path,t,false)
- t[#t+1] = "W n"
- 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)
- t = { }
- flusher.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
- 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 then
- -- move test to function
- local special = metapost.specials[prescript]
- if special then
- currentobject, before, inbetween, after = special(currentobject.postscript,currentobject,t,flusher)
+ local objects = getobjects(result,figure,f)
+ local fignum = figure:charcode() or 0
+ if not askedfig or (askedfig == fignum) then
+ local t = { }
+ 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] -- faster than unpack
+ metapost.llx = llx
+ metapost.lly = lly
+ metapost.urx = urx
+ metapost.ury = ury
+ if urx < llx then
+ -- invalid
+ flusher.startfigure(fignum,0,0,0,0,"invalid",figure)
+ flusher.stopfigure()
+ else
+ flusher.startfigure(fignum,llx,lly,urx,ury,"begin",figure)
+ t[#t+1] = "q"
+ if objects then
+ 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
+ -- skip
+ elseif objecttype == "start_clip" then
+ t[#t+1] = "q"
+ flushnormalpath(object.path,t,false)
+ t[#t+1] = "W n"
+ 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
+ t = { }
+ flusher.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
- end
- --
- cs = currentobject.color
- if cs and #cs > 0 then
- t[#t+1], cr = colorconverter(cs)
- end
- --
- if before then object, t = before() end
- local ml = currentobject.miterlimit
- if ml and ml ~= miterlimit then
- miterlimit = ml
- t[#t+1] = format("%f M",ml)
- end
- local lj = currentobject.linejoin
- if lj and lj ~= linejoin then
- linejoin = lj
- t[#t+1] = format("%i j",lj)
- end
- local lc = currentobject.linecap
- if lc and lc ~= linecap then
- linecap = lc
- t[#t+1] = format("%i J",lc)
- end
- local dl = currentobject.dash
- if dl then
- local d = format("[%s] %i d",join(dl.dashes or {}," "),dl.offset)
- if d ~= dashed then
- dashed = d
- t[#t+1] = dashed
+ --
+ 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
end
- elseif dashed then
- t[#t+1] = "[] 0 d"
- dashed = false
- end
- if inbetween then object, t = inbetween() end
- local path = currentobject.path
- 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
- if pen then
- if pen.type=='elliptical' then
- transformed, penwidth = pen_characteristics(object) -- boolean, value
- t[#t+1] = format("%f w",penwidth) -- todo: only if changed
- if objecttype == 'fill' then
- objecttype = 'both'
+ --
+ 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
+ if ml and ml ~= miterlimit then
+ miterlimit = ml
+ t[#t+1] = format("%f M",ml)
+ end
+ local lj = currentobject.linejoin
+ if lj and lj ~= linejoin then
+ linejoin = lj
+ t[#t+1] = format("%i j",lj)
+ end
+ local lc = currentobject.linecap
+ if lc and lc ~= linecap then
+ linecap = lc
+ t[#t+1] = format("%i J",lc)
+ end
+ local dl = currentobject.dash
+ if dl then
+ local d = format("[%s] %i d",concat(dl.dashes or {}," "),dl.offset)
+ if d ~= dashed then
+ dashed = d
+ t[#t+1] = dashed
end
- else -- calculated by mplib itself
- objecttype = 'fill'
- end
- end
- if transformed then
- t[#t+1] = "q"
- end
- if path then
- if transformed then
- flushconcatpath(path,t,open)
- else
- flushnormalpath(path,t,open)
+ elseif dashed then
+ t[#t+1] = "[] 0 d"
+ dashed = false
end
- if objecttype == "fill" then
- t[#t+1] = "h f"
- elseif objecttype == "outline" then
- t[#t+1] = (open and "S") or "h S"
- elseif objecttype == "both" then
- t[#t+1] = "h B"
+ if inbetween then currentobject, t = inbetween() end
+ local path = currentobject.path
+ 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
+ if pen then
+ if pen.type == 'elliptical' then
+ transformed, penwidth = pen_characteristics(object) -- boolean, value
+ t[#t+1] = format("%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
- t[#t+1] = "Q"
- end
- local path = currentobject.htap
- if path then
if transformed then
t[#t+1] = "q"
end
- if transformed then
- flushconcatpath(path,t,open)
- else
- flushnormalpath(path,t,open)
- end
- if objecttype == "fill" then
- t[#t+1] = "h f"
- elseif objecttype == "outline" then
- t[#t+1] = (open and "S") or "h S"
- elseif objecttype == "both" then
- t[#t+1] = "h B"
+ if path then
+ if transformed then
+ flushconcatpath(path,t,open)
+ else
+ flushnormalpath(path,t,open)
+ end
+ if objecttype == "fill" then
+ t[#t+1] = "h f"
+ elseif objecttype == "outline" then
+ t[#t+1] = (open and "S") or "h S"
+ elseif objecttype == "both" then
+ t[#t+1] = "h B"
+ end
end
if transformed then
t[#t+1] = "Q"
end
+ local path = currentobject.htap
+ if path then
+ if transformed then
+ t[#t+1] = "q"
+ end
+ if transformed then
+ flushconcatpath(path,t,open)
+ else
+ flushnormalpath(path,t,open)
+ end
+ if objecttype == "fill" then
+ t[#t+1] = "h f"
+ elseif objecttype == "outline" then
+ t[#t+1] = (open and "S") or "h S"
+ elseif objecttype == "both" then
+ t[#t+1] = "h B"
+ end
+ if transformed then
+ t[#t+1] = "Q"
+ end
+ end
+ if cr then
+ t[#t+1] = cr
+ end
+ if after then currentobject, t = after() end
end
- if cr then
- t[#t+1] = cr
- end
- if after then object, t = after() end
- end
- end
+ end
+ end
+ t[#t+1] = "Q"
+ flusher.flushfigure(t)
+ flusher.stopfigure("end")
+ end
+ if askedfig then
+ break
end
- t[#t+1] = "Q"
- flusher.flushfigure(t)
- flusher.stopfigure("end")
end
end
end
end
end
-function metapost.parse(result)
+function metapost.parse(result,askedfig)
if result then
local figures = result.fig
if figures then
for f=1, #figures do
local figure = figures[f]
---~ local objects = figure:objects()
-local objects = result.objects
-if not objects then
- objects = figure:objects()
- result.objects = objects
-end
- if objects then
- 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)
+ local fignum = figure:charcode() or 0
+ if not askedfig or (askedfig == fignum) then
+ local bbox = figure:boundingbox()
+ local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
+ metapost.llx = llx
+ metapost.lly = lly
+ metapost.urx = urx
+ metapost.ury = ury
+ local objects = getobjects(result,figure,f)
+ if objects then
+ 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
- end
+ end
+ end
end
+ break
end
end
end
end
end
-do
-
- -- just tracing
+-- tracing:
- local t = { }
+local t = { }
- local flusher = {
- startfigure = function()
- t = { }
- sprint(tex.ctxcatcodes,"\\startnointerference")
- end,
- flushfigure = function(literals)
- for i=1, #literals do
- t[#t+1] = literals[i]
- end
- end,
- stopfigure = function()
- sprint(tex.ctxcatcodes,"\\stopnointerference")
+local flusher = {
+ startfigure = function()
+ t = { }
+ texsprint(ctxcatcodes,"\\startnointerference")
+ end,
+ flushfigure = function(literals)
+ for i=1, #literals do
+ t[#t+1] = literals[i]
end
- }
-
- function metapost.pdfliterals(result)
- metapost.flush(result,flusher)
- return t
+ end,
+ stopfigure = function()
+ texsprint(ctxcatcodes,"\\stopnointerference")
end
+}
+function metapost.pdfliterals(result)
+ metapost.flush(result,flusher)
+ return t
end
+-- so far
+
function metapost.totable(result)
local figure = result and result.fig and result.fig[1]
if figure then
local t = { }
local objects = figure:objects()
- for _, object in ipairs(objects) do
+ for o=1,#objects do
+ local object = objects[o]
local tt = { }
- for _, field in ipairs(mplib.fields(object)) do
+ local fields = mplib.fields(object)
+ for f=1,#fields do
+ local field = fields[f]
tt[field] = object[field]
end
t[#t+1] = tt
@@ -509,6 +509,8 @@ function metapost.totable(result)
end
end
+-- will be overloaded later
+
function metapost.colorconverter()
return function(cr)
local n = #cr