good-mth.lmt /size: 6548 b    last modification: 2024-01-16 09:02
1if not modules then modules = { } end modules ['good-mth'] = {
2    version   = 1.000,
3    comment   = "companion to font-lib.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 type, next, tonumber, unpack = type, next, tonumber, unpack
10local ceil = math.ceil
11local match = string.match
12
13local fonts = fonts
14
15local trace_goodies      = false  trackers.register("fonts.goodies", function(v) trace_goodies = v end)
16local report_goodies     = logs.reporter("fonts","goodies")
17
18local registerotffeature = fonts.handlers.otf.features.register
19
20local fontgoodies        = fonts.goodies or { }
21
22local fontcharacters     = fonts.hashes.characters
23
24local trace_defining     = false  trackers.register  ("math.defining",  function(v) trace_defining   = v     end)
25local use_math_goodies   = true   directives.register("math.nogoodies", function(v) use_math_goodies = not v end)
26
27local report_math        = logs.reporter("mathematics","initializing")
28
29local nuts               = nodes.nuts
30local setlink            = nuts.setlink
31
32local nodepool           = nuts.pool
33local new_kern           = nodepool.kern
34local new_glyph          = nodepool.glyph
35local new_hlist          = nodepool.hlist
36local new_vlist          = nodepool.vlist
37
38local insertnodeafter    = nuts.insertafter
39
40local function initialize(goodies)
41    local mathgoodies = goodies.mathematics
42    if mathgoodies then
43        local virtuals = mathgoodies.virtuals
44        local mapfiles = mathgoodies.mapfiles
45        local maplines = mathgoodies.maplines
46        if virtuals then
47            for name, specification in next, virtuals do
48                -- beware, they are all constructed ... we should be more selective
49                mathematics.makefont(name,specification,goodies)
50            end
51        end
52        if mapfiles then
53            for i=1,#mapfiles do
54                fonts.mappings.loadfile(mapfiles[i]) -- todo: backend function
55            end
56        end
57        if maplines then
58            for i=1,#maplines do
59                fonts.mappings.loadline(maplines[i]) -- todo: backend function
60            end
61        end
62    end
63end
64
65fontgoodies.register("mathematics", initialize)
66
67-- This is used in the koeieletters font:
68
69local function mathradicalaction(n,h,v,font,mchar,echar)
70    local characters = fontcharacters[font]
71    local mchardata  = characters[mchar]
72    local echardata  = characters[echar]
73    local ewidth     = echardata.width
74    local mwidth     = mchardata.width
75    local delta      = h - ewidth
76    local glyph      = new_glyph(font,echar)
77    local head       = glyph
78    if delta > 0 then
79        local count = ceil(delta/mwidth)
80        local kern  = (delta - count * mwidth) / count
81        for i=1,count do
82            local k = new_kern(kern)
83            local g = new_glyph(font,mchar)
84            setlink(k,head)
85            setlink(g,k)
86            head = g
87        end
88    end
89    local height = mchardata.height
90    local list   = new_hlist(head)
91    local kern   = new_kern(height-v)
92    list = setlink(kern,list)
93    local list = new_vlist(kern)
94    insertnodeafter(n,n,list)
95end
96
97local function mathhruleaction(n,h,v,font,bchar,mchar,echar)
98    local characters = fontcharacters[font]
99    local bchardata  = characters[bchar]
100    local mchardata  = characters[mchar]
101    local echardata  = characters[echar]
102    local bwidth     = bchardata.width
103    local mwidth     = mchardata.width
104    local ewidth     = echardata.width
105    local delta      = h - ewidth - bwidth
106    local glyph      = new_glyph(font,echar)
107    local head       = glyph
108    if delta > 0 then
109        local count = ceil(delta/mwidth)
110        local kern  = (delta - count * mwidth) / (count+1)
111        for i=1,count do
112            local k = new_kern(kern)
113            local g = new_glyph(font,mchar)
114            setlink(k,head)
115            setlink(g,k)
116            head = g
117        end
118        local k = new_kern(kern)
119        setlink(k,head)
120        head = k
121    end
122    local g = new_glyph(font,bchar)
123    setlink(g,head)
124    head = g
125    local height = mchardata.height
126    local list   = new_hlist(head)
127    local kern   = new_kern(height-v)
128    list = setlink(kern,list)
129    local list = new_vlist(kern)
130    insertnodeafter(n,n,list)
131end
132
133local function initialize(tfmdata)
134    local goodies = tfmdata.goodies
135    if goodies then
136        local resources = tfmdata.resources
137        local ruledata  = { }
138        for i=1,#goodies do
139            local mathematics = goodies[i].mathematics
140            if mathematics then
141                local rules = mathematics.rules
142                if rules then
143                    for tag, name in next, rules do
144                        ruledata[tag] = name
145                    end
146                end
147            end
148        end
149        if next(ruledata) then
150            local characters = tfmdata.characters
151            local unicodes   = resources.unicodes
152            if characters and unicodes then
153                local mathruleactions = resources.mathruleactions
154                if not mathruleactions then
155                    mathruleactions = { }
156                    resources.mathruleactions = mathruleactions
157                end
158                --
159                local mchar = unicodes[ruledata["radical.extender"] or false]
160                local echar = unicodes[ruledata["radical.end"]      or false]
161                if mchar and echar then
162                    mathruleactions.radicalaction = function(n,h,v,font)
163                        mathradicalaction(n,h,v,font,mchar,echar)
164                    end
165                end
166                --
167                local bchar = unicodes[ruledata["hrule.begin"]    or false]
168                local mchar = unicodes[ruledata["hrule.extender"] or false]
169                local echar = unicodes[ruledata["hrule.end"]      or false]
170                if bchar and mchar and echar then
171                    mathruleactions.hruleaction = function(n,h,v,font)
172                        mathhruleaction(n,h,v,font,bchar,mchar,echar)
173                    end
174                end
175                -- not that nice but we need to register it at the tex end
176             -- context.enablemathrules("\\fontclass")
177            end
178        end
179    end
180end
181
182registerotffeature {
183    name         = "mathrules",
184    description  = "check math rules",
185    default      = true,
186    initializers = {
187        base = initialize,
188        node = initialize,
189    }
190}
191