meta-fnt.lmt /size: 5259 b    last modification: 2021-10-28 13:51
1if not modules then modules = { } end modules ['meta-fnt'] = {
2    version   = 1.001,
3    comment   = "companion to meta-fnt.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
9-- This was one of the demo modules that never was used for real so the \MKIV\
10-- variant has been replaced by one using the newer \LMTX\ interface, but only
11-- because we want to be (sort of) compatible. Instead of doing the work at the
12-- \LUA\ end we do it at the \TEX end.
13
14metapost.fonts = metapost.fonts or { }
15
16function metapost.fonts.define(specification)
17    local fontname = specification.fontname
18    local filename = specification.filename
19    local fontsize = specification.size
20    context.definemetafont (
21        { fontname },
22        { filename },
23        { size and { "at " .. size .. " sp" } or "" }
24    )
25end
26
27-- metapost.fonts.define {
28--     fontname = "bidi",
29--     filename = "bidi-symbols.mp",
30-- }
31
32-- okay, let's for the moment put this here:
33
34local tonumber = tonumber
35local find = string.find
36
37local context = context
38
39local fastserialize     = table.fastserialize
40local settings_to_hash  = utilities.parsers.settings_to_hash
41local settings_to_array = utilities.parsers.settings_to_array
42
43local addcharacters     = fonts.constructors.addcharacters
44local fontdata          = fonts.hashes.identifiers
45
46-- This is a prelude to a more advance mechanism: when we are in mp we can construct the
47-- whole composed character there.
48
49function fonts.helpers.combineglyphs(fnt, specification)
50    local hash     = fastserialize(specification)
51    local fontid   = fnt or font.current()
52    local tfmdata  = fontdata[fontid]
53    local combhash = tfmdata.combhash or { }
54    local unicode  = combhash[hash]
55    if not unicode then
56        local t = { }
57        local h = 0
58        local d = 0
59        local w = 0
60        local o = 0
61        local characters = tfmdata.characters
62        for i=1,#specification do
63            local s = specification[i]
64            local l = find(s,"=") and settings_to_hash(s)
65            local n = tonumber(l and l.unicode or s) or tonumber(s)
66            if n then
67                local data = characters[n]
68                if data then
69                    local bb = data.boundingbox
70                    if bb then
71                        local llx = bb[1]
72                        local lly = bb[2]
73                        local urx = bb[3]
74                        local ury = bb[4]
75                        if ury > h then
76                            h = ury
77                        elseif - ury > d then
78                            d = - ury
79                        end
80                        if - lly > d then
81                            d = - lly
82                        elseif lly > h then
83                            h = lly
84                        end
85                        if llx < o then
86                            o = llx
87                        end
88                        -- could be an extension to the "offset" command
89                        local c = l and l.color
90                        if c then
91                            t[#t+1] = { "startcolor", c }
92                        end
93                        t[#t+1] = { "offset", 0, 0, n }
94                        if c then
95                            t[#t+1] = { "stopcolor" }
96                        end
97                     -- t[#t+1] = { "push" }
98                     -- if c then
99                     --     t[#t+1] = { "startcolor", c }
100                     -- end
101                     -- t[#t+1] = { "right", 0 }
102                     -- t[#t+1] = { "char", n }
103                     -- if c then
104                     --     t[#t+1] = { "stopcolor" }
105                     -- end
106                     -- t[#t+1] = { "pop" }
107                        if urx > w then
108                            w = urx
109                        end
110                    else
111                        local ht = data.height or 0 if ht > h then h = ht end
112                        local dp = data.depth  or 0 if dp > d then d = dp end
113                        local wd = data.width  or 0 if wd > w then w = wd end
114                        t[#t+1] = { "char", n }
115                    end
116                end
117            end
118        end
119        for i=1,#t do
120--             if t[i][1] == "right" then
121            if t[i][1] == "offset" then
122                t[i][2] = -o
123--                 t[i][2] = o
124            end
125        end
126        -- cheat one: we get a private slot
127        unicode = fonts.helpers.addprivate(tfmdata,nil,{
128            commands = t,
129            width    = w - o,
130            height   = h,
131            depth    = d,
132        })
133        -- cheat two: we overload it later
134        addcharacters(fontid,{ characters = { [unicode] = characters[unicode] } })
135        tfmdata.combhash = combhash
136        combhash[hash] = unicode
137    end
138    return unicode
139end
140
141interfaces.implement {
142    name      = "combineglyphs",
143    public    = true,
144    arguments = "string",
145    actions   = function(list)
146        local list = settings_to_array(list)
147        local unicode = fonts.helpers.combineglyphs(font.current(),list)
148        context(unicode)
149    end,
150}
151