if not modules then modules = { } end modules ['mlib-lmt'] = {
    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: check for possible inject usage

local type = type
local round, abs = math.round, math.abs

local aux            = mp.aux
local mpdirect       = aux.direct
local mppath         = mp.path

local scan           = mp.scan
local scannumeric    = scan.numeric
local scanpath       = scan.path

local injectpath     = mp.inject.path
local injectnumeric  = mp.inject.numeric
local injectcolor    = mp.inject.color

local getparameter   = metapost.getparameter
local registerscript = metapost.registerscript

function mp.lmt_function_x(xmin,xmax,xstep,code,shape) -- experimental
    local code      = "return function(x) return " .. code .. " end"
    local action    = load(code)
    local points    = { }
    local nofpoints = 0
    if action then
         action = action()
    end
    if shape == "steps" then
        local halfx     = xstep / 2
        local lastx     = xmin
        local lasty     = action(xmin)
        for xi = xmin, xmax, xstep do
            local yi  = action(xi)
            local xx  = lastx + halfx
            nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, lasty }
            nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, yi }
            lastx     = xi
            lasty     = yi
        end
        if points[nofpoints][1] ~= xmax then
            local yi  = action(xmax)
            local xx  = lastx + halfx
            nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, lasty }
            nofpoints = nofpoints + 1 ; points[nofpoints] = { xx, yi }
            lastx     = xi
            lasty     = yi
        end
    else
        for xi = xmin, xmax, xstep do
            nofpoints = nofpoints + 1 ; points[nofpoints] = { xi, action(xi) }
        end
        if points[nofpoints][1] ~= xmax then
            nofpoints = nofpoints + 1 ; points[nofpoints] = { xmax, action(xmax) }
        end
    end
    mppath(points,shape == "curve" and ".." or "--",false)
end

function mp.lmt_mesh_set()
    local mesh = getparameter { "mesh", "paths" }
    structures.references.currentset.mesh = mesh
end

function mp.lmt_mesh_update()
    local mesh = getparameter { "paths" } or getparameter { "mesh", "paths" }
    mesh[scannumeric()] = scanpath(true)
end

-- moved here

function mp.lmt_svg_include()
    local labelfile = metapost.getparameter { "labelfile" }
    if labelfile and labelfile ~= "" then
        labelfile = resolvers.findbinfile(labelfile)
    end
    if labelfile and labelfile ~= "" then
        local labels = table.load(labelfile) -- todo: same path as svg file
        if type(labels) == "table" then
            for i=1,#labels do
                metapost.remaptext(labels[i])
            end
        end
    end
    local fontname = metapost.getparameter { "fontname" }
    if fontname and fontname ~= "" then
        local unicode = metapost.getparameter { "unicode" }
        if unicode then
            mpdirect (
                metapost.svgglyphtomp(fontname,math.round(unicode))
            )
        end
        return
    end
    local colorfile = metapost.getparameter { "colormap" }
    local colormap  = false
    if colorfile and colorfile ~= "" then
        colormap = metapost.svgcolorremapper(colorfile)
    end
    local filename = metapost.getparameter { "filename" }
    if filename and filename ~= "" then
        local ok, data = resolvers.loadbinfile(filename)
        mpdirect ( metapost.svgtomp {
            data     = data,
            remap    = true,
            colormap = colormap,
            id       = filename,
        } )
    else
        local buffer = metapost.getparameter { "buffer" }
        if buffer then
            mpdirect ( metapost.svgtomp {
                data     = buffers.getcontent(buffer),
             -- remap    = true,
                colormap = colormap,
                id       = buffer or "buffer",
            } )
        else
            local code = metapost.getparameter { "code" }
            if code then
                mpdirect ( metapost.svgtomp {
                    data     = code,
                    colormap = colormap,
                    id       = "code",
                } )
            end
        end
    end
end

registerscript("remaptext", function()
    local parameters = metapost.scanparameters(true) -- gobble the semi colon (avoid lookahead)
    if parameters and parameters.label then
        metapost.remaptext(parameters)
    end
end)

do

    local dropins        = fonts.dropins
    local registerglyph  = dropins.registerglyph
    local registerglyphs = dropins.registerglyphs

    registerscript("registerglyph", function() registerglyph (metapost.getparameterset("mpsglyph"))  end)
    registerscript("registerglyphs",function() registerglyphs(metapost.getparameterset("mpsglyphs")) end)

end

todecimal = xdecimal and xdecimal.new or tonumber -- bonus

-- mail on list by Mikael Sundqvist and Taco's analysis of near duplicate points (2021/02/11+)

registerscript("scrutinized", function()
    local pth = scanpath()
-- for i=1,#pth do
--     pth[i].right_type = nil
--     pth[i].left_type = nil
-- end
    local d   = 1/(10^scannumeric()) -- decimals
    local p1  = pth[1]
    local x1  = p1[1]
    local y1  = p1[2]
    local res = { pth[1] }
    local r   = 1
    for i=2,#pth do
        local pi = pth[i]
        x2 = pi[1]
        y2 = pi[2]
        if abs(x1-x2) > d or abs(y1-y2) > d then
            r = r + 1 res[r] = pi
            x1 = x2
            y1 = y2
        else
            res[r][5] = pi[5]
            res[r][6] = pi[6]
        end
    end
    if pth.cycle then
        res.cycle = true
        if abs(x1-p1[1]) > d or abs(y1-p1[2]) > d then
            -- keep
        else
            p1[3] = res[r][3]
            p1[4] = res[r][4]
            res[r] = nil
        end
    end
    injectpath(res)
end)

local newtable = lua.newtable

registerscript("recycled", function()
    local pth = scanpath()
    local n   = scannumeric()
    local p   = #pth
    n = n % p
    if n == 0 or not pth.cycle then -- table.rotate
        injectpath(pth)
    else
      local res = newtable(p,1)
      local r   = 0
      for i=p-n+1,p do
          r = r + 1 ; res[r] = pth[i]
      end
      for i=1,p-n do
          r = r + 1 ; res[r] = pth[i]
      end
-- for i=1,r do
--     res[i].right_type = nil
--     res[i].left_type  = nil
-- end
        res.cycle = true
        injectpath(res)
    end
end)

-- A goodie, mostly a side effect of updating the metafun manual.

local labtorgb = attributes.colors.labtorgb
local xyxtorgb = attributes.colors.xyztorgb
local lchtorgb = attributes.colors.lchtorgb
local hsvtorgb = attributes.colors.hsvtorgb
local hwbtorgb = attributes.colors.hwbtorgb

registerscript("labtorgb", function() injectcolor(labtorgb(scannumeric(),scannumeric(),scannumeric())) end)
registerscript("xyztorgb", function() injectcolor(xyztorgb(scannumeric(),scannumeric(),scannumeric())) end)
registerscript("lchtorgb", function() injectcolor(lchtorgb(scannumeric(),scannumeric(),scannumeric())) end)
registerscript("hsvtorgb", function() injectcolor(hsvtorgb(scannumeric(),scannumeric(),scannumeric())) end)
registerscript("hwbtorgb", function() injectcolor(hwbtorgb(scannumeric(),scannumeric(),scannumeric())) end)
