math-fnt.lmt /size: 6011 b    last modification: 2024-01-16 09:02
1if not modules then modules = { } end modules ['math-fnt'] = {
2    version   = 1.001,
3    comment   = "companion to math-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
9-- It is a pitty that we don't have a unicode character that can be used but that never
10-- gets copied when we cut and paste. Not all pdf viewers ignore 0xFFFD for instance.
11
12local round = math.round
13local setmetatableindex = table.setmetatableindex
14
15local nuts          = nodes.nuts
16local tonut         = nodes.tonut
17local tonode        = nodes.tonode
18local nodepool      = nuts.pool
19
20local vlist_code    = nodes.nodecodes.vlist
21
22local new_hlist     = nodepool.hlist
23local new_vlist     = nodepool.vlist
24----- new_glyph     = nodepool.glyph
25local new_glyph     = nuts.newmathglyph
26
27local getattrlst    = nuts.getattributelist
28local setattrlst    = nuts.setattributelist
29local setwhd        = nuts.setwhd
30local getwhd        = nuts.getwhd
31local getid         = nuts.getid
32
33local chardata      = fonts.hashes.characters
34local addcharacters = font.addcharacters
35
36-- not yet ok for compact fonts .. needs checking .. or just make this non-compact only
37-- there's also an inaccuracy creeping in: \sqrt{\quad\blackrule[height=25pt,depth=25pt]}
38
39local cache = setmetatableindex(function(t,width)
40    local v = setmetatableindex(function(t,height)
41        local v = setmetatableindex(function(t,depth)
42            local v = setmetatableindex(function(t,font)
43                local v = setmetatableindex(function(t,char)
44                    t[char] = v
45                    return v
46                end)
47                t[font] = v
48                return v
49            end)
50            t[depth] = v
51            return v
52        end)
53        t[height] = v
54        return v
55    end)
56    t[width] = v
57    return v
58end)
59
60local enabled = "vertical"  directives.register("math.extensibles", function(v) enabled = v end) -- default per 2022-08-25
61
62local function register_extensible(font,char,style,att,box)
63    if enabled then
64        -- We don't share (yet)!
65        local fontdata = chardata[font]
66        local oldchar  = fontdata[char]
67        if oldchar and not oldchar.keepvirtual then
68            if enabled == true or enabled == "both" or oldchar.partsorientation == enabled then
69                -- we're okay
70            else
71                return
72            end
73if not box then -- pending build bot
74    box = att
75end
76            local bx = tonut(box)
77            -- actually we don't want colors and such so if we do finalize we
78            -- should be more selective:
79    --         updaters.apply("tagging.state.disable")
80    --         nodes.handlers.finalizelist(bx)
81    --         updaters.apply("tagging.state.enable")
82-- updaters.apply("tagging.state.disable")
83            local id = getid(bx)
84if not att then -- pending build bot
85    att = getattrlst(box)
86end
87            local al = tonut(att)
88            local wd, ht, dp = getwhd(bx)
89            local unicode = oldchar.unicode or char
90            -- we cannot have self referencing t3 fonts .. see devirtualize code
91            local oldcommands = oldchar.oldcommands
92            local newcommands = oldchar.commands
93            if oldcommands then
94                oldchar.commands = oldcommands
95            end
96            -- these need to be applied here
97            local p  = fonts.hashes.parameters[font]
98            local sx = round(1000/(p.extendfactor  or 1)) or 1000
99            local sy = round(1000/(p.squeezefactor or 1)) or 1000
100--             -- we saved a scaled glyph stream so we now use an unscaled one ... horrible hack:
101--             if sx ~= 1000 then
102--                 wd = wd * 7200/7227
103--             end
104--             if sy ~= 1000 then
105--                 ht = ht * 7200/7227
106--                 dp = dp * 7200/7227
107--             end
108            --
109        --  local private = fonts.helpers.setboxdirectly(font,unicode,box) -- maybe cache in setboxdirectly
110            local private = cache[wd][ht][dp][font][unicode]
111            if not private then
112                private = fonts.helpers.setboxdirectly(font,unicode,box,true) -- expose=true so we get color
113                cache[wd][ht][dp][font][unicode] = private
114            end
115            local glyph = new_glyph(font,private,al)
116            setattrlst(glyph,al)
117            nuts.setscales(glyph,1000,sx,sy)
118            --
119         -- if fonts.hashes.properties[font].compactmath then
120         --     nuts.setscales(g,1000,1000,1000)
121         -- end
122            --
123            -- nasty, testcase: bold math sqrt extensible
124            --
125            local n = new_hlist(glyph)
126            --
127            if newcommands then
128                oldchar.commands = newcommands
129            end
130            --
131         -- local newchar = {
132         --     unicode = unicode,
133         --     width   = wd,
134         --     height  = ht,
135         --     depth  =  dp,
136         -- }
137         -- local p = oldchar.parts
138         -- if p then
139         --     local first = fontdata[p[#p].glyph]
140         --     local last  = fontdata[p[ 1].glyph]
141         --     if first then
142         --         newchar.topleft  = first.topleft
143         --         newchar.topright = first.topright
144         --     end
145         --     if last then
146         --         newchar.bottomleft  = last.bottomleft
147         --         newchar.bottomright = last.bottomright
148         --     end
149         -- end
150         -- addcharacters(font, { [private] = newchar })
151            -- so the dimensions of the box don't match the glyph scale!
152            setwhd(n,wd,ht,dp)
153            setattrlst(n,al)
154            if id == vlist_code then
155                n = new_vlist(n)
156                setwhd(n,wd,ht,dp)
157                setattrlst(n,al)
158            end
159            return tonode(n)
160        end
161    end
162end
163
164callbacks.register("register_extensible",register_extensible,"register math extensible construct")
165