font-mpf.lmt /size: 6044 b    last modification: 2025-02-21 11:03
1if not modules then modules = { } end modules ['font-mpf'] = {
2    version   = 1.001,
3    comment   = "companion to font-ini.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local tonumber, unpack, type = tonumber, unpack, type
10
11local context  = context
12local metapost = metapost
13
14local metafonts    = { }
15metapost.metafonts = metafonts
16
17local sortedhash        = table.sortedhash
18
19local addcharacters     = fonts.constructors.addcharacters
20local fontdata          = fonts.hashes.identifiers
21
22local otf               = fonts.handlers.otf
23local otfregister       = otf.features.register
24
25local getshapes         = fonts.dropins.getshapes
26
27local setparameterset   = metapost.setparameterset
28local simplemetapost    = metapost.simple
29
30local register          = fonts.collections.register
31local checkenabled      = fonts.collections.checkenabled
32local newprivateslot    = fonts.helpers.newprivateslot
33
34local currentfont       = font.current
35
36local function setmetaglyphs(category,fontid,unicode,specification)
37    if unicode then
38        local tfmdata    = fontdata[fontid]
39        local characters = tfmdata.characters
40        specification.unicode  = unicode
41        specification.category = category
42        -- Generate one shape, make a use we pass the unicode as that is
43        -- the index in a picture list (normally). We could actually already
44        -- fetch the stream but for now we do that later (i.e. we delay the
45        -- serialization to pdf).
46        local code = specification.code
47        if code then
48            setparameterset("mpsfont",specification)
49         -- simplemetapost(instance,"begingroup;",true,true)
50            simplemetapost("simplefun",code)
51         -- simplemetapost(instance,"endgroup;",true,true)
52        end
53        -- We now know (hopefully) the dimensions of the image which is what
54        -- we need to pass to the engine in order to let it do its work.
55        local shapes = getshapes(category)
56        local units  = shapes.parameters.units
57        local scale  = tfmdata.parameters.size / units
58        local shape  = shapes.glyphs[unicode]
59        if shape then
60            --
61            local llx, lly, urx, ury = unpack(shape.boundingbox)
62            llx = llx * scale
63            urx = urx * scale
64            lly = lly * scale
65            ury = ury * scale
66            --
67            local newdata = { }
68            characters[unicode] = newdata -- so that we can register commands
69            fonts.dropins.swapone("mps",tfmdata,shape,unicode)
70            --
71            newdata.width   = urx - llx
72            newdata.height  = ury
73            newdata.depth   = -lly
74            newdata.unicode = unicode
75            -- commands = { { "offset", -llx, 0, newdata.commands[1][1], newdata.commands[1][2] } }
76            if llx ~= 0 then
77                newdata.commands = { { "offset", -llx, 0 }, newdata.commands[1] }
78            end
79            -- pass dimensions to lua
80            characters[unicode] = newdata
81            -- pass dimensions to tex
82            addcharacters(fontid, { characters = { [unicode] = newdata } })
83            return fontid, unicode
84        else
85            logs.report("metaglyph", "bad shape %U in font %i", unicode, fontid)
86        end
87    end
88end
89
90local function setmetaglyph(specification)
91    if specification then
92        local category = specification.category
93        local name     = specification.name
94        if category and name then
95            local fontid  = specification.fontid or currentfont()
96            local private = newprivateslot(name)
97            register(fontid,private,function(font,char)
98                return setmetaglyphs(category,font,char,specification) end
99            )
100            checkenabled()
101        end
102    end
103end
104
105local function initializempf(tfmdata,kind,value)
106    local metafont = metafonts[value]
107    if value then
108        local font = tfmdata.properties.id
109        for char, spec in sortedhash(metafont) do
110            local char = type(char) == "string" and newprivateslot(char) or char
111            register(font,char,function(font,char)
112                return setmetaglyphs(value,font,char,spec)
113            end)
114        end
115        checkenabled()
116    end
117end
118
119fonts.helpers.setmetaglyphs = setmetaglyphs
120fonts.helpers.setmetaglyph  = setmetaglyph
121
122otfregister {
123    name         = "metafont",
124    description  = "metafont glyphs",
125    manipulators = {
126        base = initializempf,
127        node = initializempf,
128    }
129}
130
131do
132
133    local scanners   = tokens.scanners
134    local scanopen   = scanners.scanopen
135    local scanclose  = scanners.scanclose
136    local scanword   = scanners.word
137    local scanstring = scanners.string
138
139    interfaces.implement {
140        name      = "setmetaglyph",
141        public    = true,
142        protected = true,
143        actions   = function(t)
144            local t = { }
145            if scanopen() then
146                 while not scanclose() do
147                    local key = scanword()
148                    if key == "shapes" then
149                        if scanopen() then
150                            local tt = { }
151                            local nn = 0
152                            while not scanclose() do
153                                if scanopen() then
154                                    local ttt = { }
155                                    while not scanclose() do
156                                        local key = scanword()
157                                        ttt[key] = scanstring()
158                                    end
159                                    nn= nn + 1
160                                    tt[nn] = ttt
161                                end
162                            end
163                            t[key] = tt
164                        end
165                    else
166                        t[key] = scanstring()
167                    end
168                end
169            end
170            setmetaglyph(t)
171        end
172    }
173
174end
175