s-math-characters.lua /size: 11 Kb    last modification: 2021-10-28 13:51
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-- This is one of the oldest cld files but I'm not going to clean it up.
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 -- or specification.id
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
116local 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
143end
144
145local alllookups = collectalllookups(tfmdata,"math","dflt")
146
147        context.showmathcharactersstart()
148        for _, unicode in next, sorted do
149            if not limited or unicode < upperlimit then
150                local code = gaps[unicode] or unicode
151                local char = characters[code]
152                local desc = descriptions[code]
153                local info = chardata[code]
154                if char then
155                    local commands    = char.commands
156                    if commands and not showvirtual then
157                        -- skip
158                    else
159                        local next_sizes  = char.next
160                        local v_variants  = char.vert_variants
161                        local h_variants  = char.horiz_variants
162                        local mathclass   = info.mathclass
163                        local mathspec    = info.mathspec
164                        local mathsymbol  = info.mathsymbol
165                        local description = info.description or no_description
166                        context.showmathcharactersstartentry()
167                        context.showmathcharactersreference(f_unicode(unicode))
168                        context.showmathcharactersentryhexdectit(f_unicode(code),code,lower(description))
169                        context.showmathcharactersentrywdhtdpic(round(char.width or 0),round(char.height or 0),round(char.depth or 0),round(char.italic or 0))
170                        if virtual and commands then
171                            local t = { }
172                            for i=1,#commands do
173                                local ci = commands[i]
174                                if ci[1] == "slot" then
175                                    local fnt, idx = ci[2], ci[3]
176                                    t[#t+1] = f_slot(names[fnt] or fnt,idx)
177                                end
178                            end
179                            if #t > 0 then
180                                context.showmathcharactersentryresource(concat(t,", "))
181                            end
182                        end
183                        if mathclass or mathspec then
184                            context.showmathcharactersstartentryclassspec()
185                            if mathclass then
186                                context.showmathcharactersentryclassname(mathclass,info.mathname or "no name")
187                            end
188                            if mathspec then
189                                for i=1,#mathspec do
190                                    local mi = mathspec[i]
191                                    context.showmathcharactersentryclassname(mi.class,mi.name or "no name")
192                                end
193                            end
194                            context.showmathcharactersstopentryclassspec()
195                        end
196                        if mathsymbol then
197                            context.showmathcharactersentrysymbol(f_unicode(mathsymbol),mathsymbol)
198                        end
199                        if next_sizes then
200                            local n, done = 0, { }
201                            context.showmathcharactersstartnext()
202                            while next_sizes do
203                                n = n + 1
204                                if done[next_sizes] then
205                                    context.showmathcharactersnextcycle(n)
206                                    break
207                                else
208                                    done[next_sizes] = true
209                                    context.showmathcharactersnextentry(n,f_unicode(next_sizes),next_sizes)
210                                    next_sizes = characters[next_sizes]
211                                    v_variants = next_sizes.vert_variants  or v_variants
212                                    h_variants = next_sizes.horiz_variants or h_variants
213                                    if next_sizes then
214                                        next_sizes = next_sizes.next
215                                    end
216                                end
217                            end
218                            context.showmathcharactersstopnext()
219                            if h_variants or v_variants then
220                                context.showmathcharactersbetweennextandvariants()
221                            end
222                        end
223                        if h_variants then
224                            context.showmathcharactersstarthvariants()
225                            for i=1,#h_variants do -- we might go top-down in the original
226                                local vi = h_variants[i]
227                                context.showmathcharactershvariantsentry(i,f_unicode(vi.glyph),vi.glyph)
228                            end
229                            context.showmathcharactersstophvariants()
230                        elseif v_variants then
231                            context.showmathcharactersstartvvariants()
232                            for i=1,#v_variants do
233                                local vi = v_variants[#v_variants-i+1]
234                                context.showmathcharactersvvariantsentry(i,f_unicode(vi.glyph),vi.glyph)
235                            end
236                            context.showmathcharactersstopvvariants()
237                        end
238                        local lookups = alllookups[unicode]
239                        if lookups then
240                            local variants   = { }
241                            local singles    = lookups.gsub_single
242                            local alternates = lookups.gsub_alternate
243                            if singles then
244                                for lookupname, code in next, singles do
245                                    variants[code] = lookupname
246                                end
247                            end
248                            if singles then
249                                for lookupname, codes in next, alternates do
250                                    for i=1,#codes do
251                                        variants[codes[i]] = lookupname .. " : " .. i
252                                    end
253                                end
254                            end
255                            context.showmathcharactersstartlookupvariants()
256                            local i = 0
257                            for variant, lookuptype in sortedhash(variants) do
258                                i = i + 1
259                                context.showmathcharacterslookupvariant(i,f_unicode(variant),variant,lookuptype)
260                            end
261                            context.showmathcharactersstoplookupvariants()
262                        end
263                        context.showmathcharactersstopentry()
264                    end
265                end
266            end
267        end
268        context.showmathcharactersstop()
269    end
270end
271