if not modules then modules = { } end modules ['font-mpf'] = {
    version   = 1.001,
    comment   = "companion to font-ini.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local tonumber, unpack, type = tonumber, unpack, type

local context  = context
local metapost = metapost

local metafonts    = { }
metapost.metafonts = metafonts

local sortedhash        = table.sortedhash

local addcharacters     = fonts.constructors.addcharacters
local fontdata          = fonts.hashes.identifiers

local otf               = fonts.handlers.otf
local otfregister       = otf.features.register

local getshapes         = fonts.dropins.getshapes

local setparameterset   = metapost.setparameterset
local simplemetapost    = metapost.simple

local register          = fonts.collections.register
local checkenabled      = fonts.collections.checkenabled
local newprivateslot    = fonts.helpers.newprivateslot

local currentfont       = font.current

local function setmetaglyphs(category,fontid,unicode,specification)
    if unicode then
        local tfmdata    = fontdata[fontid]
        local characters = tfmdata.characters
        specification.unicode  = unicode
        specification.category = category
        -- Generate one shape, make a use we pass the unicode as that is
        -- the index in a picture list (normally). We could actually already
        -- fetch the stream but for now we do that later (i.e. we delay the
        -- serialization to pdf).
        local code = specification.code
        if code then
            setparameterset("mpsfont",specification)
         -- simplemetapost(instance,"begingroup;",true,true)
            simplemetapost("simplefun",code)
         -- simplemetapost(instance,"endgroup;",true,true)
        end
        -- We now know (hopefully) the dimensions of the image which is what
        -- we need to pass to the engine in order to let it do its work.
        local shapes = getshapes(category)
        local units  = shapes.parameters.units
        local scale  = tfmdata.parameters.size / units
        local shape  = shapes.glyphs[unicode]
        if shape then
            --
            local llx, lly, urx, ury = unpack(shape.boundingbox)
            llx = llx * scale
            urx = urx * scale
            lly = lly * scale
            ury = ury * scale
            --
            local newdata = { }
            characters[unicode] = newdata -- so that we can register commands
            fonts.dropins.swapone("mps",tfmdata,shape,unicode)
            --
            local olddata = characters[unicode]
            newdata.width   = urx - llx
            newdata.height  = ury
            newdata.depth   = -lly
            newdata.unicode = unicode
            -- commands = { { "offset", -llx, 0, newdata.commands[1][1], newdata.commands[1][2] } }
            if llx ~= 0 then
                newdata.commands = { { "offset", -llx, 0 }, newdata.commands[1] }
            end
            -- pass dimensions to lua
            characters[unicode] = newdata
            -- pass dimensions to tex
            addcharacters(fontid, { characters = { [unicode] = newdata } })
            return fontid, unicode
        else
            logs.report("metaglyph", "bad shape %U in font %i", unicode, fontid)
        end
    end
end

local function setmetaglyph(specification)
    if specification then
        local category = specification.category
        local name     = specification.name
        if category and name then
            local fontid  = specification.fontid or currentfont()
            local private = newprivateslot(name)
            register(fontid,private,function(font,char)
                return setmetaglyphs(category,font,char,specification) end
            )
            checkenabled()
        end
    end
end

local function initializempf(tfmdata,kind,value)
    local metafont = metafonts[value]
    if value then
        local font = tfmdata.properties.id
        for char, spec in sortedhash(metafont) do
            if type(char) == "string" then
                char = newprivateslot(char)
            end
            register(font,char,function(font,char)
                return setmetaglyphs(value,font,char,spec)
            end)
        end
        checkenabled()
    end
end

fonts.helpers.setmetaglyphs = setmetaglyphs
fonts.helpers.setmetaglyph  = setmetaglyph

otfregister {
    name         = "metafont",
    description  = "metafont glyphs",
    manipulators = {
        base = initializempf,
        node = initializempf,
    }
}

do

    local scanners   = tokens.scanners
    local scanopen   = scanners.scanopen
    local scanclose  = scanners.scanclose
    local scanword   = scanners.word
    local scanstring = scanners.string

    interfaces.implement {
        name      = "setmetaglyph",
        public    = true,
        protected = true,
        actions   = function(t)
            local t = { }
            if scanopen() then
                 while not scanclose() do
                    local key = scanword()
                    if key == "shapes" then
                        if scanopen() then
                            local tt = { }
                            local nn = 0
                            while not scanclose() do
                                if scanopen() then
                                    local ttt = { }
                                    while not scanclose() do
                                        local key = scanword()
                                        ttt[key] = scanstring()
                                    end
                                    nn= nn + 1
                                    tt[nn] = ttt
                                end
                            end
                            t[key] = tt
                        end
                    else
                        t[key] = scanstring()
                    end
                end
            end
            setmetaglyph(t)
        end
    }

end
