summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/mlib-lua.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/mlib-lua.lua')
-rw-r--r--tex/context/base/mkiv/mlib-lua.lua1412
1 files changed, 29 insertions, 1383 deletions
diff --git a/tex/context/base/mkiv/mlib-lua.lua b/tex/context/base/mkiv/mlib-lua.lua
index 9b4ec44dd..b38dbdcf6 100644
--- a/tex/context/base/mkiv/mlib-lua.lua
+++ b/tex/context/base/mkiv/mlib-lua.lua
@@ -6,1399 +6,45 @@ if not modules then modules = { } end modules ['mlib-lua'] = {
license = "see context related readme files",
}
--- This is very preliminary code!
+local type = type
+local insert, remove = table.insert, table.remove
--- maybe we need mplib.model, but how with instances
+local set = mp.set
+local get = mp.get
-local type, tostring, tonumber, select, loadstring = type, tostring, tonumber, select, loadstring
-local find, match, gsub, gmatch = string.find, string.match, string.gsub, string.gmatch
-local concat, insert, remove = table.concat, table.insert, table.remove
+local currentmpx = nil
+local stack = { }
-local formatters = string.formatters
-local lpegmatch = lpeg.match
-local lpegpatterns = lpeg.patterns
+local get_numeric = mplib.get_numeric
+local get_integer = mplib.get_integer
+local get_string = mplib.get_string
+local get_boolean = mplib.get_boolean
+local get_path = mplib.get_path
+local set_path = mplib.set_path
-local P, S, Ct, Cs, Cc, C = lpeg.P, lpeg.S, lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.C
-
-local report_luarun = logs.reporter("metapost","lua")
-local report_script = logs.reporter("metapost","script")
-local report_message = logs.reporter("metapost")
-
-local trace_luarun = false trackers.register("metapost.lua",function(v) trace_luarun = v end)
-
-local be_tolerant = true directives.register("metapost.lua.tolerant", function(v) be_tolerant = v end)
-
-local get, set, aux, scan, inject = { }, { }, { }, { }, { }
-
-mp = mp or { -- system namespace
- set = set,
- get = get,
- aux = aux,
- scan = scan,
- inject = inject,
-}
-
-MP = MP or { -- user namespace
-}
-
--- We had this:
---
--- table.setmetatablecall(mp,function(t,k) mpprint(k) end)
---
--- but the next one is more interesting because we cannot use calls like:
---
--- lua.mp.somedefdname("foo")
---
--- which is due to expansion of somedefdname during suffix creation. So:
---
--- lua.mp("somedefdname","foo")
-
-table.setmetatablecall(mp,function(t,k,...) return t[k](...) end)
-table.setmetatablecall(MP,function(t,k,...) return t[k](...) end)
-
-do
-
- local currentmpx = nil
- local stack = { }
-
- if CONTEXTLMTXMODE > 0 then
-
- local scan_next = mplib.scan_next
- local scan_expression = mplib.scan_expression
- local scan_token = mplib.scan_token
- local scan_symbol = mplib.scan_symbol
- local scan_numeric = mplib.scan_numeric
- local scan_integer = mplib.scan_integer
- local scan_boolean = mplib.scan_boolean
- local scan_string = mplib.scan_string
- local scan_pair = mplib.scan_pair
- local scan_color = mplib.scan_color
- local scan_cmykcolor = mplib.scan_cmykcolor
- local scan_transform = mplib.scan_transform
- local scan_path = mplib.scan_path
- local scan_pen = mplib.scan_pen
-
- scan.next = function(k) return scan_next (currentmpx,k) end
- scan.expression = function(k) return scan_expression(currentmpx,k) end
- scan.token = function(k) return scan_token (currentmpx,k) end
- scan.symbol = function(k,e) return scan_symbol (currentmpx,k,e) end
- scan.numeric = function() return scan_numeric (currentmpx) end
- scan.integer = function() return scan_integer (currentmpx) end
- scan.boolean = function() return scan_boolean (currentmpx) end
- scan.string = function() return scan_string (currentmpx) end
- scan.pair = function(t) return scan_pair (currentmpx,t) end
- scan.color = function(t) return scan_color (currentmpx,t) end
- scan.cmykcolor = function(t) return scan_cmykcolor (currentmpx,t) end
- scan.transform = function(t) return scan_transform (currentmpx,t) end
- scan.path = function(t) return scan_path (currentmpx,t) end
- scan.pen = function(t) return scan_pen (currentmpx,t) end
-
- local inject_path = mplib.inject_path
- local inject_numeric = mplib.inject_numeric
- local inject_pair = mplib.inject_pair
- local inject_boolean = mplib.inject_boolean
- local inject_integer = mplib.inject_integer
- local inject_string = mplib.inject_string
- local inject_color = mplib.inject_color
- local inject_cmykcolor = mplib.inject_cmykcolor
- local inject_transform = mplib.inject_transform
- local inject_whatever = mplib.inject_whatever
-
- inject.path = function(t,cycle,curled) return inject_path (currentmpx,t,cycle,curled) end
- inject.numeric = function(n) return inject_numeric (currentmpx,n) end
- inject.pair = function(x,y) return inject_pair (currentmpx,x,y) end
- inject.boolean = function(b) return inject_boolean (currentmpx,b) end
- inject.integer = function(i) return inject_integer (currentmpx,i) end
- inject.string = function(s) return inject_string (currentmpx,s) end
- inject.color = function(r,g,b) return inject_color (currentmpx,r,g,b) end
- inject.cmykcolor = function(c,m,y,k) return inject_cmykcolor(currentmpx,c,m,y,k) end
- inject.transform = function(x,y,xx,xy,yx,yy) return inject_transform(currentmpx,x,y,xx,xy,yx,yy) end
- inject.whatever = function(...) return inject_whatever (currentmpx,...) end
-
- -- bonus:
-
- scan .number = scan .numeric
- inject.number = inject.numeric
-
- table.setmetatablecall(inject,function(t,...)
- inject_whatever(currentmpx,...)
- end)
-
- -- experiment
-
- function mp.autoinject(m)
- local t = type(m)
- if t == "table" then
- local n = #t
- if n == 2 then
- inject_pair(currentmpx,m)
- elseif n == 3 then
- inject_color(currentmpx,m)
- elseif n == 4 then
- inject_cmykcolor(currentmpx,m)
- elseif n == 6 then
- inject_transform(currentmpx,m)
- end
- elseif t == "number" then
- inject_numeric(currentmpx,m)
- elseif t == "string" then
- inject_string(currentmpx,m)
- elseif t == "boolean" then
- inject_boolean(currentmpx,m)
- end
- end
-
- else
-
- local get_numeric = mplib.get_numeric
- local get_integer = mplib.get_integer
- local get_string = mplib.get_string
- local get_boolean = mplib.get_boolean
- local get_path = mplib.get_path
- local set_path = mplib.set_path
-
- get.numeric = function(s) return get_numeric(currentmpx,s) end
- get.number = function(s) return get_numeric(currentmpx,s) end
- get.integer = function(s) return get_integer(currentmpx,s) end
- get.string = function(s) return get_string (currentmpx,s) end
- get.boolean = function(s) return get_boolean(currentmpx,s) end
- get.path = function(s) return get_path (currentmpx,s) end
- set.path = function(s,t) return set_path (currentmpx,s,t) end -- not working yet
-
- end
-
- function metapost.pushscriptrunner(mpx)
- insert(stack,mpx)
- currentmpx = mpx
- end
-
- function metapost.popscriptrunner()
- currentmpx = remove(stack,mpx)
- end
-
- function metapost.currentmpx()
- return currentmpx
- end
-
- local status = mplib.status
-
- function metapost.currentmpxstatus()
- return status and status(currentmpx) or 0
- end
-
-end
-
--- unless we adapt the old mp library too, in the end we will have two
--- variants
-
-do
-
- local lmtxmode = CONTEXTLMTXMODE > 0
-
- -- serializers
-
- local f_integer = formatters["%i"]
- local f_numeric = formatters["%F"]
-
- -- no %n as that can produce -e notation and that is not so nice for scaled butmaybe we
- -- should then switch between ... i.e. make a push/pop for the formatters here ... not now.
-
- local f_integer = formatters["%i"]
- local f_numeric = formatters["%F"]
- local f_pair = formatters["(%F,%F)"]
- local f_ctrl = formatters["(%F,%F) .. controls (%F,%F) and (%F,%F)"]
- local f_triplet = formatters["(%F,%F,%F)"]
- local f_quadruple = formatters["(%F,%F,%F,%F)"]
- local f_transform = formatters["totransform(%F,%F,%F,%F,%F,%F)"]
- local f_pen = formatters["(pencircle transformed totransform(%F,%F,%F,%F,%F,%F))"]
-
- local f_points = formatters["%p"]
- local f_pair_pt = formatters["(%p,%p)"]
- local f_ctrl_pt = formatters["(%p,%p) .. controls (%p,%p) and (%p,%p)"]
- local f_triplet_pt = formatters["(%p,%p,%p)"]
- local f_quadruple_pt = formatters["(%p,%p,%p,%p)"]
-
- local r = P('%') / "percent"
- + P('"') / "dquote"
- + P('\n') / "crlf"
- -- + P(' ') / "space"
- local a = Cc("&")
- local q = Cc('"')
- local p = Cs(q * (r * a)^-1 * (a * r * (P(-1) + a) + P(1))^0 * q)
-
- mp.cleaned = function(s) return lpegmatch(p,s) or s end
-
- -- management
-
- -- sometimes we gain (e.g. .5 sec on the sync test)
-
- local cache = table.makeweak()
-
- local runscripts = { }
- local runnames = { }
- local nofscripts = 0
-
- function metapost.registerscript(name,f)
- nofscripts = nofscripts + 1
- if f then
- runscripts[nofscripts] = f
- runnames[name] = nofscripts
- else
- runscripts[nofscripts] = name
- end
- return nofscripts
- end
-
- function metapost.scriptindex(name)
- return runnames[name] or 0
- end
-
- -- The gbuffer sharing and such is not really needed now but make a dent when
- -- we have a high volume of simpel calls (loops) so we keep it around for a
- -- while.
-
- local nesting = 0
- local runs = 0
- local gbuffer = { }
- local buffer = gbuffer
- local n = 0
-
- local function mpdirect1(a)
- n = n + 1 buffer[n] = a
- end
- local function mpdirect2(a,b)
- n = n + 1 buffer[n] = a
- n = n + 1 buffer[n] = b
- end
- local function mpdirect3(a,b,c)
- n = n + 1 buffer[n] = a
- n = n + 1 buffer[n] = b
- n = n + 1 buffer[n] = c
- end
- local function mpdirect4(a,b,c,d)
- n = n + 1 buffer[n] = a
- n = n + 1 buffer[n] = b
- n = n + 1 buffer[n] = c
- n = n + 1 buffer[n] = d
- end
- local function mpdirect5(a,b,c,d,e)
- n = n + 1 buffer[n] = a
- n = n + 1 buffer[n] = b
- n = n + 1 buffer[n] = c
- n = n + 1 buffer[n] = d
- n = n + 1 buffer[n] = e
- end
-
- local function mpflush(separator)
- buffer[1] = concat(buffer,separator or "",1,n)
- n = 1
- end
-
- function metapost.runscript(code)
- nesting = nesting + 1
- runs = runs + 1
-
- local index = type(code) == "number"
- local f
- local result
-
- if index then
- f = runscripts[code]
- if not f then
- report_luarun("%i: bad index: %s",nesting,code)
- elseif trace_luarun then
- report_luarun("%i: index: %i",nesting,code)
- end
- else
- if trace_luarun then
- report_luarun("%i: code: %s",nesting,code)
- end
- f = cache[code]
- if not f then
- f = loadstring("return " .. code)
- if f then
- cache[code] = f
- elseif be_tolerant then
- f = loadstring(code)
- if f then
- cache[code] = f
- end
- end
- end
- end
-
- -- returning nil is more efficient and a signal not to scan in mp
-
- if f then
-
- local lbuffer, ln
-
- if nesting == 1 then
- buffer = gbuffer
- n = 0
- else
- lbuffer = buffer
- ln = n
- buffer = { }
- n = 0
- end
-
- result = f()
- if result then
- local t = type(result)
- if lmtxmode then
- -- we can consider to use the injector for tables but then we need to
- -- check of concatination is expected so best keep this!
- if t == "number" or t == "boolean" then
- -- native types
- elseif t == "string" or t == "table" then
- -- (concatenated) passed to scantokens
- else
- -- scantokens
- result = tostring(result)
- end
- else
- if t == "number" then
- result = f_numeric(result)
- elseif t == "table" then
- result = concat(result) -- no spaces here
- else
- result = tostring(result)
- end
- end
- if trace_luarun then
- report_luarun("%i: %s result: %s",nesting,t,result)
- end
- elseif n == 0 then
--- result = ""
-result = nil -- no scantokens done then
- if trace_luarun then
- report_luarun("%i: no buffered result",nesting)
- end
- elseif n == 1 then
- result = buffer[1]
- if trace_luarun then
- report_luarun("%i: 1 buffered result: %s",nesting,result)
- end
- else
- -- the space is why we sometimes have collectors
- if nesting == 1 then
- -- if we had no space we could pass result directly in lmtx
- result = concat(buffer," ",1,n)
- if n > 500 or #result > 10000 then
- gbuffer = { } -- newtable(20,0)
- lbuffer = gbuffer
- end
- else
- -- if we had no space we could pass result directly in lmtx
- result = concat(buffer," ")
- end
- if trace_luarun then
- report_luarun("%i: %i buffered results: %s",nesting,n,result)
- end
- end
-
- if nesting == 1 then
- n = 0
- else
- buffer = lbuffer
- n = ln
- end
-
- else
- report_luarun("%i: no result, invalid code: %s",nesting,code)
- result = ""
- end
-
- nesting = nesting - 1
-
- return result
- end
-
- function metapost.nofscriptruns()
- return runs
- end
-
- -- writers
-
- local function mpp(value)
- n = n + 1
- local t = type(value)
- if t == "number" then
- buffer[n] = f_numeric(value)
- elseif t == "string" then
- buffer[n] = value
- elseif t == "table" then
- if #t == 6 then
- buffer[n] = "totransform(" .. concat(value,",") .. ")"
- else
- buffer[n] = "(" .. concat(value,",") .. ")"
- end
- else -- boolean or whatever
- buffer[n] = tostring(value)
- end
- end
-
- local function mpprint(first,second,...)
- if second == nil then
- if first ~= nil then
- mpp(first)
- end
- else
- for i=1,select("#",first,second,...) do
- local value = (select(i,first,second,...))
- if value ~= nil then
- mpp(value)
- end
- end
- end
- end
-
- local function mpp(value)
- n = n + 1
- local t = type(value)
- if t == "number" then
- buffer[n] = f_numeric(value)
- elseif t == "string" then
- buffer[n] = lpegmatch(p,value)
- elseif t == "table" then
- if #t > 4 then
- buffer[n] = ""
- else
- buffer[n] = "(" .. concat(value,",") .. ")"
- end
- else -- boolean or whatever
- buffer[n] = tostring(value)
- end
- end
-
- local function mpvprint(first,second,...) -- variable print
- if second == nil then
- if first ~= nil then
- mpp(first)
- end
- else
- for i=1,select("#",first,second,...) do
- local value = (select(i,first,second,...))
- if value ~= nil then
- mpp(value)
- end
- end
- end
- end
-
- local function mpstring(value)
- n = n + 1
- buffer[n] = lpegmatch(p,value)
- end
-
- local function mpboolean(b)
- n = n + 1
- buffer[n] = b and "true" or "false"
- end
-
- local function mpnumeric(f)
- n = n + 1
- if not f or f == 0 then
- buffer[n] = "0"
- else
- buffer[n] = f_numeric(f)
- end
- end
-
- local function mpinteger(i)
- n = n + 1
- -- buffer[n] = i and f_integer(i) or "0"
- buffer[n] = i or "0"
- end
-
- local function mppoints(i)
- n = n + 1
- if not i or i == 0 then
- buffer[n] = "0pt"
- else
- buffer[n] = f_points(i)
- end
- end
-
- local function mppair(x,y)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_pair(x[1],x[2])
- else
- buffer[n] = f_pair(x,y)
- end
- end
-
- local function mppairpoints(x,y)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_pair_pt(x[1],x[2])
- else
- buffer[n] = f_pair_pt(x,y)
- end
- end
-
- local function mptriplet(x,y,z)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_triplet(x[1],x[2],x[3])
- else
- buffer[n] = f_triplet(x,y,z)
- end
- end
-
- local function mptripletpoints(x,y,z)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_triplet_pt(x[1],x[2],x[3])
- else
- buffer[n] = f_triplet_pt(x,y,z)
- end
- end
-
- local function mpquadruple(w,x,y,z)
- n = n + 1
- if type(w) == "table" then
- buffer[n] = f_quadruple(w[1],w[2],w[3],w[4])
- else
- buffer[n] = f_quadruple(w,x,y,z)
- end
- end
-
- local function mpquadruplepoints(w,x,y,z)
- n = n + 1
- if type(w) == "table" then
- buffer[n] = f_quadruple_pt(w[1],w[2],w[3],w[4])
- else
- buffer[n] = f_quadruple_pt(w,x,y,z)
- end
- end
-
- local function mptransform(x,y,xx,xy,yx,yy)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_transform(x[1],x[2],x[3],x[4],x[5],x[6])
- else
- buffer[n] = f_transform(x,y,xx,xy,yx,yy)
- end
- end
-
- local function mpcolor(c,m,y,k)
- n = n + 1
- if type(c) == "table" then
- local l = #c
- if l == 4 then
- buffer[n] = f_quadruple(c[1],c[2],c[3],c[4])
- elseif l == 3 then
- buffer[n] = f_triplet(c[1],c[2],c[3])
- else
- buffer[n] = f_numeric(c[1])
- end
- else
- if k then
- buffer[n] = f_quadruple(c,m,y,k)
- elseif y then
- buffer[n] = f_triplet(c,m,y)
- else
- buffer[n] = f_numeric(c)
- end
- end
- end
-
- -- we have three kind of connectors:
- --
- -- .. ... -- (true)
-
- local function mp_path(f2,f6,t,connector,cycle)
- if type(t) == "table" then
- local tn = #t
- if tn == 1 then
- local t1 = t[1]
- n = n + 1
- if t.pen then
- buffer[n] = f_pen(unpack(t1))
- else
- buffer[n] = f2(t1[1],t1[2])
- end
- elseif tn > 0 then
- if connector == true or connector == nil then
- connector = ".."
- elseif connector == false then
- connector = "--"
- end
- if cycle == nil then
- cycle = t.cycle
- if cycle == nil then
- cycle = true
- end
- end
- local six = connector == ".." -- otherwise we use whatever gets asked for
- local controls = connector -- whatever
- local a = t[1]
- local b = t[2]
- n = n + 1
- buffer[n] = "("
- n = n + 1
- if six and #a == 6 and #b == 6 then
- buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4])
- controls = ".."
- else
- buffer[n] = f2(a[1],a[2])
- controls = connector
- end
- for i=2,tn-1 do
- a = b
- b = t[i+1]
- n = n + 1
- buffer[n] = connector
- n = n + 1
- if six and #a == 6 and #b == 6 then
- buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4])
- controls = ".."
- else
- buffer[n] = f2(a[1],a[2])
- controls = connector
- end
- end
- n = n + 1
- buffer[n] = connector
- a = b
- b = t[1]
- n = n + 1
- if cycle then
- if six and #a == 6 and #b == 6 then
- buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4])
- controls = ".."
- else
- buffer[n] = f2(a[1],a[2])
- controls = connector
- end
- n = n + 1
- buffer[n] = connector
- n = n + 1
- buffer[n] = "cycle"
- else
- buffer[n] = f2(a[1],a[2])
- end
- n = n + 1
- buffer[n] = ")"
- end
- end
- end
-
- local function mppath(...)
- mp_path(f_pair,f_ctrl,...)
- end
-
- local function mppathpoints(...)
- mp_path(f_pair_pt,f_ctrl_pt,...)
- end
-
- local function mpsize(t)
- n = n + 1
- buffer[n] = type(t) == "table" and f_numeric(#t) or "0"
- end
-
- local replacer = lpeg.replacer("@","%%")
-
- local function mpfprint(fmt,...)
- n = n + 1
- if not find(fmt,"%",1,true) then
- fmt = lpegmatch(replacer,fmt)
- end
- buffer[n] = formatters[fmt](...)
- end
-
- local function mpquoted(fmt,s,...)
- if s then
- n = n + 1
- if not find(fmt,"%",1,true) then
- fmt = lpegmatch(replacer,fmt)
- end
- -- buffer[n] = '"' .. formatters[fmt](s,...) .. '"'
- buffer[n] = lpegmatch(p,formatters[fmt](s,...))
- elseif fmt then
- n = n + 1
- -- buffer[n] = '"' .. fmt .. '"'
- buffer[n] = lpegmatch(p,fmt)
- else
- -- something is wrong
- end
- end
-
- aux.direct = mpdirect1
- aux.direct1 = mpdirect1
- aux.direct2 = mpdirect2
- aux.direct3 = mpdirect3
- aux.direct4 = mpdirect4
- aux.flush = mpflush
-
- aux.print = mpprint
- aux.vprint = mpvprint
- aux.boolean = mpboolean
- aux.string = mpstring
- aux.numeric = mpnumeric
- aux.number = mpnumeric
- aux.integer = mpinteger
- aux.points = mppoints
- aux.pair = mppair
- aux.pairpoints = mppairpoints
- aux.triplet = mptriplet
- aux.tripletpoints = mptripletpoints
- aux.quadruple = mpquadruple
- aux.quadruplepoints = mpquadruplepoints
- aux.path = mppath
- aux.pathpoints = mppathpoints
- aux.size = mpsize
- aux.fprint = mpfprint
- aux.quoted = mpquoted
- aux.transform = mptransform
- aux.color = mpcolor
-
- -- for the moment
-
- local function mpdraw(lines,list) -- n * 4
- if list then
- local c = #lines
- for i=1,c do
- local ci = lines[i]
- local ni = #ci
- n = n + 1 buffer[n] = i < c and "d(" or "D("
- for j=1,ni,2 do
- local l = j + 1
- n = n + 1 buffer[n] = ci[j]
- n = n + 1 buffer[n] = ","
- n = n + 1 buffer[n] = ci[l]
- n = n + 1 buffer[n] = l < ni and ")--(" or ");"
- end
- end
- else
- local l = #lines
- local m = l - 4
- for i=1,l,4 do
- n = n + 1 buffer[n] = i < m and "d(" or "D("
- n = n + 1 buffer[n] = lines[i]
- n = n + 1 buffer[n] = ","
- n = n + 1 buffer[n] = lines[i+1]
- n = n + 1 buffer[n] = ")--("
- n = n + 1 buffer[n] = lines[i+2]
- n = n + 1 buffer[n] = ","
- n = n + 1 buffer[n] = lines[i+3]
- n = n + 1 buffer[n] = ");"
- end
- end
- end
-
- local function mpfill(lines,list)
- if list then
- local c = #lines
- for i=1,c do
- local ci = lines[i]
- local ni = #ci
- n = n + 1 buffer[n] = i < c and "f(" or "F("
- for j=1,ni,2 do
- local l = j + 1
- n = n + 1 buffer[n] = ci[j]
- n = n + 1 buffer[n] = ","
- n = n + 1 buffer[n] = ci[l]
- n = n + 1 buffer[n] = l < ni and ")--(" or ")--C;"
- end
- end
- else
- local l = #lines
- local m = l - 4
- for i=1,l,4 do
- n = n + 1 buffer[n] = i < m and "f(" or "F("
- n = n + 1 buffer[n] = lines[i]
- n = n + 1 buffer[n] = ","
- n = n + 1 buffer[n] = lines[i+1]
- n = n + 1 buffer[n] = ")--("
- n = n + 1 buffer[n] = lines[i+2]
- n = n + 1 buffer[n] = ","
- n = n + 1 buffer[n] = lines[i+3]
- n = n + 1 buffer[n] = ")--C;"
- end
- end
- end
-
- aux.draw = mpdraw
- aux.fill = mpfill
-
- for k, v in next, aux do mp[k] = v end
-
-end
-
-do
-
- -- Another experimental feature:
-
- local mpnumeric = mp.numeric
- local scanstring = scan.string
- local scriptindex = metapost.scriptindex
-
- function mp.mf_script_index(name)
- local index = scriptindex(name)
- -- report_script("method %i, name %a, index %i",1,name,index)
- mpnumeric(index)
- end
-
- -- once bootstrapped ... (needs pushed mpx instances)
-
- metapost.registerscript("scriptindex",function()
- local name = scanstring()
- local index = scriptindex(name)
- -- report_script("method %i, name %a, index %i",2,name,index)
- mpnumeric(index)
- end)
-
-end
-
--- the next will move to mlib-lmp.lua
-
-do
-
- local mpnamedcolor = attributes.colors.mpnamedcolor
- local mpprint = aux.print
- local scanstring = scan.string
-
- mp.mf_named_color = function(str)
- mpprint(mpnamedcolor(str))
- end
-
- -- todo: we can inject but currently we always get a string back so then
- -- we need to deal with it upstream in the color module ... not now
-
- metapost.registerscript("namedcolor",function()
- mpprint(mpnamedcolor(scanstring()))
- end)
+get.numeric = function(s) return get_numeric(currentmpx,s) end
+get.number = function(s) return get_numeric(currentmpx,s) end
+get.integer = function(s) return get_integer(currentmpx,s) end
+get.string = function(s) return get_string (currentmpx,s) end
+get.boolean = function(s) return get_boolean(currentmpx,s) end
+get.path = function(s) return get_path (currentmpx,s) end
+set.path = function(s,t) return set_path (currentmpx,s,t) end -- not working yet
+function metapost.pushscriptrunner(mpx)
+ insert(stack,mpx)
+ currentmpx = mpx
end
-function mp.n(t) -- used ?
- return type(t) == "table" and #t or 0
+function metapost.popscriptrunner()
+ currentmpx = remove(stack,mpx)
end
-do
-
- -- experiment: names can change
-
- local mppath = aux.path
- local mpsize = aux.size
-
- local whitespace = lpegpatterns.whitespace
- local newline = lpegpatterns.newline
- local setsep = newline^2
- local comment = (S("#%") + P("--")) * (1-newline)^0 * (whitespace - setsep)^0
- local value = (1-whitespace)^1 / tonumber
- local entry = Ct( value * whitespace * value)
- local set = Ct((entry * (whitespace-setsep)^0 * comment^0)^1)
- local series = Ct((set * whitespace^0)^1)
-
- local pattern = whitespace^0 * series
-
- local datasets = { }
- mp.datasets = datasets
-
- function mp.dataset(str)
- return lpegmatch(pattern,str)
- end
-
- function datasets.load(tag,filename)
- if not filename then
- tag, filename = file.basename(tag), tag
- end
- local data = lpegmatch(pattern,io.loaddata(filename) or "")
- datasets[tag] = {
- data = data,
- line = function(n) mppath(data[n or 1]) end,
- size = function() mpsize(data) end,
- }
- end
-
- table.setmetatablecall(datasets,function(t,k,f,...)
- local d = datasets[k]
- local t = type(d)
- if t == "table" then
- d = d[f]
- if type(d) == "function" then
- d(...)
- else
- mpvprint(...)
- end
- elseif t == "function" then
- d(f,...)
- end
- end)
-
+function metapost.currentmpx()
+ return currentmpx
end
--- \startluacode
--- local str = [[
--- 10 20 20 20
--- 30 40 40 60
--- 50 10
---
--- 10 10 20 30
--- 30 50 40 50
--- 50 20 -- the last one
---
--- 10 20 % comment
--- 20 10
--- 30 40 # comment
--- 40 20
--- 50 10
--- ]]
---
--- MP.myset = mp.dataset(str)
---
--- inspect(MP.myset)
--- \stopluacode
---
--- \startMPpage
--- color c[] ; c[1] := red ; c[2] := green ; c[3] := blue ;
--- for i=1 upto lua("mp.print(mp.n(MP.myset))") :
--- draw lua("mp.path(MP.myset[" & decimal i & "])") withcolor c[i] ;
--- endfor ;
--- \stopMPpage
-
--- texts:
-
-do
-
- local mptriplet = mp.triplet
-
- local bpfactor = number.dimenfactors.bp
- local textexts = nil
- local mptriplet = mp.triplet
- local nbdimensions = nodes.boxes.dimensions
-
- function mp.mf_tt_initialize(tt)
- textexts = tt
- end
-
- function mp.mf_tt_dimensions(n)
- local box = textexts and textexts[n]
- if box then
- -- could be made faster with nuts but not critical
- mptriplet(box.width*bpfactor,box.height*bpfactor,box.depth*bpfactor)
- else
- mptriplet(0,0,0)
- end
- end
-
- function mp.mf_tb_dimensions(category,name)
- local w, h, d = nbdimensions(category,name)
- mptriplet(w*bpfactor,h*bpfactor,d*bpfactor)
- end
-
- function mp.report(a,b,c,...)
- if c then
- report_message("%s : %s",a,formatters[(gsub(b,"@","%%"))](c,...))
- elseif b then
- report_message("%s : %s",a,b)
- elseif a then
- report_message("%s : %s","message",a)
- end
- end
-
-end
-
-do
-
- local mpprint = aux.print
- local modes = tex.modes
- local systemmodes = tex.systemmodes
-
- function mp.mode(s)
- mpprint(modes[s] and true or false)
- end
-
- function mp.systemmode(s)
- mpprint(systemmodes[s] and true or false)
- end
-
- mp.processingmode = mp.mode
+local status = mplib.status
+function metapost.currentmpxstatus()
+ return status and status(currentmpx) or 0
end
-
--- for alan's nodes:
-
-do
-
- local mpprint = aux.print
- local mpquoted = aux.quoted
-
- function mp.isarray(str)
- mpprint(find(str,"%d") and true or false)
- end
-
- function mp.prefix(str)
- mpquoted(match(str,"^(.-)[%d%[]") or str)
- end
-
- -- function mp.dimension(str)
- -- local n = 0
- -- for s in gmatch(str,"%[?%-?%d+%]?") do --todo: lpeg
- -- n = n + 1
- -- end
- -- mpprint(n)
- -- end
-
- mp.dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer,mpprint)
-
- -- faster and okay as we don't have many variables but probably only
- -- basename makes sense and even then it's not called that often
-
- -- local hash = table.setmetatableindex(function(t,k)
- -- local v = find(k,"%d") and true or false
- -- t[k] = v
- -- return v
- -- end)
- --
- -- function mp.isarray(str)
- -- mpprint(hash[str])
- -- end
- --
- -- local hash = table.setmetatableindex(function(t,k)
- -- local v = '"' .. (match(k,"^(.-)%d") or k) .. '"'
- -- t[k] = v
- -- return v
- -- end)
- --
- -- function mp.prefix(str)
- -- mpprint(hash[str])
- -- end
-
-end
-
-do
-
- local getmacro = tex.getmacro
- local getdimen = tex.getdimen
- local getcount = tex.getcount
- local gettoks = tex.gettoks
- local setmacro = tex.setmacro
- local setdimen = tex.setdimen
- local setcount = tex.setcount
- local settoks = tex.settoks
-
- local mpprint = mp.print
- local mpquoted = mp.quoted
-
- local bpfactor = number.dimenfactors.bp
-
- -- more helpers
-
- local function getmacro(k) mpprint (getmacro(k)) end
- local function getdimen(k) mpprint (getdimen(k)*bpfactor) end
- local function getcount(k) mpprint (getcount(k)) end
- local function gettoks (k) mpquoted(gettoks (k)) end
-
- local function setmacro(k,v) setmacro(k,v) end
- local function setdimen(k,v) setdimen(k,v/bpfactor) end
- local function setcount(k,v) setcount(k,v) end
- local function settoks (k,v) settoks (k,v) end
-
- -- def foo = lua.mp.foo ... enddef ; % loops due to foo in suffix
-
- mp._get_macro_ = getmacro mp.getmacro = getmacro
- mp._get_dimen_ = getdimen mp.getdimen = getdimen
- mp._get_count_ = getcount mp.getcount = getcount
- mp._get_toks_ = gettoks mp.gettoks = gettoks
-
- mp._set_macro_ = setmacro mp.setmacro = setmacro
- mp._set_dimen_ = setdimen mp.setdimen = setdimen
- mp._set_count_ = setcount mp.setcount = setcount
- mp._set_toks_ = settoks mp.settoks = settoks
-
-end
-
--- position fun
-
-do
-
- local mpprint = mp.print
- local mpfprint = mp.fprint
- local mpquoted = mp.quoted
- local jobpositions = job.positions
- local getwhd = jobpositions.whd
- local getxy = jobpositions.xy
- local getposition = jobpositions.position
- local getpage = jobpositions.page
- local getregion = jobpositions.region
- local getmacro = tokens.getters.macro
-
- function mp.positionpath(name)
- local w, h, d = getwhd(name)
- if w then
- mpfprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",0,-d,w,-d,w,h,0,h)
- else
- mpprint("(origin--cycle)")
- end
- end
-
- function mp.positioncurve(name)
- local w, h, d = getwhd(name)
- if w then
- mpfprint("((%p,%p)..(%p,%p)..(%p,%p)..(%p,%p)..cycle)",0,-d,w,-d,w,h,0,h)
- else
- mpprint("(origin--cycle)")
- end
- end
-
- function mp.positionbox(name)
- local p, x, y, w, h, d = getposition(name)
- if p then
- mpfprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",x,y-d,x+w,y-d,x+w,y+h,x,y+h)
- else
- mpprint("(%p,%p)",x,y)
- end
- end
-
- function mp.positionxy(name)
- local x, y = getxy(name)
- if x then
- mpfprint("(%p,%p)",x,y)
- else
- mpprint("origin")
- end
- end
-
- function mp.positionpage(name)
- mpfprint("%i",getpage(name) or 0)
- end
-
- function mp.positionregion(name)
- local r = getregion(name)
- if r then
- mpquoted(r)
- else
- mpquoted("unknown")
- end
- end
-
- function mp.positionwhd(name)
- local w, h, d = getwhd(name)
- if w then
- mpfprint("(%p,%p,%p)",w,h,d)
- else
- mpprint("(0,0,0)")
- end
- end
-
- function mp.positionpxy(name)
- local p, x, y = getposition(name)
- if p then
- mpfprint("(%p,%p,%p)",p,x,y)
- else
- mpprint("(0,0,0)")
- end
- end
-
- function mp.positionanchor()
- mpquoted(getmacro("MPanchorid"))
- end
-
-end
-
-do
-
- local mppair = mp.pair
-
- function mp.textextanchor(s)
- local x, y = match(s,"tx_anchor=(%S+) (%S+)") -- todo: make an lpeg
- if x and y then
- x = tonumber(x)
- y = tonumber(y)
- end
- mppair(x or 0,y or 0)
- end
-
-end
-
-do
-
- local mpprint = mp.print
- local mpquoted = mp.quoted
- local getmacro = tokens.getters.macro
-
- function mp.texvar(name)
- mpprint(getmacro(metapost.namespace .. name))
- end
-
- function mp.texstr(name)
- mpquoted(getmacro(metapost.namespace .. name))
- end
-
-end
-
-do
-
- local mpprint = aux.print
- local mpvprint = aux.vprint
-
- local hashes = { }
-
- function mp.newhash(name)
- if name then
- hashes[name] = { }
- else
- for i=1,#hashes+1 do
- if not hashes[i] then
- hashes[i] = { }
- mpvprint(i)
- return
- end
- end
- end
- end
-
- function mp.disposehash(n)
- if tonumber(n) then
- hashes[n] = false
- else
- hashes[n] = nil
- end
- end
-
- function mp.inhash(n,key)
- local h = hashes[n]
- mpvprint(h and h[key] and true or false)
- end
-
- function mp.tohash(n,key,value)
- local h = hashes[n]
- if h then
- if value == nil then
- h[key] = true
- else
- h[key] = value
- end
- end
- end
-
- function mp.fromhash(n,key)
- local h = hashes[n]
- mpvprint(h and h[key] or false)
- end
-
- interfaces.implement {
- name = "MPfromhash",
- arguments = "2 strings",
- actions = function(name,key)
- local h = hashes[name] or hashes[tonumber(name)]
- if h then
- local v = h[key] or h[tonumber(key)]
- if v then
- context(v)
- end
- end
- end
- }
-
-end
-
-do
-
- -- a bit overkill: just a find(str,"mf_object=") can be enough
- --
- -- todo : share with mlib-pps.lua metapost,isobject
-
- local mpboolean = aux.boolean
-
- local p1 = P("mf_object=")
- local p2 = lpegpatterns.eol * p1
- local pattern = (1-p2)^0 * p2 + p1
-
- function mp.isobject(str)
- mpboolean(pattern and str ~= "" and lpegmatch(pattern,str))
- end
-
-end
-
-function mp.flatten(t)
- local tn = #t
-
- local t1 = t[1]
- local t2 = t[2]
- local t3 = t[3]
- local t4 = t[4]
-
- for i=1,tn-5,2 do
- local t5 = t[i+4]
- local t6 = t[i+5]
- if t1 == t3 and t3 == t5 and ((t2 <= t4 and t4 <= t6) or (t6 <= t4 and t4 <= t2)) then
- t[i+3] = t2
- t4 = t2
- t[i] = false
- t[i+1] = false
- elseif t2 == t4 and t4 == t6 and ((t1 <= t3 and t3 <= t5) or (t5 <= t3 and t3 <= t1)) then
- t[i+2] = t1
- t3 = t1
- t[i] = false
- t[i+1] = false
- end
- t1 = t3
- t2 = t4
- t3 = t5
- t4 = t6
- end
-
- -- remove duplicates
-
- local t1 = t[1]
- local t2 = t[2]
- for i=1,tn-2,2 do
- local t3 = t[i+2]
- local t4 = t[i+3]
- if t1 == t3 and t2 == t4 then
- t[i] = false
- t[i+1] = false
- end
- t1 = t3
- t2 = t4
- end
-
- -- move coordinates
-
- local m = 0
- for i=1,tn,2 do
- if t[i] then
- m = m + 1 t[m] = t[i]
- m = m + 1 t[m] = t[i+1]
- end
- end
-
- -- prune the table (not gc'd)
-
- for i=tn,m+1,-1 do
- t[i] = nil
- end
-
- -- safeguard so that we have at least one segment
-
- if m == 2 then
- t[3] = t[1]
- t[4] = t[2]
- end
-
-end
-
-do
-
- -- if needed we can optimize the sub (cache last split)
-
- local utflen = utf.len
- local utfsub = utf.sub
-
- function mp.utflen(s)
- mpnumeric(utflen(s))
- end
-
- function mp.utfsub(s,f,t)
- mpquoted(utfsub(s,f,t or f))
- end
-
-end
-