1if not modules then modules = { } end modules['s-math-characters'] = {
2 version = 1.001,
3 comment = "companion to s-math-characters.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
10
11moduledata.math = moduledata.math or { }
12moduledata.math.characters = moduledata.math.characters or { }
13
14local concat = table.concat
15local lower = string.lower
16local utfchar = utf.char
17local round = math.round
18local setmetatableindex = table.setmetatableindex
19local sortedhash = table.sortedhash
20
21local context = context
22
23local fontdata = fonts.hashes.identifiers
24local chardata = characters.data
25local blocks = characters.blocks
26
27local no_description = "no description, private to font"
28
29local limited = true
30local fillinthegaps = true
31local upperlimit = 0x0007F
32local upperlimit = 0xF0000
33
34local f_unicode = string.formatters["%U"]
35local f_slot = string.formatters["%s/%0X"]
36
37function moduledata.math.characters.showlist(specification)
38 specification = interfaces.checkedspecification(specification)
39 local id = specification.number
40 local list = specification.list
41 local showvirtual = specification.virtual == "all"
42 local check = specification.check == "yes"
43 if not id then
44 id = font.current()
45 end
46 if list == "" then
47 list = nil
48 end
49 local tfmdata = fontdata[id]
50 local characters = tfmdata.characters
51 local descriptions = tfmdata.descriptions
52 local resources = tfmdata.resources
53 local lookuptypes = resources.lookuptypes
54 local virtual = tfmdata.properties.virtualized
55 local names = { }
56 local gaps = mathematics.gaps
57 local sorted = { }
58 if type(list) == "string" then
59 sorted = utilities.parsers.settings_to_array(list)
60 for i=1,#sorted do
61 sorted[i] = tonumber(sorted[i])
62 end
63 elseif type(list) == "table" then
64 sorted = list
65 for i=1,#sorted do
66 sorted[i] = tonumber(sorted[i])
67 end
68 elseif fillinthegaps then
69 sorted = table.keys(characters)
70 for k, v in next, gaps do
71 if characters[v] then
72 sorted[#sorted+1] = k
73 end
74 end
75 table.sort(sorted)
76 else
77 sorted = table.sortedkeys(characters)
78 end
79 if virtual then
80 local fonts = tfmdata.fonts
81 for i=1,#fonts do
82 local id = fonts[i].id
83 local name = fontdata[id].properties.name
84 names[i] = (name and file.basename(name)) or id
85 end
86 end
87 if check then
88 for k, v in table.sortedhash(blocks) do
89 if v.math then
90 local first = v.first
91 local last = v.last
92 local f, l = 0, 0
93 if first and last then
94 for unicode=first,last do
95 local code = gaps[unicode] or unicode
96 local char = characters[code]
97 if char and not (char.commands and not showvirtual) then
98 f = unicode
99 break
100 end
101 end
102 for unicode=last,first,-1 do
103 local code = gaps[unicode] or unicode
104 local char = characters[code]
105 if char and not (char.commands and not showvirtual) then
106 l = unicode
107 break
108 end
109 end
110 context.showmathcharacterssetrange(k,f,l)
111 end
112 end
113 end
114 else
115
116 local function collectalllookups(tfmdata,script,language)
117 local all = setmetatableindex(function(t,k) local v = setmetatableindex("table") t[k] = v return v end)
118 local shared = tfmdata.shared
119 local rawdata = shared and shared.rawdata
120 if rawdata then
121 local features = rawdata.resources.features
122 if features.gsub then
123 for kind, feature in next, features.gsub do
124 local validlookups, lookuplist = fonts.handlers.otf.collectlookups(rawdata,kind,script,language)
125 if validlookups then
126 for i=1,#lookuplist do
127 local lookup = lookuplist[i]
128 local steps = lookup.steps
129 for i=1,lookup.nofsteps do
130 local coverage = steps[i].coverage
131 if coverage then
132 for k, v in next, coverage do
133 all[k][lookup.type][kind] = v
134 end
135 end
136 end
137 end
138 end
139 end
140 end
141 end
142 return all
143 end
144
145 local alllookups = collectalllookups(tfmdata,"math","dflt")
146
147 local luametatex = LUATEXENGINE == "luametatex"
148
149 context.showmathcharactersstart()
150 for _, unicode in next, sorted do
151 if not limited or unicode < upperlimit then
152 local code = gaps[unicode] or unicode
153 local char = characters[code]
154 local desc = descriptions[code]
155 local info = chardata[code]
156 if char then
157 local commands = char.commands
158 if commands and not showvirtual then
159
160 else
161 local next_sizes = char.next
162 local vparts = char.vparts or char.vert_variants
163 local hparts = char.hparts or char.horiz_variants
164 local mathclass = info.mathclass
165 local mathspec = info.mathspec
166 local mathsymbol = info.mathsymbol
167 local description = info.description or no_description
168 context.showmathcharactersstartentry(
169 )
170 context.showmathcharactersreference(
171 f_unicode(unicode)
172 )
173 context.showmathcharactersentryhexdectit(
174 f_unicode(code),
175 code,
176 lower(description)
177 )
178 if luametatex then
179 context.showmathcharactersentrywdhtdpicta(
180 code
181 )
182 else
183 context.showmathcharactersentrywdhtdpicta(
184 round(char.width or 0),
185 round(char.height or 0),
186 round(char.depth or 0),
187 round(char.italic or 0),
188 round(char.topanchor or char.topaccent or 0)
189 )
190 end
191 if virtual and commands then
192 local t = { }
193 for i=1,#commands do
194 local ci = commands[i]
195 if ci[1] == "slot" then
196 local fnt, idx = ci[2], ci[3]
197 t[#t+1] = f_slot(names[fnt] or fnt,idx)
198 end
199 end
200 if #t > 0 then
201 context.showmathcharactersentryresource(concat(t,", "))
202 end
203 end
204 if mathclass or mathspec then
205 context.showmathcharactersstartentryclassspec()
206 if mathclass then
207 context.showmathcharactersentryclassname(mathclass,info.mathname or "no name")
208 end
209 if mathspec then
210 for i=1,#mathspec do
211 local mi = mathspec[i]
212 context.showmathcharactersentryclassname(mi.class,mi.name or "no name")
213 end
214 end
215 context.showmathcharactersstopentryclassspec()
216 end
217 if mathsymbol then
218 context.showmathcharactersentrysymbol(f_unicode(mathsymbol),mathsymbol)
219 end
220 if next_sizes then
221 local n, done = 0, { }
222 context.showmathcharactersstartnext()
223 while next_sizes do
224 n = n + 1
225 if done[next_sizes] then
226 context.showmathcharactersnextcycle(n)
227 break
228 else
229 done[next_sizes] = true
230 context.showmathcharactersnextentry(n,f_unicode(next_sizes),next_sizes)
231 next_sizes = characters[next_sizes]
232 vparts = next_sizes.vparts or next_sizes.vert_variants or vparts
233 hparts = next_sizes.hparts or next_sizes.horiz_variants or hparts
234 if next_sizes then
235 next_sizes = next_sizes.next
236 end
237 end
238 end
239 context.showmathcharactersstopnext()
240 if vparts or hparts then
241 context.showmathcharactersbetweennextandvariants()
242 end
243 end
244 if vparts then
245 context.showmathcharactersstartvparts()
246 for i=1,#vparts do
247 local vi = vparts[i]
248 context.showmathcharactersvpartsentry(i,f_unicode(vi.glyph),vi.glyph)
249 end
250 context.showmathcharactersstopvparts()
251 end
252 if hparts then
253 context.showmathcharactersstarthparts()
254 for i=1,#hparts do
255 local hi = hparts[#hparts-i+1]
256 context.showmathcharactershpartsentry(i,f_unicode(hi.glyph),hi.glyph)
257 end
258 context.showmathcharactersstophparts()
259 end
260 local lookups = alllookups[unicode]
261 if lookups then
262 local variants = { }
263 local singles = lookups.gsub_single
264 local alternates = lookups.gsub_alternate
265 if singles then
266 for lookupname, code in next, singles do
267 variants[code] = lookupname
268 end
269 end
270 if singles then
271 for lookupname, codes in next, alternates do
272 for i=1,#codes do
273 variants[codes[i]] = lookupname .. " : " .. i
274 end
275 end
276 end
277 context.showmathcharactersstartlookupvariants()
278 local i = 0
279 for variant, lookuptype in sortedhash(variants) do
280 i = i + 1
281 context.showmathcharacterslookupvariant(i,f_unicode(variant),variant,lookuptype)
282 end
283 context.showmathcharactersstoplookupvariants()
284 end
285 context.showmathcharactersstopentry()
286 end
287 end
288 end
289 end
290 context.showmathcharactersstop()
291 end
292end
293 |