From b2276ae7a04a9f9c35403e508670049d8c3e4b3e Mon Sep 17 00:00:00 2001
From: Context Git Mirror Bot <phg42.2a@gmail.com>
Date: Mon, 20 Jun 2016 23:10:11 +0200
Subject: 2016-06-20 22:19:00

---
 tex/context/base/context-version.pdf               | Bin 4249 -> 4250 bytes
 tex/context/base/mkiv/cont-new.mkiv                |   2 +-
 tex/context/base/mkiv/context.mkiv                 |   2 +-
 tex/context/base/mkiv/font-cft.lua                 | 543 +++++++++++++++++++++
 tex/context/base/mkiv/font-chk.lua                 |   2 +-
 tex/context/base/mkiv/font-con.lua                 | 139 ++----
 tex/context/base/mkiv/font-ctx.lua                 |  37 +-
 tex/context/base/mkiv/font-def.lua                 |   5 +-
 tex/context/base/mkiv/font-lib.mkvi                |   1 +
 tex/context/base/mkiv/font-tra.mkiv                |  12 +
 tex/context/base/mkiv/l-table.lua                  |  16 +-
 tex/context/base/mkiv/page-mix.lua                 |  69 +--
 tex/context/base/mkiv/status-files.pdf             | Bin 9210 -> 9084 bytes
 tex/context/base/mkiv/status-lua.pdf               | Bin 269096 -> 268913 bytes
 tex/context/interface/mkiv/i-context.pdf           | Bin 821347 -> 821218 bytes
 tex/context/interface/mkiv/i-readme.pdf            | Bin 60789 -> 60787 bytes
 tex/generic/context/luatex/luatex-fonts-merged.lua | 131 ++---
 17 files changed, 716 insertions(+), 243 deletions(-)
 create mode 100644 tex/context/base/mkiv/font-cft.lua

(limited to 'tex')

diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index 4f5952d9b..91591b038 100644
Binary files a/tex/context/base/context-version.pdf and b/tex/context/base/context-version.pdf differ
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 852e0fddd..89a6d4c7f 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -11,7 +11,7 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
-\newcontextversion{2016.06.19 13:29}
+\newcontextversion{2016.06.20 22:14}
 
 %D This file is loaded at runtime, thereby providing an excellent place for
 %D hacks, patches, extensions and new features.
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index c441cf7ad..dd869f035 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -39,7 +39,7 @@
 %D up and the dependencies are more consistent.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2016.06.19 13:29}
+\edef\contextversion{2016.06.20 22:14}
 \edef\contextkind   {beta}
 
 %D For those who want to use this:
diff --git a/tex/context/base/mkiv/font-cft.lua b/tex/context/base/mkiv/font-cft.lua
new file mode 100644
index 000000000..63c056022
--- /dev/null
+++ b/tex/context/base/mkiv/font-cft.lua
@@ -0,0 +1,543 @@
+if not modules then modules = { } end modules ['font-cft'] = {
+    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"
+}
+
+-- context font tables
+
+-- todo: extra:
+--
+-- extra_space       => space.extra
+-- space             => space.width
+-- space_stretch     => space.stretch
+-- space_shrink      => space.shrink
+
+-- We do keep the x-height, extra_space, space_shrink and space_stretch
+-- around as these are low level official names.
+
+local type = type
+
+local fonts  = fonts or { }
+local tables = fonts.tables or { }
+fonts.tables = tables
+
+local data   = utilities.storage.allocate()
+tables.data  = data
+
+do
+
+    local t_units     = "<units>"
+    local t_unicode   = "<unicode>"
+    local t_unispec   = "<unispec>"      -- t_unicode | { t_unicode }
+    local t_index     = "<index>"
+    local t_cardinal  = "<cardinal>"
+    local t_integer   = "<integer>"
+    local t_float     = "<float>"
+    local t_boolean   = "<boolean>"
+    local t_string    = "<string>"
+    local t_array     = "<array>"
+    local t_hash      = "<hash>"
+    local t_scaled    = "<scaled>"
+    local t_keyword   = "<keyword>"
+    local t_scale     = "<scale>"       -- 1000 based tex scale
+    local t_value     = "<value>"       -- number, string, boolean
+    local t_function  = "<function>"
+
+    data.types = {
+        ["units"]     = "<units>",
+        ["unicode"]   = "<unicode>",
+        ["unispec"]   = "<unispec>" ,     -- t_unicode | { t_unicode }
+        ["index"]     = "<index>",
+        ["cardinal"]  = "<cardinal>",
+        ["integer"]   = "<integer>",
+        ["float"]     = "<float>",
+        ["boolean"]   = "<boolean>",
+        ["string"]    = "<string>",
+        ["array"]     = "<array>",
+        ["hash"]      = "<hash>",
+        ["scaled"]    = "<scaled>",
+        ["keyword"]   = "<keyword>",
+        ["scale"]     = "<scale>",       -- 1000 based tex scale
+        ["value"]     = "<value>",       -- number, string, boolean
+        ["function"]  = "<function>",
+    }
+
+    local boundingbox = {
+        t_units,
+        t_units,
+        t_units,
+        t_units
+    }
+
+    local mathvariants = {
+        t_array
+    }
+
+    local mathparts = {
+        {
+            advance  = t_units,
+            ["end"]  = t_units,
+            extender = t_units,
+            glyph    = t_unicode,
+            start    = t_units,
+        }
+    }
+
+    local mathkerns = {
+        {
+            height = t_units,
+            kern   = t_units,
+        },
+    }
+
+    local mathparts = {
+        {
+            advance  = t_scaled,
+            ["end"]  = t_scaled,
+            extender = t_scaled,
+            glyph    = t_unicode,
+            start    = t_scaled,
+        }
+    }
+
+    local mathkerns = {
+        {
+            height = t_scaled,
+            kern   = t_scaled,
+        },
+    }
+
+    local vfcommands = {
+        { t_keyword, t_value },
+    }
+
+    local description = {
+        width       = t_units,
+        height      = t_units,
+        depth       = t_units,
+        italic      = t_units,
+        index       = t_index,
+        boundingbox = boundingbox,
+        unicode     = t_unispec,
+        math        = {
+            accent    = t_units,
+            hvariants = mathvariants,
+            vvariants = mathvariants,
+            hparts    = mathparts,
+            vparts    = mathparts,
+            kerns     = {
+                bottomright = mathkerns,
+                bottomleft  = mathkerns,
+                topright    = mathkerns,
+                topleft     = mathkerns,
+            }
+        },
+    }
+
+    local character = {
+        width            = t_scaled,
+        height           = t_scaled,
+        depth            = t_scaled,
+        italic           = t_scaled,
+        index            = t_index,
+        expansion_factor = t_scaled,
+        left_protruding  = t_scaled,
+        right_protruding = t_scaled,
+        tounicode        = t_string,
+        unicode          = t_unispec,
+        commands         = vfcommands,
+        accent           = t_scaled,
+        hvariants        = mathvariants,
+        vvariants        = mathvariants,
+        hparts           = math_parts,
+        vparts           = math_parts,
+        kerns            = {
+            bottomright = math_kerns,
+            bottomleft  = math_kerns,
+            topright    = math_kerns,
+            topleft     = math_kerns,
+        },
+        ligatures        = t_hash,
+        kerns            = t_hash,
+        next             = t_array,
+    }
+
+    data.original = {
+        cache_uuid     =  t_string,
+        cache_version  =  t_float,
+        compacted      =  t_boolean,
+        creator        =  t_string,
+        descriptions   =  { description },
+        format         =  t_string,
+        goodies        =  t_hash,
+        metadata       =  {
+            ascender      = t_units,
+            averagewidth  = t_units,
+            capheight     = t_units,
+            descender     = t_units,
+            family        = t_string,
+            familyname    = t_string,
+            fontname      = t_string,
+            fullname      = t_string,
+            italicangle   = t_float,
+            monospaced    = t_boolean,
+            panoseweight  = t_string,
+            panosewidth   = t_string,
+            pfmweight     = t_units,
+            pfmwidth      = t_units,
+            subfamily     = t_string,
+            subfamilyname = t_string,
+            subfontindex  = t_index,
+            units         = t_cardinal,
+            version       = t_string,
+            weight        = t_string,
+            width         = t_string,
+            xheight       = t_units,
+        },
+        private        = t_unicode,
+        properties     = {
+            hascolor      = t_boolean,
+            hasitalics    = t_boolean,
+            hasspacekerns = t_boolean,
+        },
+        resources      = {
+            duplicates    = t_hash,
+            features      = {
+                gpos = t_hash,
+                gsub = t_hash,
+            },
+            filename      = t_string,
+            markclasses   = t_hash,
+            marks         = t_hash,
+            marksets      = t_hash,
+            mathconstants = t_hash,
+            private       = t_cardinal,
+            sequences     = t_array,
+         -- unicodes      = t_hash,
+            version       = t_string,
+        },
+        size         = t_cardinal,
+     -- tables       = t_array,
+        tableversion = t_float,
+        time         = t_cardinal,
+    }
+
+    data.scaled = {
+        properties = {
+            encodingbytes    = t_cardinal,
+            embedding        = t_cardinal, -- ?
+            cidinfo          = t_hash,
+            format           = t_string,
+            fontname         = t_string,
+            fullname         = t_string,
+            filename         = t_string,
+            psname           = t_string,
+            name             = t_string,
+            virtualized      = t_boolean,
+            hasitalics       = t_boolean,
+            autoitalicamount = t_float,
+            nostackmath      = t_boolean,
+            noglyphnames     = t_boolean,
+            mode             = t_string,
+            hasmath          = t_boolean,
+            mathitalics      = t_boolean,
+            textitalics      = t_boolean,
+            finalized        = t_boolean,
+        },
+        parameters = {
+            mathsize               = t_cardinal,
+            scriptpercentage       = t_float,
+            scriptscriptpercentage = t_float,
+            units                  = t_cardinal,
+            designsize             = t_scaled,
+            expansion              = {
+                stretch = t_scale,
+                shrink  = t_scale,
+                step    = t_scale,
+                auto    = t_boolean,
+            },
+            protrusion             = {
+                auto = t_boolean,
+            },
+            slantfactor   = t_float,
+            extendfactor  = t_float,
+            factor        = t_float,
+            hfactor       = t_float,
+            vfactor       = t_float,
+            size          = t_scaled,
+            units         = t_scaled,
+            scaledpoints  = t_scaled,
+            slantperpoint = t_scaled,
+            xheight       = t_scaled,
+            quad          = t_scaled,
+            ascender      = t_scaled,
+            descender     = t_scaled,
+            spacing       = {
+                width   = t_scaled,
+                stretch = t_scaled,
+                shrink  = t_scaled,
+                extra   = t_scaled,
+            },
+         -- synonyms      = {
+         --     space         = "spacing.width",
+         --     spacestretch  = "spacing.stretch",
+         --     spaceshrink   = "spacing.shrink",
+         --     extraspace    = "spacing.extra",
+         --     x_height      = "xheight",
+         --     space_stretch = "spacing.stretch",
+         --     space_shrink  = "spacing.shrink",
+         --     extra_space   = "spacing.extra",
+         --     em            = "quad",
+         --     ex            = "xheight",
+         --     slant         = "slantperpoint",
+         -- },
+        },
+        descriptions   =  { description },
+        characters     =  { character },
+    }
+
+    data.goodies = {
+        -- preamble
+        name      = t_string,
+        version   = t_string,
+        comment   = t_string,
+        author    = t_string,
+        copyright = t_string,
+        --
+        remapping = {
+            tounicode = t_boolean,
+            unicodes = {
+                [t_string] = t_index,
+            },
+        },
+        mathematics = {
+            mapfiles = {
+                t_string,
+            },
+            virtuals = {
+                [t_string] = {
+                    {
+                        name       = t_string,
+                        features   = t_hash,
+                        main       = t_boolean,
+                        extension  = t_boolean,
+                        vector     = t_string,
+                        skewchar   = t_unicode,
+                        parameters = t_boolean,
+                    },
+                },
+            },
+            italics = {
+                [t_string] = {
+                    defaultfactor = t_float,
+                    disableengine = t_boolean,
+                    corrections   = {
+                        [t_unicode] = t_float,
+                    }
+                },
+            },
+            kerns = {
+                [t_unicode] = {
+                    bottomright = math_kerns,
+                    topright    = math_kerns,
+                    bottomleft  = math_kerns,
+                    topleft     = math_kerns,
+                },
+            },
+            alternates = {
+                [t_string] = {
+                    feature = t_hash,
+                    value   = t_float,
+                    comment = t_string,
+                },
+            },
+            variables = {
+                [t_string] = t_value,
+            },
+            parameters = {
+                [t_string] = t_value,
+                [t_string] = t_function,
+            },
+            dimensions = {
+                [t_string] = {
+                    [t_unicode] = {
+                        width   = t_units,
+                        height  = t_units,
+                        depth   = t_units,
+                        xoffset = t_units,
+                        yoffset = t_units,
+                    },
+                },
+            },
+        },
+        filenames = {
+            [t_string] = {
+                t_string,
+            },
+        },
+        compositions = {
+            [t_string] = {
+                dy          = t_unit,
+                dx          = t_unit,
+                [t_unicode] = {
+                    dy = t_unit
+                },
+                [t_unicode] = {
+                    anchors = {
+                        top = {
+                            x = t_unit,
+                            y = t_unit,
+                        },
+                        bottom = {
+                            x = t_unit,
+                            y = t_unit,
+                        },
+                    },
+                },
+            },
+        },
+        postprocessors = {
+            [t_string] = t_function,
+        },
+        designsizes = {
+            [t_string] = {
+                [t_string] = t_string,
+                default    = t_string
+            },
+        },
+        featuresets = {
+            [t_string] = {
+                t_string,
+                [t_keyword] = t_value
+            },
+        },
+        solutions = {
+            experimental = {
+                less = { t_string },
+                more = { t_string },
+            },
+        },
+        stylistics = {
+            [t_string] = t_string,
+            [t_string] = t_string,
+        },
+        colorschemes = {
+            default = {
+                [1] = { t_string },
+            }
+        },
+        files = {
+            name = t_string,
+            list = {
+                [t_string] = {
+                    name   = t_string,
+                    weight = t_string,
+                    style  = t_string,
+                    width  = t_string,
+                },
+            },
+        },
+        typefaces = {
+            [t_string] = {
+                shortcut     = t_string,
+                shape        = t_string,
+                fontname     = t_string,
+                normalweight = t_string,
+                boldweight   = t_string,
+                width        = t_string,
+                size         = t_string,
+                features     = t_string,
+            },
+        },
+    }
+
+end
+
+-- compatibility (for now)
+
+if fonts.constructors then
+    fonts.constructors.keys = data.scaled
+end
+
+-- handy helpers
+
+local report = logs.reporter("fonts")
+
+function tables.savefont(specification)
+    local method   = specification.method
+    local filename = specification.filename
+    local fontname = specification.fontname
+    if not method or method ~= "original" then
+        method = "scaled"
+    end
+    if not filename or filename == "" then
+        filename = "temp-font-" .. method .. ".lua"
+    else
+        filename = file.addsuffix(filename,"lua")
+    end
+    if not fontname or fontname == "" then
+        fontname = true
+    end
+    if fontname == true then
+        report("saving current font in %a",filename)
+    elseif tonumber(fontname) then
+        report("saving font id %a in %a",fontname,filename)
+        fontname = tonumber(fontname)
+    else
+        report("saving font %a in %a",fontname,filename)
+        tfmdata = fonts.definers.define {
+            name = fontname
+        }
+    end
+    if tfmdata then
+        tfmdata = fonts.hashes.identifiers[tfmdata]
+    end
+    if not tfmdata then
+        -- bad news
+    elseif method == "original" then
+        tfmdata = tfmdata.shared and tfmdata.shared.rawdata
+    else
+        tfmdata = {
+            characters    = tfmdata.characters,
+            parameters    = tfmdata.parameters,
+            properties    = tfmdata.properties,
+            specification = tfmdata.specification,
+        }
+    end
+    if tfmdata then
+        table.save(filename,tfmdata)
+    else
+     -- os.remove(filename)
+        report("saving font failed")
+    end
+end
+
+function tables.saveoriginal(filename,specification)
+    local tfmdata = get(specification)
+    if tfmdata then
+        local rawdata = tfmdata.shared and tfmdata.shared.rawdata
+        if rawdata then
+            table.save(filename,rawdata)
+        end
+    end
+end
+
+if context then
+
+    interfaces.implement {
+        name      = "savefont",
+        actions   = tables.savefont,
+        arguments = {
+            {
+                { "filename" },
+                { "fontname" },
+                { "method" },
+            }
+        },
+    }
+
+end
+
diff --git a/tex/context/base/mkiv/font-chk.lua b/tex/context/base/mkiv/font-chk.lua
index aaada574e..179a9b80e 100644
--- a/tex/context/base/mkiv/font-chk.lua
+++ b/tex/context/base/mkiv/font-chk.lua
@@ -428,7 +428,7 @@ local dummyzero = {
     commands = { { "special", "" } },
 }
 
-local function adddummysymbols(tfmdata,...)
+local function adddummysymbols(tfmdata)
     local characters = tfmdata.characters
     if not characters[0] then
         characters[0] = dummyzero
diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua
index 1a0daff63..6139b8911 100644
--- a/tex/context/base/mkiv/font-con.lua
+++ b/tex/context/base/mkiv/font-con.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['font-con'] = {
 -- some names of table entries will be changed (no _)
 
 local next, tostring, rawget = next, tostring, rawget
-local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub
+local format, match, lower, gsub, find = string.format, string.match, string.lower, string.gsub, string.find
 local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy
 local derivetable = table.derive
 
@@ -46,102 +46,6 @@ constructors.privateoffset   = 0xF0000 -- 0x10FFFF
 
 constructors.cacheintex      = true -- so we see the original table in fonts.font
 
--- Some experimental helpers (handy for tracing):
---
--- todo: extra:
---
--- extra_space       => space.extra
--- space             => space.width
--- space_stretch     => space.stretch
--- space_shrink      => space.shrink
-
--- We do keep the x-height, extra_space, space_shrink and space_stretch
--- around as these are low level official names.
-
-constructors.keys = {
-    properties = {
-        encodingbytes          = "number",
-        embedding              = "number",
-        cidinfo                = { },
-        format                 = "string",
-        fontname               = "string",
-        fullname               = "string",
-        filename               = "filename",
-        psname                 = "string",
-        name                   = "string",
-        virtualized            = "boolean",
-        hasitalics             = "boolean",
-        autoitalicamount       = "basepoints",
-        nostackmath            = "boolean",
-        noglyphnames           = "boolean",
-        mode                   = "string",
-        hasmath                = "boolean",
-        mathitalics            = "boolean",
-        textitalics            = "boolean",
-        finalized              = "boolean",
-    },
-    parameters = {
-        mathsize               = "number",
-        scriptpercentage       = "float",
-        scriptscriptpercentage = "float",
-        units                  = "cardinal",
-        designsize             = "scaledpoints",
-        expansion              = {
-                                    stretch = "integerscale", -- might become float
-                                    shrink  = "integerscale", -- might become float
-                                    step    = "integerscale", -- might become float
-                                    auto    = "boolean",
-                                 },
-        protrusion             = {
-                                    auto    = "boolean",
-                                 },
-        slantfactor            = "float",
-        extendfactor           = "float",
-        factor                 = "float",
-        hfactor                = "float",
-        vfactor                = "float",
-        size                   = "scaledpoints",
-        units                  = "scaledpoints",
-        scaledpoints           = "scaledpoints",
-        slantperpoint          = "scaledpoints",
-        spacing                = {
-                                    width   = "scaledpoints",
-                                    stretch = "scaledpoints",
-                                    shrink  = "scaledpoints",
-                                    extra   = "scaledpoints",
-                                 },
-        xheight                = "scaledpoints",
-        quad                   = "scaledpoints",
-        ascender               = "scaledpoints",
-        descender              = "scaledpoints",
-        synonyms               = {
-                                    space         = "spacing.width",
-                                    spacestretch  = "spacing.stretch",
-                                    spaceshrink   = "spacing.shrink",
-                                    extraspace    = "spacing.extra",
-                                    x_height      = "xheight",
-                                    space_stretch = "spacing.stretch",
-                                    space_shrink  = "spacing.shrink",
-                                    extra_space   = "spacing.extra",
-                                    em            = "quad",
-                                    ex            = "xheight",
-                                    slant         = "slantperpoint",
-                                  },
-    },
-    description = {
-        width                  = "basepoints",
-        height                 = "basepoints",
-        depth                  = "basepoints",
-        boundingbox            = { },
-    },
-    character = {
-        width                  = "scaledpoints",
-        height                 = "scaledpoints",
-        depth                  = "scaledpoints",
-        italic                 = "scaledpoints",
-    },
-}
-
 -- This might become an interface:
 
 local designsizes           = allocate()
@@ -351,6 +255,25 @@ local function mathkerns(v,vdelta)
     return k
 end
 
+local psfake = 0
+
+local function fixedpsname(psname,fallback)
+    local usedname = psname
+    if not psname or psname == "" then
+        -- filenames can be a mess so we do a drastic cleanup
+        psname   = fallback
+        usedname = gsub(psname,"[^a-zA-Z0-9]+","-")
+    elseif find(psname," ") then
+        -- we assume that the name is sane enough (we might sanitize completely some day)
+        usedname = gsub(psname,"[%s]+","-")
+    end
+    if not psname or psname == "" then
+        psfake = psfake + 1
+        psname = "fakename-" .. psfake
+    end
+    return usedname, psname ~= usedname
+end
+
 function constructors.scale(tfmdata,specification)
     local target         = { } -- the new table
     --
@@ -453,23 +376,22 @@ function constructors.scale(tfmdata,specification)
     target.format        = properties.format
     target.cache         = constructors.cacheintex and "yes" or "renew"
     --
-    local fontname = properties.fontname or tfmdata.fontname -- for the moment we fall back on
-    local fullname = properties.fullname or tfmdata.fullname -- names in the tfmdata although
-    local filename = properties.filename or tfmdata.filename -- that is not the right place to
-    local psname   = properties.psname   or tfmdata.psname   -- pass them
+    local fontname = properties.fontname or tfmdata.fontname
+    local fullname = properties.fullname or tfmdata.fullname
+    local filename = properties.filename or tfmdata.filename
+    local psname   = properties.psname   or tfmdata.psname
     local name     = properties.name     or tfmdata.name
     --
-    if not psname or psname == "" then
-     -- name used in pdf file as well as for selecting subfont in ttc/dfont
-        psname = fontname or (fullname and fonts.names.cleanname(fullname))
-    end
+    -- the psname used in pdf file as well as for selecting subfont in ttc
+    --
+    local psname, psfixed = fixedpsname(psname,fontname or fullname or file.nameonly(filename))
+    --
     target.fontname = fontname
     target.fullname = fullname
     target.filename = filename
     target.psname   = psname
     target.name     = name
     --
-    --
     properties.fontname = fontname
     properties.fullname = fullname
     properties.filename = filename
@@ -602,8 +524,9 @@ function constructors.scale(tfmdata,specification)
     -- end of context specific trickery
     --
     if trace_defining then
-        report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
-            name,fullname,filename,hdelta,vdelta,hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
+        report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a",
+            name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta,
+            hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
     end
     --
     constructors.beforecopyingcharacters(target,tfmdata)
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index 4a4808316..6b9434d7b 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -1387,7 +1387,7 @@ function constructors.calculatescale(tfmdata,scaledpoints,relativeid,specificati
     local scaledpoints, delta = calculatescale(tfmdata,scaledpoints)
  -- if enable_auto_r_scale and relativeid then -- for the moment this is rather context specific (we need to hash rscale then)
  --     local relativedata = fontdata[relativeid]
- --     local rfmdata = relativedata and relativedata.unscaled and relativedata.unscaled
+ --     local rfmdata = relativedata and relativedata.unscaled and relativedata.unscaled -- just use metadata instead
  --     local id_x_height = rfmdata and rfmdata.parameters and rfmdata.parameters.x_height
  --     local tf_x_height = tfmdata and tfmdata.parameters and tfmdata.parameters.x_height
  --     if id_x_height and tf_x_height then
@@ -2519,3 +2519,38 @@ function helpers.getcoloredglyphs(tfmdata)
     table.sort(collected)
     return collected
 end
+
+-- for the font manual
+
+local trace_files = false
+
+trackers.register("fonts.files",function(v) trace_files = v end)
+
+statistics.register("used fonts",function()
+    if trace_files then
+        local files = { }
+        local list  = { }
+        for id, tfmdata in sortedhash(fontdata) do
+            local filename = tfmdata.properties.filename
+            local filedata = files[filename]
+            if filedata then
+                filedata.instances = filedata.instances + 1
+            else
+                local rawdata  = tfmdata.shared and tfmdata.shared.rawdata
+                local metadata = rawdata and rawdata.metadata
+                files[filename] = {
+                    instances = 1,
+                    filename  = filename,
+                    version   = metadata and metadata.version,
+                    size      = rawdata and rawdata.size,
+                }
+            end
+        end
+        for k, v in sortedhash(files) do
+            list[#list+1] = v
+        end
+        local filename = file.nameonly(environment.jobname) .. "-usedfonts.lua"
+        table.save(filename,list)
+        return format("log saved in '%s'",filename)
+    end
+end)
diff --git a/tex/context/base/mkiv/font-def.lua b/tex/context/base/mkiv/font-def.lua
index add42ee38..88d614566 100644
--- a/tex/context/base/mkiv/font-def.lua
+++ b/tex/context/base/mkiv/font-def.lua
@@ -8,10 +8,11 @@ if not modules then modules = { } end modules ['font-def'] = {
 
 -- We can overload some of the definers.functions so we don't local them.
 
-local format, gmatch, match, find, lower, gsub = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub
+local lower, gsub = string.lower, string.gsub
 local tostring, next = tostring, next
 local lpegmatch = lpeg.match
 local suffixonly, removesuffix = file.suffix, file.removesuffix
+local formatters = string.formatters
 
 local allocate = utilities.storage.allocate
 
@@ -264,7 +265,7 @@ function definers.applypostprocessors(tfmdata)
             if type(extrahash) == "string" and extrahash ~= "" then
                 -- e.g. a reencoding needs this
                 extrahash = gsub(lower(extrahash),"[^a-z]","-")
-                properties.fullname = format("%s-%s",properties.fullname,extrahash)
+                properties.fullname = formatters["%s-%s"](properties.fullname,extrahash)
             end
         end
     end
diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi
index fe9198ec7..f6bb734fd 100644
--- a/tex/context/base/mkiv/font-lib.mkvi
+++ b/tex/context/base/mkiv/font-lib.mkvi
@@ -18,6 +18,7 @@
 \registerctxluafile{font-ini}{1.001}
 \registerctxluafile{font-log}{1.001}
 \registerctxluafile{font-con}{1.001}
+\registerctxluafile{font-cft}{1.001}
 \registerctxluafile{font-enc}{1.001}
 \registerctxluafile{font-agl}{1.001} % if needed we can comment this and delay loading
 \registerctxluafile{font-cid}{1.001} % cid maps
diff --git a/tex/context/base/mkiv/font-tra.mkiv b/tex/context/base/mkiv/font-tra.mkiv
index f5290d614..38b172ba6 100644
--- a/tex/context/base/mkiv/font-tra.mkiv
+++ b/tex/context/base/mkiv/font-tra.mkiv
@@ -287,4 +287,16 @@
    \stopotfsample
    \endgroup}
 
+% new
+
+\unexpanded\def\savefont[#1]% not yet in i-*.xml
+  {\begingroup
+   \getdummyparameters[#1]%
+   \clf_savefont {
+      filename {\dummyparameter\c!file}
+      fontname {\dummyparameter\c!name}
+      method   {\dummyparameter\c!method}
+   }%
+   \endgroup}
+
 \protect \endinput
diff --git a/tex/context/base/mkiv/l-table.lua b/tex/context/base/mkiv/l-table.lua
index 552097e1c..d1e05928f 100644
--- a/tex/context/base/mkiv/l-table.lua
+++ b/tex/context/base/mkiv/l-table.lua
@@ -673,6 +673,8 @@ local function do_serialize(root,name,depth,level,indexed)
                     else
                         handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) -- %.99g
                     end
+                elseif tk ~= "string" then
+                    -- ignore
                 elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
                     if hexify then
                         handle(format("%s %s=0x%X,",depth,k,v))
@@ -695,6 +697,8 @@ local function do_serialize(root,name,depth,level,indexed)
                     end
                 elseif tk == "boolean" then
                     handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
+                elseif tk ~= "string" then
+                    -- ignore
                 elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
                     handle(format("%s %s=%q,",depth,k,v))
                 else
@@ -710,6 +714,8 @@ local function do_serialize(root,name,depth,level,indexed)
                         end
                     elseif tk == "boolean" then
                         handle(format("%s [%s]={},",depth,k and "true" or "false"))
+                    elseif tk ~= "string" then
+                        -- ignore
                     elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
                         handle(format("%s %s={},",depth,k))
                     else
@@ -726,6 +732,8 @@ local function do_serialize(root,name,depth,level,indexed)
                             end
                         elseif tk == "boolean" then
                             handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", ")))
+                        elseif tk ~= "string" then
+                            -- ignore
                         elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
                             handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
                         else
@@ -746,6 +754,8 @@ local function do_serialize(root,name,depth,level,indexed)
                     end
                 elseif tk == "boolean" then
                     handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false"))
+                elseif tk ~= "string" then
+                    -- ignore
                 elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
                     handle(format("%s %s=%s,",depth,k,v and "true" or "false"))
                 else
@@ -763,6 +773,8 @@ local function do_serialize(root,name,depth,level,indexed)
                         end
                     elseif tk == "boolean" then
                         handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
+                    elseif tk ~= "string" then
+                        -- ignore
                     elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
                         handle(format("%s %s=load(%q),",depth,k,f))
                     else
@@ -778,6 +790,8 @@ local function do_serialize(root,name,depth,level,indexed)
                     end
                 elseif tk == "boolean" then
                     handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v)))
+                elseif tk ~= "string" then
+                    -- ignore
                 elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
                     handle(format("%s %s=%q,",depth,k,tostring(v)))
                 else
@@ -1165,7 +1179,7 @@ function table.has_one_entry(t)
     return t and next(t,next(t)) == nil
 end
 
--- new
+-- new (rather basic, not indexed and nested)
 
 function table.loweredkeys(t) -- maybe utf
     local l = { }
diff --git a/tex/context/base/mkiv/page-mix.lua b/tex/context/base/mkiv/page-mix.lua
index 1154a24f5..bafd6d234 100644
--- a/tex/context/base/mkiv/page-mix.lua
+++ b/tex/context/base/mkiv/page-mix.lua
@@ -62,6 +62,8 @@ local getbox              = nuts.getbox
 local getskip             = nuts.getskip
 local getattribute        = nuts.getattribute
 
+local texgetcount         = tex.getcount
+
 local theprop             = nuts.theprop
 
 local nodepool            = nuts.pool
@@ -106,9 +108,7 @@ local function collectinserts(result,nxt,nxtid)
     local inserts, currentskips, nextskips, inserttotal = { }, 0, 0, 0
     while nxt do
         if nxtid == insert_code then
-            inserttotal = inserttotal
-                        + getfield(nxt,"height")
-                        + getfield(nxt,"depth")
+            inserttotal = inserttotal + getfield(nxt,"height") -- height includes depth
             local s = getsubtype(nxt)
             local c = inserts[s]
             if trace_detail then
@@ -449,8 +449,8 @@ local function preparesplit(specification) -- a rather large function
             end
         end
         if trace_detail then
-            report_state("%-7s > column %s, delta %p, threshold %p, advance %p, total %p, target %p => %a (height %p, depth %p, skip %p)",
-                where,curcol,delta,threshold,advance,total,target,state,skipped,height,depth,skip)
+            report_state("%-8s > column %s, delta %p, threshold %p, advance %p, total %p, target %p => %a (height %p, depth %p, skip %p)",
+                where,curcol,delta,threshold,advance,total,target,state,height,depth,skip)
         end
         return state, skipped
     end
@@ -474,9 +474,9 @@ local function preparesplit(specification) -- a rather large function
         if advance ~= 0 then
             local state, skipped = checked(advance,"glue")
             if trace_state then
-                report_state("%-7s > column %s, state %a, advance %p, height %p","glue",column,state,advance,height)
+                report_state("%-8s > column %s, state %a, advance %p, height %p","glue",column,state,advance,height)
                 if skipped ~= 0 then
-                    report_state("%-7s > column %s, discarded %p","glue",column,skipped)
+                    report_state("%-8s > column %s, discarded %p","glue",column,skipped)
                 end
             end
             if state == "quit" then
@@ -486,15 +486,15 @@ local function preparesplit(specification) -- a rather large function
             depth  = 0
             if advance < 0 then
                 height = height + advance
-                skip   = 0
+                skip = 0
                 if height < 0 then
                     height = 0
                 end
             else
-                skip   = height > 0 and advance or 0
+                skip = height > 0 and advance or 0
             end
             if trace_state then
-                report_state("%-7s > column %s, height %p, depth %p, skip %p","glue",column,height,depth,skip)
+                report_state("%-8s > column %s, height %p, depth %p, skip %p","glue",column,height,depth,skip)
             end
         else
             -- what else? ignore? treat as valid as usual?
@@ -509,9 +509,9 @@ local function preparesplit(specification) -- a rather large function
         if advance ~= 0 then
             local state, skipped = checked(advance,"kern")
             if trace_state then
-                report_state("%-7s > column %s, state %a, advance %p, height %p, state %a","kern",column,state,advance,height)
+                report_state("%-8s > column %s, state %a, advance %p, height %p, state %a","kern",column,state,advance,height)
                 if skipped ~= 0 then
-                    report_state("%-7s > column %s, discarded %p","kern",column,skipped)
+                    report_state("%-8s > column %s, discarded %p","kern",column,skipped)
                 end
             end
             if state == "quit" then
@@ -521,7 +521,7 @@ local function preparesplit(specification) -- a rather large function
             depth  = 0
             skip   = 0
             if trace_state then
-                report_state("%-7s > column %s, height %p, depth %p, skip %p","kern",column,height,depth,skip)
+                report_state("%-8s > column %s, height %p, depth %p, skip %p","kern",column,height,depth,skip)
             end
         end
     end
@@ -532,9 +532,9 @@ local function preparesplit(specification) -- a rather large function
         if advance ~= 0 then
             local state, skipped = checked(advance,"rule")
             if trace_state then
-                report_state("%-7s > column %s, state %a, rule, advance %p, height %p","rule",column,state,advance,inserttotal,height)
+                report_state("%-8s > column %s, state %a, rule, advance %p, height %p","rule",column,state,advance,inserttotal,height)
                 if skipped ~= 0 then
-                    report_state("%-7s > column %s, discarded %p","rule",column,skipped)
+                    report_state("%-8s > column %s, discarded %p","rule",column,skipped)
                 end
             end
             if state == "quit" then
@@ -579,14 +579,14 @@ local function preparesplit(specification) -- a rather large function
                     if trace_state then
                         report_state("cycle: %s, forced column break, same page",cycle)
                         if skipped ~= 0 then
-                            report_state("%-7s > column %s, discarded %p","penalty",column,skipped)
+                            report_state("%-8s > column %s, discarded %p","penalty",column,skipped)
                         end
                     end
                 else
                     if trace_state then
                         report_state("cycle: %s, forced column break, next page",cycle)
                         if skipped ~= 0 then
-                            report_state("%-7s > column %s, discarded %p","penalty",column,skipped)
+                            report_state("%-8s > column %s, discarded %p","penalty",column,skipped)
                         end
                     end
                     return true
@@ -611,17 +611,18 @@ local function preparesplit(specification) -- a rather large function
         line = line + 1
         local inserts, insertskips, nextskips, inserttotal = nil, 0, 0, 0
         local advance = getfield(current,"height")
+        local more = nxt and (nxtid == insert_code or nxtid == mark_code)
         if trace_state then
-            report_state("%-7s > column %s, content: %s","line",column,listtoutf(getlist(current),true,true))
+            report_state("%-8s > column %s, content: %s","line (1)",column,listtoutf(getlist(current),true,true))
         end
-        if nxt and (nxtid == insert_code or nxtid == mark_code) then
-            nxt, inserts, localskips, insertskips, inserttotal = collectinserts(result,nxt,nxtid)
+        if more then
+            nxt, inserts, insertskips, nextskips, inserttotal = collectinserts(result,nxt,nxtid)
         end
-        local state, skipped = checked(advance+inserttotal+insertskips,"line",lastlocked)
+        local state, skipped = checked(advance+inserttotal+insertskips,more and "line (2)" or "line only",lastlocked)
         if trace_state then
-            report_state("%-7s > column %s, state %a, line %s, advance %p, insert %p, height %p","line",column,state,line,advance,inserttotal,height)
+            report_state("%-8s > column %s, state %a, line %s, advance %p, insert %p, height %p","line (3)",column,state,line,advance,inserttotal,height)
             if skipped ~= 0 then
-                report_state("%-7s > column %s, discarded %p","line",column,skipped)
+                report_state("%-8s > column %s, discarded %p","line (4)",column,skipped)
             end
         end
         if state == "quit" then
@@ -658,7 +659,7 @@ local function preparesplit(specification) -- a rather large function
             appendinserts(result.inserts,inserts)
         end
         if trace_state then
-            report_state("%-7s > column %s, height %p, depth %p, skip %p","line",column,height,depth,skip)
+            report_state("%-8s > column %s, height %p, depth %p, skip %p","line (5)",column,height,depth,skip)
         end
         lastcontent = current
     end
@@ -681,6 +682,7 @@ local function preparesplit(specification) -- a rather large function
         elseif id == rule_code then
             if process_rule(current,nxt) then break end
         else
+            -- skip inserts and such
         end
 
         if backtracked then
@@ -751,12 +753,12 @@ local function finalize(result)
             local h = r.head
             if h then
                 setprev(h)
-if r.back then
-    local k = new_glue(r.back)
-    setlink(k,h)
-    h = k
-    r.head = h
-end
+                if r.back then
+                    local k = new_glue(r.back)
+                    setlink(k,h)
+                    h = k
+                    r.head = h
+                end
                 local t = r.tail
                 if t then
                     setnext(t,nil)
@@ -771,8 +773,11 @@ end
                         local h = new_hlist()
                         t[i] = h
                         setlist(h,getfield(l,"head"))
-                        setfield(h,"height",getfield(l,"height"))
-                        setfield(h,"depth",getfield(l,"depth"))
+                        local ht = getfield(l,"height")
+                        local dp = getfield(l,"depth")
+                        -- here ht is still ht + dp !
+                        setfield(h,"height",ht)
+                        setfield(h,"depth",dp)
                         setfield(l,"head",nil)
                     end
                     setprev(t[1])  -- needs checking
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 08d64337b..c79387699 100644
Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index 4582f1650..e011f4e49 100644
Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ
diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf
index 4a675467a..0e4fab907 100644
Binary files a/tex/context/interface/mkiv/i-context.pdf and b/tex/context/interface/mkiv/i-context.pdf differ
diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf
index d2d76e5ba..3894aae56 100644
Binary files a/tex/context/interface/mkiv/i-readme.pdf and b/tex/context/interface/mkiv/i-readme.pdf differ
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 6c33374c7..9981b1aa6 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
 -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
 -- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date  : 06/19/16 13:29:04
+-- merge date  : 06/20/16 22:14:55
 
 do -- begin closure to overcome local limits and interference
 
@@ -1487,6 +1487,7 @@ local function do_serialize(root,name,depth,level,indexed)
           else
             handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) 
           end
+        elseif tk~="string" then
         elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
           if hexify then
             handle(format("%s %s=0x%X,",depth,k,v))
@@ -1509,6 +1510,7 @@ local function do_serialize(root,name,depth,level,indexed)
           end
         elseif tk=="boolean" then
           handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
+        elseif tk~="string" then
         elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
           handle(format("%s %s=%q,",depth,k,v))
         else
@@ -1524,6 +1526,7 @@ local function do_serialize(root,name,depth,level,indexed)
             end
           elseif tk=="boolean" then
             handle(format("%s [%s]={},",depth,k and "true" or "false"))
+          elseif tk~="string" then
           elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
             handle(format("%s %s={},",depth,k))
           else
@@ -1540,6 +1543,7 @@ local function do_serialize(root,name,depth,level,indexed)
               end
             elseif tk=="boolean" then
               handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", ")))
+            elseif tk~="string" then
             elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
               handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
             else
@@ -1560,6 +1564,7 @@ local function do_serialize(root,name,depth,level,indexed)
           end
         elseif tk=="boolean" then
           handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false"))
+        elseif tk~="string" then
         elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
           handle(format("%s %s=%s,",depth,k,v and "true" or "false"))
         else
@@ -1576,6 +1581,7 @@ local function do_serialize(root,name,depth,level,indexed)
             end
           elseif tk=="boolean" then
             handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
+          elseif tk~="string" then
           elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
             handle(format("%s %s=load(%q),",depth,k,f))
           else
@@ -1591,6 +1597,7 @@ local function do_serialize(root,name,depth,level,indexed)
           end
         elseif tk=="boolean" then
           handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v)))
+        elseif tk~="string" then
         elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
           handle(format("%s %s=%q,",depth,k,tostring(v)))
         else
@@ -5682,7 +5689,7 @@ if not modules then modules={} end modules ['font-con']={
   license="see context related readme files"
 }
 local next,tostring,rawget=next,tostring,rawget
-local format,match,lower,gsub=string.format,string.match,string.lower,string.gsub
+local format,match,lower,gsub,find=string.format,string.match,string.lower,string.gsub,string.find
 local sort,insert,concat,sortedkeys,serialize,fastcopy=table.sort,table.insert,table.concat,table.sortedkeys,table.serialize,table.fastcopy
 local derivetable=table.derive
 local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
@@ -5702,89 +5709,6 @@ constructors.version=1.01
 constructors.cache=containers.define("fonts","constructors",constructors.version,false)
 constructors.privateoffset=0xF0000 
 constructors.cacheintex=true
-constructors.keys={
-  properties={
-    encodingbytes="number",
-    embedding="number",
-    cidinfo={},
-    format="string",
-    fontname="string",
-    fullname="string",
-    filename="filename",
-    psname="string",
-    name="string",
-    virtualized="boolean",
-    hasitalics="boolean",
-    autoitalicamount="basepoints",
-    nostackmath="boolean",
-    noglyphnames="boolean",
-    mode="string",
-    hasmath="boolean",
-    mathitalics="boolean",
-    textitalics="boolean",
-    finalized="boolean",
-  },
-  parameters={
-    mathsize="number",
-    scriptpercentage="float",
-    scriptscriptpercentage="float",
-    units="cardinal",
-    designsize="scaledpoints",
-    expansion={
-                  stretch="integerscale",
-                  shrink="integerscale",
-                  step="integerscale",
-                  auto="boolean",
-                 },
-    protrusion={
-                  auto="boolean",
-                 },
-    slantfactor="float",
-    extendfactor="float",
-    factor="float",
-    hfactor="float",
-    vfactor="float",
-    size="scaledpoints",
-    units="scaledpoints",
-    scaledpoints="scaledpoints",
-    slantperpoint="scaledpoints",
-    spacing={
-                  width="scaledpoints",
-                  stretch="scaledpoints",
-                  shrink="scaledpoints",
-                  extra="scaledpoints",
-                 },
-    xheight="scaledpoints",
-    quad="scaledpoints",
-    ascender="scaledpoints",
-    descender="scaledpoints",
-    synonyms={
-                  space="spacing.width",
-                  spacestretch="spacing.stretch",
-                  spaceshrink="spacing.shrink",
-                  extraspace="spacing.extra",
-                  x_height="xheight",
-                  space_stretch="spacing.stretch",
-                  space_shrink="spacing.shrink",
-                  extra_space="spacing.extra",
-                  em="quad",
-                  ex="xheight",
-                  slant="slantperpoint",
-                 },
-  },
-  description={
-    width="basepoints",
-    height="basepoints",
-    depth="basepoints",
-    boundingbox={},
-  },
-  character={
-    width="scaledpoints",
-    height="scaledpoints",
-    depth="scaledpoints",
-    italic="scaledpoints",
-  },
-}
 local designsizes=allocate()
 constructors.designsizes=designsizes
 local loadedfonts=allocate()
@@ -5922,6 +5846,21 @@ local function mathkerns(v,vdelta)
   end
   return k
 end
+local psfake=0
+local function fixedpsname(psname,fallback)
+  local usedname=psname
+  if not psname or psname=="" then
+    psname=fallback
+    usedname=gsub(psname,"[^a-zA-Z0-9]+","-")
+  elseif find(psname," ") then
+    usedname=gsub(psname,"[%s]+","-")
+  end
+  if not psname or psname=="" then
+    psfake=psfake+1
+    psname="fakename-"..psfake
+  end
+  return usedname,psname~=usedname
+end
 function constructors.scale(tfmdata,specification)
   local target={}
   if tonumber(specification) then
@@ -5995,14 +5934,12 @@ function constructors.scale(tfmdata,specification)
   target.cidinfo=properties.cidinfo
   target.format=properties.format
   target.cache=constructors.cacheintex and "yes" or "renew"
-  local fontname=properties.fontname or tfmdata.fontname 
-  local fullname=properties.fullname or tfmdata.fullname 
-  local filename=properties.filename or tfmdata.filename 
-  local psname=properties.psname  or tfmdata.psname  
+  local fontname=properties.fontname or tfmdata.fontname
+  local fullname=properties.fullname or tfmdata.fullname
+  local filename=properties.filename or tfmdata.filename
+  local psname=properties.psname  or tfmdata.psname
   local name=properties.name   or tfmdata.name
-  if not psname or psname=="" then
-    psname=fontname or (fullname and fonts.names.cleanname(fullname))
-  end
+  local psname,psfixed=fixedpsname(psname,fontname or fullname or file.nameonly(filename))
   target.fontname=fontname
   target.fullname=fullname
   target.filename=filename
@@ -6115,8 +6052,9 @@ function constructors.scale(tfmdata,specification)
     end
   end
   if trace_defining then
-    report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
-      name,fullname,filename,hdelta,vdelta,hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
+    report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a",
+      name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta,
+      hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
   end
   constructors.beforecopyingcharacters(target,tfmdata)
   local sharedkerns={}
@@ -24583,10 +24521,11 @@ if not modules then modules={} end modules ['font-def']={
   copyright="PRAGMA ADE / ConTeXt Development Team",
   license="see context related readme files"
 }
-local format,gmatch,match,find,lower,gsub=string.format,string.gmatch,string.match,string.find,string.lower,string.gsub
+local lower,gsub=string.lower,string.gsub
 local tostring,next=tostring,next
 local lpegmatch=lpeg.match
 local suffixonly,removesuffix=file.suffix,file.removesuffix
+local formatters=string.formatters
 local allocate=utilities.storage.allocate
 local trace_defining=false trackers .register("fonts.defining",function(v) trace_defining=v end)
 local directive_embedall=false directives.register("fonts.embedall",function(v) directive_embedall=v end)
@@ -24747,7 +24686,7 @@ function definers.applypostprocessors(tfmdata)
       local extrahash=postprocessors[i](tfmdata) 
       if type(extrahash)=="string" and extrahash~="" then
         extrahash=gsub(lower(extrahash),"[^a-z]","-")
-        properties.fullname=format("%s-%s",properties.fullname,extrahash)
+        properties.fullname=formatters["%s-%s"](properties.fullname,extrahash)
       end
     end
   end
-- 
cgit v1.2.3