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

local abs = math.abs

local next, type = next, type
local concat = table.concat
local formatters = string.formatters

local fonts              = fonts

local handlers           = fonts.handlers
local registerotffeature = handlers.otf.features.register
local registerafmfeature = handlers.afm.features.register

local settings_to_array  = utilities.parsers.settings_to_array
local setmetatableindex  = table.setmetatableindex

local helpers            = fonts.helpers
local appendcommandtable = helpers.appendcommandtable
local prependcommands    = helpers.prependcommands
local charcommand        = helpers.commands.char

local variables          = interfaces.variables

local v_background       <const> = variables.background
local v_frame            <const> = variables.frame
local v_empty            <const> = variables.empty
local v_none             <const> = variables.none

-- d:width d:height d:depth d:rulethickness b:outline b:advance b:baseline s:color

-- local function initialize(tfmdata,key,value)
--     if value then
--         local vfspecials  = fonts.helpers.vfspecials
--         local vfcommands  = fonts.helpers.commands
--         local backgrounds = vfspecials.backgrounds
--         local outlines    = vfspecials.outlines
--         local characters  = tfmdata.characters
--         local rulecache   = backgrounds
--         local showchar    = true
--         local color       = "palegray"
--         if type(value) == "string" then
--             value = settings_to_array(value)
--             for i=1,#value do
--                 local v = value[i]
--                 if v == v_frame then
--                     rulecache = outlines
--                 elseif v == v_background then
--                     rulecache = backgrounds
--                 elseif v == v_empty then
--                     showchar = false
--                 elseif v == v_none then
--                     color = nil
--                 else
--                     color = v
--                 end
--             end
--         end
--         local gray  = color and { "startcolor", color } or nil
--         local black = gray  and { "stopcolor" }         or nil
--         for unicode, character in next, characters do
--             local width  = character.width  or 0
--             local height = character.height or 0
--             local depth  = character.depth  or 0
--             local rule   = rulecache[height][depth][width]
--             if showchar then
--                 local commands = character.commands
--                 if commands then
--                     if gray then
--                         character.commands = prependcommands (
--                             commands, gray, rule, black
--                         )
--                     else
--                         character.commands = prependcommands (
--                             commands, rule
--                         )
--                     end
--                 else
--                     local char = charcommand[unicode]
--                     if gray then
--                         character.commands = {
--                             gray, rule, black, char
--                         }
--                      else
--                         character.commands = {
--                             rule, char
--                         }
--                     end
--                 end
--             else
--                 if gray then
--                     character.commands = {
--                         gray, rule, black
--                     }
--                 else
--                     character.commands = {
--                         rule
--                     }
--                 end
--             end
--         end
--     end
-- end

local function initialize(tfmdata,key,value)
    if value then
        local vfspecials  = fonts.helpers.vfspecials
        local vfcommands  = fonts.helpers.commands
     -- local backgrounds = vfspecials.backgrounds
     -- local outlines    = vfspecials.outlines
        local characters  = tfmdata.characters
        local rule        = { "frame", true, true, true, false, false, false, false, "palegray" }
        local showchar    = true
        if type(value) == "string" then
            value = settings_to_array(value)
            for i=1,#value do
                local v = value[i]
                if v == v_frame then
                    rule[6] = true
                elseif v == v_background then
                    rule[6] = false
                elseif v == v_empty then
                    showchar = false
                elseif v == v_none then
                    rule[9] = false
                else
                    local thickness = string.todimen(v)
                    if thickness and thickness > 0 then
                        rule[5] = thickness
                    else
                        rule[9] = v
                    end
                end
            end
        end
        if not showchar then
            rule = { rule }
        end
        for unicode, character in next, characters do
            if characters == 32 then
                -- maybe skip all spacing
            elseif showchar then
                local commands = character.commands
                if commands then
                    character.commands = prependcommands ( commands, rule )
                else
                    character.commands = { rule, charcommand[unicode] }
                end
            else
                character.commands = rule
            end
        end
    end
end

local specification = {
    name        = "boundingbox",
    description = "show boundingbox",
    manipulators = {
        base = initialize,
        node = initialize,
    }
}

registerotffeature(specification)
registerafmfeature(specification)

local function initialize(tfmdata,key,value)
    if value then
        local rawdata       = tfmdata.shared.rawdata
        local rawresources  = rawdata and rawdata.resources
        local mathconstants = rawresources.mathconstants
        if mathconstants then
            local vfspecials  = fonts.helpers.vfspecials
            local vfcommands  = fonts.helpers.commands
            local backgrounds = vfspecials.backgrounds
         -- local outlines    = vfspecials.outlines
            local characters  = tfmdata.characters
            local rulecache   = backgrounds
            local push        = vfcommands.push
            local pop         = vfcommands.pop
            local black       = { "stopcolor" }
            local itcolor     = { "startcolor", "trace:0" } -- s / dd (transparent)
            local brcolor     = { "startcolor", "trace:1" } -- r / dr
            local trcolor     = { "startcolor", "trace:2" } -- g / dg
            local blcolor     = { "startcolor", "trace:3" } -- b / db
            local tlcolor     = { "startcolor", "trace:4" } -- y / dy
            for unicode, character in next, characters do
                local mathkerns = character.mathkerns
                local italic    = character.vitalic or character.italic

if italic ~= italic then
    -- 8427 in pagella suddenly gets a "nan" assigned ... can this be a lua bug
    -- test file : staircase-001.tex
    italic = 0
end

                if mathkerns or (italic and italic ~= 0) then
                    local width  = character.width  or 0
                    local height = character.height or 0
                    local depth  = character.depth  or 0
                    local list   = { }
                    local count  = 0
                    if italic and italic ~= 0 then
                        count = count + 1 list[count] = itcolor
                        count = count + 1 list[count] = push
                        count = count + 1 list[count] = { "offset", width + (italic < 0 and -italic or 0), 0 }
                        count = count + 1 list[count] = rulecache[height][depth][italic < 0 and -italic or italic]
                        count = count + 1 list[count] = pop
                        count = count + 1 list[count] = black
                    end
                    if mathkerns then
                        local br = mathkerns.bottomright
                        local tr = mathkerns.topright
                        local bl = mathkerns.bottomleft
                        local tl = mathkerns.topleft
                        if br then
                            local done = false
                            for i=1,#br do
                                local l = br[i]
                                local h = l.height or 0
                                local k = l.kern or 0
                                if k ~= 0 then
                                    if h == 0 then
                                        h = height + depth -- todo max
                                    end
                                    if not done then
                                        count = count + 1 list[count] = brcolor
                                        done  = true
                                    end
                                    count = count + 1 list[count] = push
                                    count = count + 1 list[count] = { "offset", width + (k < 0 and k or 0), - depth }
                                    count = count + 1 list[count] = rulecache[h][0][k < 0 and -k or k]
                                    count = count + 1 list[count] = pop
                                end
                            end
                            if done then
                                count = count + 1 list[count] = black
                            end
                        end
                        if tr then
                            local done = false
                            for i=1,#tr do
                                local l = tr[i]
                                local h = l.height or 0
                                local k = l.kern or 0
                                if k ~= 0 then
                                    if h == 0 then
                                        h = height + depth -- todo max
                                    end
                                    if not done then
                                        count = count + 1 list[count] = trcolor
                                        done  = true
                                    end
                                    count = count + 1 list[count] = push
                                    count = count + 1 list[count] = { "offset", width + (k < 0 and k or 0), height - h }
                                    count = count + 1 list[count] = rulecache[h][0][k < 0 and k or k]
                                    count = count + 1 list[count] = pop
                                end
                            end
                            if done then
                                count = count + 1 list[count] = black
                            end
                        end
                        if bl then
                            local done = false
                            for i=1,#bl do
                                local l = bl[i]
                                local h = l.height or 0
                                local k = l.kern or 0
                                if k ~= 0 then
                                    if h == 0 then
                                        h = height + depth -- todo max
                                    end
                                    if not done then
                                        count = count + 1 list[count] = blcolor
                                        done  = true
                                    end
                                    count = count + 1 list[count] = push
                                    count = count + 1 list[count] = { "offset", (k < 0 and k or 0), -depth }
                                    count = count + 1 list[count] = rulecache[h][0][abs(k)]
                                    count = count + 1 list[count] = pop
                                end
                            end
                            if done then
                                count = count + 1 list[count] = black
                            end
                        end
                        if tl then
                            local done = false
                            for i=1,#tl do
                                local l = tl[i]
                                local h = l.height or 0
                                local k = l.kern or 0
                                if k ~= 0 then
                                    if h == 0 then
                                        h = height + depth -- todo max
                                    end
                                    if not done then
                                        count = count + 1 list[count] = tlcolor
                                        done  = true
                                    end
                                    count = count + 1 list[count] = push
                                    count = count + 1 list[count] = { "offset", (k < 0 and k or 0), height - h }
                                    count = count + 1 list[count] = rulecache[h][0][abs(k)]
                                    count = count + 1 list[count] = pop
                                end
                            end
                            if done then
                                count = count + 1 list[count] = black
                            end
                        end
                    end
                    if count > 0 then
                        local commands = character.commands
                        if commands then
                            character.commands = appendcommandtable(commands,list)
                        else
                            list[#list+1] = charcommand[unicode]
                            character.commands = list
                        end
                    end
                end
            end
        end
    end
end

local specification = {
    name         = "staircase",
    description  = "show staircase kerns",
--  position     = 1,
    manipulators = {
        base = initialize,
        node = initialize,
    }
}

registerotffeature(specification)
registerafmfeature(specification)
