mlib-lua.lmt /size: 9204 b    last modification: 2023-12-21 09:44
1if not modules then modules = { } end modules ['mlib-lua'] = {
2    version   = 1.001,
3    comment   = "companion to mlib-ctx.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files",
7}
8
9local type = type
10local insert, remove = table.insert, table.remove
11
12local trace  = false  trackers.register("metapost.instance",function(v) trace = v end)
13
14local report = logs.reporter("metapost","instance")
15
16local codes = mplib.getcodes()
17local types = mplib.gettypes()
18
19table.hashed(codes)
20table.hashed(types)
21
22metapost.codes = codes
23metapost.types = types
24
25local scan   = mp.scan
26local skip   = mp.skip
27local get    = mp.get
28local inject = mp.inject
29
30local bpfactor   = number.dimenfactors.bp
31local currentmpx = nil
32local stack      = { }
33
34local function reports(s) report("%a scan %s",  tostring(currentmpx),s) end -- temporary, till we're okay
35local function reporti(s) report("%a inject %s",tostring(currentmpx),s) end -- temporary, till we're okay
36
37local scannext       = mplib.scannext
38local scanexpression = mplib.scanexpression
39local scantoken      = mplib.scantoken
40local scansymbol     = mplib.scansymbol
41local scanproperty   = mplib.scanproperty
42local scannumeric    = mplib.scannumeric
43local scaninteger    = mplib.scaninteger
44local scanboolean    = mplib.scanboolean
45local scanstring     = mplib.scanstring
46local scanpair       = mplib.scanpair
47local scancolor      = mplib.scancolor
48local scancmykcolor  = mplib.scancmykcolor
49local scantransform  = mplib.scantransform
50local scanpath       = mplib.scanpath
51local scanpen        = mplib.scanpen
52
53local skiptoken      = mplib.skiptoken
54
55local gethashentry   = mplib.gethashentry
56
57scan.next       = function(k)     if trace then reporti("next")       end return scannext      (currentmpx,k)     end
58scan.expression = function(k)     if trace then reporti("expression") end return scanexpression(currentmpx,k)     end
59scan.token      = function(k)     if trace then reporti("token")      end return scantoken     (currentmpx,k)     end
60scan.symbol     = function(k,e)   if trace then reporti("symbol")     end return scansymbol    (currentmpx,k,e)   end
61scan.property   = function(k)     if trace then reporti("property")   end return scanproperty  (currentmpx,k)     end
62scan.numeric    = function()      if trace then reporti("numeric")    end return scannumeric   (currentmpx)       end
63scan.integer    = function()      if trace then reporti("integer")    end return scaninteger   (currentmpx)       end
64scan.boolean    = function()      if trace then reporti("boolean")    end return scanboolean   (currentmpx)       end
65scan.string     = function()      if trace then reporti("string")     end return scanstring    (currentmpx)       end
66scan.pair       = function(t)     if trace then reporti("pair")       end return scanpair      (currentmpx,t)     end
67scan.color      = function(t)     if trace then reporti("color")      end return scancolor     (currentmpx,t)     end
68scan.cmykcolor  = function(t)     if trace then reporti("cmykcolor")  end return scancmykcolor (currentmpx,t)     end
69scan.transform  = function(t)     if trace then reporti("transform")  end return scantransform (currentmpx,t)     end
70scan.path       = function(t,k,c) if trace then reporti("path")       end return scanpath      (currentmpx,t,k,c) end -- compact kind (prim) check
71scan.pen        = function(t)     if trace then reporti("pen")        end return scanpen       (currentmpx,t)     end
72
73skip.token      = function(t) return skiptoken   (currentmpx,t) end
74get.hashentry   = function(n) return gethashentry(currentmpx,n) end
75
76local solvepath = mplib.solvepath
77local getstatus = mplib.getstatus
78local expandtex = mplib.expandtex
79
80mp.solve     = function(...) return solvepath(currentmpx,...) end
81mp.expandtex = function(...) return expandtex(currentmpx,...) end
82
83local injectpath      = mplib.injectpath
84local injectnumeric   = mplib.injectnumeric
85local injectpair      = mplib.injectpair
86local injectboolean   = mplib.injectboolean
87local injectinteger   = mplib.injectinteger
88local injectstring    = mplib.injectstring
89local injectcolor     = mplib.injectcolor
90local injectcmykcolor = mplib.injectcmykcolor
91local injecttransform = mplib.injecttransform
92local injectwhatever  = mplib.injectwhatever
93
94------.path      = function(t,cycle,curled)  if trace then reporti("path")      end return injectpath     (currentmpx,t,cycle,curled)  end
95inject.numeric   = function(n)               if trace then reporti("numeric")   end return injectnumeric  (currentmpx,n)               end
96inject.pair      = function(x,y)             if trace then reporti("pair")      end return injectpair     (currentmpx,x,y)             end
97inject.boolean   = function(b)               if trace then reporti("boolean")   end return injectboolean  (currentmpx,b)               end
98inject.integer   = function(i)               if trace then reporti("integer")   end return injectinteger  (currentmpx,i)               end
99inject.string    = function(s)               if trace then reporti("string")    end return injectstring   (currentmpx,s)               end
100inject.color     = function(r,g,b)           if trace then reporti("color")     end return injectcolor    (currentmpx,r,g,b)           end
101inject.cmykcolor = function(c,m,y,k)         if trace then reporti("cmykcolor") end return injectcmykcolor(currentmpx,c,m,y,k)         end
102inject.transform = function(x,y,xx,xy,yx,yy) if trace then reporti("transform") end return injecttransform(currentmpx,x,y,xx,xy,yx,yy) end
103inject.whatever  = function(...)             if trace then reporti("whatever")  end return injectwhatever (currentmpx,...)             end
104
105inject.triplet    = inject.color
106inject.quadruplet = inject.cmykcolor
107
108-- these can be optimized for zero:
109
110inject.whd = function(w,h,d) injectcolor  (currentmpx,(w or 0)*bpfactor,(h or 0)*bpfactor,(d or 0)*bpfactor) end
111inject.xy  = function(x,y)   injectpair   (currentmpx,(x or 0)*bpfactor,(y or 0)*bpfactor) end
112inject.pt  = function(n)     injectnumeric(currentmpx,(n or 0)*bpfactor) end
113
114local function same(p,n)
115    local f = p[1]
116    local l = p[n]
117    local nf = #f
118    local nl = #l
119    if nf == nl then
120        for i=1,nf do
121            if f[i] ~= l[i] then
122                return false
123            end
124        end
125        return true
126    end
127    return false
128end
129
130-- function inject.path(p,close,connector)
131--     local closed = false
132--     local curled = false
133--     local n = #p
134-- print("spec",p,close,connector)
135--     if close == nil then
136--         closed = (p.close or p.cycle or p.closed) and true or false
137--     else
138--         closed = close
139--     end
140--     if connector then
141--         if connector == "auto" then
142--             connector = #p[1] > 2
143--         end
144--         if connector == false or connector == "--" then
145--             curled = true
146--      -- elseif connector == true or connector == ".." then
147--      --     if close and not same(p,n) then
148--      --         p[n+1] = p[1]
149--      --     end
150--         end
151--     elseif p.curled then
152--         curled = true
153--     end
154--     if trace then reporti("path") end
155--     inspect(p)
156--     print(p,closed,curled)
157--     return injectpath(currentmpx,p,closed,curled)
158-- end
159
160function inject.path(p,connector,close)
161    local closed = false
162    local curled = false
163    local n = #p
164    if close == nil then
165        closed = (p.close or p.cycle or p.closed) and true or false
166    else
167        closed = close
168    end
169    if connector then
170        if connector == "auto" then
171            connector = #p[1] > 2
172        end
173        if connector == false or connector == "--" then
174            curled = true
175        end
176    elseif p.curled then
177        curled = true
178    end
179    if trace then reporti("path") end
180    return injectpath(currentmpx,p,closed,curled)
181end
182
183-- bonus:
184
185scan  .number    = scan  .numeric
186inject.number    = inject.numeric
187
188table.setmetatablecall(inject,function(t,...)
189    injectwhatever(currentmpx,...)
190end)
191
192-- experiment
193
194function mp.autoinject(m)
195    local t = type(m)
196    if t == "table" then
197        local n = #t
198        if n == 2 then
199            injectpair(currentmpx,m)
200        elseif n == 3 then
201            injectcolor(currentmpx,m)
202        elseif n == 4 then
203            injectcmykcolor(currentmpx,m)
204        elseif n == 6 then
205            injecttransform(currentmpx,m)
206        end
207    elseif t == "number" then
208        injectnumeric(currentmpx,m)
209    elseif t == "string" then
210        injectstring(currentmpx,m)
211    elseif t == "boolean" then
212        injectboolean(currentmpx,m)
213    end
214end
215
216function metapost.pushscriptrunner(mpx)
217    if trace then
218        report("%a => %a",tostring(currentmpx),tostring(mpx))
219    end
220    insert(stack,currentmpx)
221    currentmpx = mpx
222end
223
224function metapost.popscriptrunner()
225    local mpx = remove(stack)
226    if trace then
227        report("%a <= %a",tostring(mpx),tostring(currentmpx))
228    end
229    currentmpx = mpx
230end
231
232function metapost.currentmpx()
233    return currentmpx
234end
235
236-- mplib.getstates(): zero is "normal"
237
238function metapost.currentmpxstatus()
239    return getstatus(currentmpx) or 0
240end
241