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
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])
55 end
56 end
57 if maplines then
58 for i=1,#maplines do
59 fonts.mappings.loadline(maplines[i])
60 end
61 end
62 end
63end
64
65fontgoodies.register("mathematics", initialize)
66
67
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
176
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 |