font-mpf.lmt /size: 6114 b    last modification: 2021-10-28 13:51
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            local olddata = characters[unicode]
72            newdata.width   = urx - llx
73            newdata.height  = ury
74            newdata.depth   = -lly
75            newdata.unicode = unicode
76            -- commands = { { "offset", -llx, 0, newdata.commands[1][1], newdata.commands[1][2] } }
77            if llx ~= 0 then
78                newdata.commands = { { "offset", -llx, 0 }, newdata.commands[1] }
79            end
80            -- pass dimensions to lua
81            characters[unicode] = newdata
82            -- pass dimensions to tex
83            addcharacters(fontid, { characters = { [unicode] = newdata } })
84            return fontid, unicode
85        else
86            logs.report("metaglyph", "bad shape %U in font %i", unicode, fontid)
87        end
88    end
89end
90
91local function setmetaglyph(specification)
92    if specification then
93        local category = specification.category
94        local name     = specification.name
95        if category and name then
96            local fontid  = specification.fontid or currentfont()
97            local private = newprivateslot(name)
98            register(fontid,private,function(font,char)
99                return setmetaglyphs(category,font,char,specification) end
100            )
101            checkenabled()
102        end
103    end
104end
105
106local function initializempf(tfmdata,kind,value)
107    local metafont = metafonts[value]
108    if value then
109        local font = tfmdata.properties.id
110        for char, spec in sortedhash(metafont) do
111            if type(char) == "string" then
112                char = newprivateslot(char)
113            end
114            register(font,char,function(font,char)
115                return setmetaglyphs(value,font,char,spec)
116            end)
117        end
118        checkenabled()
119    end
120end
121
122fonts.helpers.setmetaglyphs = setmetaglyphs
123fonts.helpers.setmetaglyph  = setmetaglyph
124
125otfregister {
126    name         = "metafont",
127    description  = "metafont glyphs",
128    manipulators = {
129        base = initializempf,
130        node = initializempf,
131    }
132}
133
134do
135
136    local scanners   = tokens.scanners
137    local scanopen   = scanners.scanopen
138    local scanclose  = scanners.scanclose
139    local scanword   = scanners.word
140    local scanstring = scanners.string
141
142    interfaces.implement {
143        name      = "setmetaglyph",
144        public    = true,
145        protected = true,
146        actions   = function(t)
147            local t = { }
148            if scanopen() then
149                 while not scanclose() do
150                    local key = scanword()
151                    if key == "shapes" then
152                        if scanopen() then
153                            local tt = { }
154                            local nn = 0
155                            while not scanclose() do
156                                if scanopen() then
157                                    local ttt = { }
158                                    while not scanclose() do
159                                        local key = scanword()
160                                        ttt[key] = scanstring()
161                                    end
162                                    nn= nn + 1
163                                    tt[nn] = ttt
164                                end
165                            end
166                            t[key] = tt
167                        end
168                    else
169                        t[key] = scanstring()
170                    end
171                end
172            end
173            setmetaglyph(t)
174        end
175    }
176
177end
178