summaryrefslogtreecommitdiff
path: root/tex/context/base/x-math-svg.lua
blob: 8a628816773077451ea6a9b1f503ced0d1d315e7 (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
if not modules then modules = { } end modules ['x-math-svg'] = {
    version   = 1.001,
    comment   = "companion to x-math-svg.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local tostring, type, next = tostring, type, next
local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs

local xmlfirst      = xml.first
local xmlconvert    = xml.convert
local xmlload       = xml.load
local xmlsave       = xml.save
local xmlcollected  = xml.collected
local xmldelete     = xml.delete

local loadtable     = table.load
local savetable     = table.save

local replacesuffix = file.replacesuffix
local addsuffix     = file.addsuffix
local removefile    = os.remove
local isfile        = lfs.isfile

local formatters    = string.formatters

moduledata          = moduledata or table.setmetatableindex("table")
local svgmath       = moduledata.svgmath -- autodefined

local namedata      = { }
local pagedata      = { }

local statusname    = "x-math-svg-status.lua"
local pdfname       = "x-math-svg.pdf"

local pdftosvg      = os.which("mudraw")

local f_make_tex    = formatters[ [[context --global kpse:x-math-svg.mkvi --inputfile="%s" --svgstyle="%s" --batch --noconsole --once --purgeall]] ]
local f_make_svg    = formatters[ [[mudraw -o "math-%%d.svg" "%s" 1-9999]] ]

----- f_inline      = formatters[ [[<div class='math-inline' style='vertical-align:%p'></div>]] ]
local f_inline      = formatters[ [[<div class='math-inline'></div>]] ]
local f_display     = formatters[ [[<div class='math-display'></div>]] ]
local f_style       = formatters[ [[vertical-align:%p]] ]

local f_math_tmp    = formatters[ [[math-%i]] ]

function svgmath.process(filename)
    if not filename then
        -- no filename given
        return
    elseif not isfile(filename) then
        -- invalid filename
        return
    end
    local index = 0
    local page  = 0
    local blobs = { }
    local root  = xmlload(filename)
    for mth in xmlcollected(root,"math") do
        index = index + 1
        local blob = tostring(mth)
        if blobs[blob] then
            context.ReuseSVGMath(index,blobs[blob])
        else
            page = page + 1
            buffers.assign(f_math_tmp(page),blob)
            context.MakeSVGMath(index,page,mth.at.display)
            blobs[blob] = page
        end
    end
    context(function()
        -- for tracing purposes:
        for mathdata, pagenumber in next, blobs do
            local p  = pagedata[pagenumber]
            p.mathml = mathdata
            p.number = pagenumber
        end
        --
        savetable(statusname, {
            pagedata = pagedata,
            namedata = namedata,
        })
    end)
end

function svgmath.register(index,page,specification)
    if specification then
        pagedata[page] = specification
    end
    namedata[index] = page
end

function svgmath.convert(filename,svgstyle)
    if not filename then
        -- no filename given
        return false, "no filename"
    elseif not isfile(filename) then
        -- invalid filename
        return false, "invalid filename"
    elseif not pdftosvg then
        return false, "mudraw is not installed"
    end

    os.execute(f_make_tex(filename,svgstyle))

    local data = loadtable(statusname)
    if not data then
        -- invalid tex run
        return false, "invalid tex run"
    elseif not next(data) then
        return false, "no converson needed"
    end

    local pagedata = data.pagedata
    local namedata = data.namedata

    os.execute(f_make_svg(pdfname))

    local root   = xmlload(filename)
    local index  = 0
    local done   = { }
    local unique = 0

    local between = (1-P("<"))^1/""
    local strip = Cs((
        (P("<text") * ((1-P("</text>"))^1) * P("</text>")) * between^0 / "" +
        P(">") * between +
        P(1)
    )^1)

    for mth in xmlcollected(root,"m:math") do
        index = index + 1
        local page = namedata[index]
        if done[page] then
            mth.__p__.dt[mth.ni] = done[page]
        else
            local info    = pagedata[page]
            local depth   = info.depth
            local mode    = info.mode
            local svgname = addsuffix(f_math_tmp(page),"svg")
            local action  = mode == "inline" and f_inline or f_display
         -- local x_div   = xmlfirst(xmlconvert(action(-depth)),"/div")
            local x_div   = xmlfirst(xmlconvert(action()),"/div")
            local svgdata = io.loaddata(svgname)
            if not svgdata or svgdata == "" then
                print("error in:",svgname,tostring(mth))
            else
             -- svgdata = string.gsub(svgdata,">%s<","")
                svgdata = lpegmatch(strip,svgdata)
                local x_svg = xmlfirst(xmlconvert(svgdata),"/svg")
             -- xmldelete(x_svg,"text")
if mode == "inline" then
    x_svg.at.style = f_style(-depth)
end

                x_div.dt = { x_svg }
                mth.__p__.dt[mth.ni] = x_div -- use helper
            end
            done[page] = x_div
            unique = unique + 1
        end
    end

--     for k, v in next, data do
--         removefile(addsuffix(k,"svg"))
--     end
--     removefile(statusname)
--     removefile(pdfname)

    xmlsave(root,filename)

    return true, index, unique
end