summaryrefslogtreecommitdiff
path: root/tex/context/base/mlib-ctx.lua
blob: a1a4e645a5267097007a924d8c4c2a0b71707713 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
if not modules then modules = { } end modules ['mlib-ctx'] = {
    version   = 1.001,
    comment   = "companion to mlib-ctx.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files",
}

-- todo

local format, concat = string.format, table.concat
local settings_to_hash = utilities.parsers.settings_to_hash

local report_metapost = logs.reporter("metapost")

local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming

local mplib = mplib

metapost       = metapost or {}
local metapost = metapost

local v_no = interfaces.variables.no

metapost.defaultformat   = "metafun"
metapost.defaultinstance = "metafun"
metapost.defaultmethod   = "default"

local function setmpsformat(specification)
    local instance = specification.instance
    local format   = specification.format
    local method   = specification.method
    if not instance or instance == "" then
        instance = metapost.defaultinstance
        specification.instance = instance
    end
    if not format or format == "" then
        format = metapost.defaultformat
        specification.format = format
    end
    if not method or method == "" then
        method = metapost.defaultmethod
        specification.method = method
    end
    specification.mpx = metapost.format(instance,format,method)
    return specification
end

local extensiondata    = metapost.extensiondata or storage.allocate { }
metapost.extensiondata = extensiondata

storage.register("metapost/extensiondata",extensiondata,"metapost.extensiondata")

function metapost.setextensions(instances,data)
    if data and data ~= "" then
        extensiondata[#extensiondata+1] = {
            usedinall  = not instances or instances == "",
            instances  = settings_to_hash(instances or ""),
            extensions = data,
        }
    end
end

function metapost.getextensions(instance,state)
    if state and state == v_no then
        return ""
    else
        local t = { }
        for i=1,#extensiondata do
            local e = extensiondata[i]
            local status = e.instances[instance]
            if (status ~= true) and (e.usedinall or status) then
                t[#t+1] = e.extensions
                e.instances[instance] = true
            end
        end
        return concat(t," ")
    end
end

function commands.getmpextensions(instance,state)
    context(metapost.getextensions(instance,state))
end

function metapost.graphic(specification)
    setmpsformat(specification)
    metapost.graphic_base_pass(specification)
end

function metapost.getclippath(specification) -- why not a special instance for this
    setmpsformat(specification)
    local mpx = specification.mpx
    local data = specification.data or ""
    if mpx and data ~= "" then
        starttiming(metapost)
        starttiming(metapost.exectime)
        local result = mpx:execute ( format ( "%s;%s;beginfig(1);%s;%s;endfig;",
            specification.extensions or "",
            specification.inclusions or "",
            specification.initializations or "",
            data
        ) )
        stoptiming(metapost.exectime)
        if result.status > 0 then
            report_metapost("%s: %s", result.status, result.error or result.term or result.log)
            result = nil
        else
            result = metapost.filterclippath(result)
        end
        stoptiming(metapost)
        return result
    end
end

function metapost.filterclippath(result)
    if result then
        local figures = result.fig
        if figures and #figures > 0 then
            local figure = figures[1]
            local objects = figure:objects()
            if objects then
                local lastclippath
                for o=1,#objects do
                    local object = objects[o]
                    if object.type == "start_clip" then
                        lastclippath = object.path
                    end
                end
                return lastclippath
            end
        end
    end
end

function metapost.theclippath(...)
    local result = metapost.getclippath(...)
    if result then -- we could just print the table
        result = concat(metapost.flushnormalpath(result),"\n")
        context(result)
    end
end

statistics.register("metapost processing time", function()
    local n =  metapost.n
    if n and n > 0 then
        local nofconverted = metapost.makempy.nofconverted
        local elapsedtime = statistics.elapsedtime
        local elapsed = statistics.elapsed
        local str = format("%s seconds, loading: %s, execution: %s, n: %s, average: %s",
            elapsedtime(metapost), elapsedtime(mplib), elapsedtime(metapost.exectime), n,
            elapsedtime((elapsed(metapost) + elapsed(mplib) + elapsed(metapost.exectime)) / n))
        if nofconverted > 0 then
            return format("%s, external: %s (%s calls)",
                str, elapsedtime(metapost.makempy), nofconverted)
        else
            return str
        end
    else
        return nil
    end
end)

-- only used in graphictexts

metapost.tex = metapost.tex or { }

local environments = { }

function metapost.tex.set(str)
    environments[#environments+1] = str
end

function metapost.tex.reset()
    environments = { }
end

function metapost.tex.get()
    return concat(environments,"\n")
end