1if not modules then modules = { } end modules ['s-fonts-features'] = {
2 version = 1.001,
3 comment = "companion to s-fonts-features.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
9moduledata.fonts = moduledata.fonts or { }
10moduledata.fonts.features = moduledata.fonts.features or { }
11
12
13
14local rawget = rawget
15local insert, remove, sortedhash = table.insert, table.remove, table.sortedhash
16
17local v_yes = interfaces.variables.yes
18local v_no = interfaces.variables.no
19local c_name = interfaces.constants.name
20
21local NC, NR, bold = context.NC, context.NR, context.bold
22
23function moduledata.fonts.features.showused(specification)
24
25 specification = interfaces.checkedspecification(specification)
26
27
28
29 context.starttabulate { "|T|T|T|T|T|" }
30
31 context.HL()
32
33 NC() bold("feature")
34 NC()
35 NC() bold("description")
36 NC() bold("value")
37 NC() bold("internal")
38 NC() NR()
39
40 context.HL()
41
42 local usedfeatures = fonts.handlers.otf.statistics.usedfeatures
43 local features = fonts.handlers.otf.tables.features
44 local descriptions = fonts.handlers.otf.features.descriptions
45
46 for feature, keys in sortedhash(usedfeatures) do
47
48 local done = false
49 for k, v in sortedhash(keys) do
50 if done then
51 NC()
52 NC()
53 NC()
54 elseif rawget(descriptions,feature) then
55 NC() context(feature)
56 NC() context("+")
57 NC() context.escaped(descriptions[feature])
58 done = true
59 elseif rawget(features,feature) then
60 NC() context(feature)
61 NC()
62 NC() context.escaped(features[feature])
63 done = true
64 else
65 NC() context(feature)
66 NC() context("-")
67 NC()
68 done = true
69 end
70 NC() context(k)
71 NC() context(tostring(v))
72 NC() NR()
73 end
74
75 end
76
77 context.HL()
78
79 context.stoptabulate()
80
81end
82
83local function collectkerns(tfmdata,feature)
84 local combinations = { }
85 local resources = tfmdata.resources
86 local characters = tfmdata.characters
87 local sequences = resources.sequences
88 local lookuphash = resources.lookuphash
89 local feature = feature or "kern"
90 if sequences then
91 for i=1,#sequences do
92 local sequence = sequences[i]
93 if sequence.features and sequence.features[feature] then
94 local steps = sequence.steps
95 for i=1,#steps do
96 local step = steps[i]
97 local format = step.format
98 for unicode, hash in table.sortedhash(step.coverage) do
99 local kerns = combinations[unicode]
100 if not kerns then
101 kerns = { }
102 combinations[unicode] = kerns
103 end
104 for otherunicode, kern in table.sortedhash(hash) do
105 if format == "pair" then
106 local f = kern[1]
107 local s = kern[2]
108 if f then
109 if s then
110
111 else
112 if not kerns[otherunicode] and f[3] ~= 0 then
113 kerns[otherunicode] = f[3]
114 end
115 end
116 elseif s then
117
118 end
119 elseif format == "kern" then
120 if not kerns[otherunicode] and kern ~= 0 then
121 kerns[otherunicode] = kern
122 end
123 end
124 end
125 end
126 end
127 end
128 end
129 end
130
131 return combinations
132end
133
134local showkernpair = context.showkernpair
135
136function moduledata.fonts.features.showbasekerns(specification)
137
138 specification = interfaces.checkedspecification(specification)
139 local id, cs = fonts.definers.internal(specification,"<module:fonts:features:font>")
140 local tfmdata = fonts.hashes.identifiers[id]
141 local done = false
142 for unicode, character in sortedhash(tfmdata.characters) do
143 local kerns = character.kerns
144 if kerns then
145 context.par()
146 for othercode, kern in sortedhash(kerns) do
147 showkernpair(unicode,kern,othercode)
148 end
149 context.par()
150 done = true
151 end
152 end
153 if not done then
154 context("no kern pairs found")
155 context.par()
156 end
157end
158
159function moduledata.fonts.features.showallkerns(specification)
160 specification = interfaces.checkedspecification(specification)
161 local id, cs = fonts.definers.internal(specification,"<module:fonts:features:font>")
162 local tfmdata = fonts.hashes.identifiers[id]
163 local allkerns = collectkerns(tfmdata)
164 local characters = tfmdata.characters
165 local hfactor = tfmdata.parameters.hfactor
166 if next(allkerns) then
167 for first, pairs in sortedhash(allkerns) do
168 context.par()
169 for second, kern in sortedhash(pairs) do
170
171
172
173
174 showkernpair(first,kern*hfactor,second)
175 end
176 context.par()
177 end
178 else
179 context("no kern pairs found")
180 context.par()
181 end
182end
183
184function moduledata.fonts.features.showfeatureset(specification)
185 specification = interfaces.checkedspecification(specification)
186 local name = specification[c_name]
187 if name then
188 local s = fonts.specifiers.contextsetups[name]
189 if s then
190 local t = table.copy(s)
191 t.number = nil
192 if t and next(t) then
193 context.starttabulate { "|T|T|" }
194 for k, v in sortedhash(t) do
195 NC() context(k) NC() context(v == true and v_yes or v == false and v_no or tostring(v)) NC() NR()
196 end
197 context.stoptabulate()
198 end
199 end
200 end
201end
202
203
204
205local function collectligatures(tfmdata)
206 local sequences = tfmdata.resources.sequences
207
208 if not sequences then
209 return
210 end
211
212
213
214 local series = { }
215 local stack = { }
216 local max = 0
217
218 local function add(v)
219 local n = #stack
220 if n > max then
221 max = n
222 end
223 series[#series+1] = { v, unpack(stack) }
224 end
225
226 local function make(tree)
227 for k, v in sortedhash(tree) do
228 if k == "ligature" then
229 add(v)
230 elseif tonumber(v) then
231 insert(stack,k)
232 add(v)
233 remove(stack)
234 else
235 insert(stack,k)
236 make(v)
237 remove(stack)
238 end
239 end
240 end
241
242 for i=1,#sequences do
243 local sequence = sequences[i]
244 if sequence.type == "gsub_ligature" then
245 local steps = sequence.steps
246 for i=1,#steps do
247 local step = steps[i]
248 local coverage = step.coverage
249 if coverage then
250 make(coverage)
251 end
252 end
253 end
254 end
255
256 return series, max
257end
258
259function moduledata.fonts.features.showallligatures(specification)
260 specification = interfaces.checkedspecification(specification)
261 local id, cs = fonts.definers.internal(specification,"<module:fonts:features:font>")
262 local tfmdata = fonts.hashes.identifiers[id]
263 local allligatures,
264 max = collectligatures(tfmdata)
265 local characters = tfmdata.characters
266 local descriptions = tfmdata.descriptions
267 if #allligatures > 0 then
268 context.starttabulate { "|T|" .. string.rep("|",max) .. "|T|T|" }
269 for i=1,#allligatures do
270 local s = allligatures[i]
271 local n = #s
272 local u = s[1]
273 local c = characters[u]
274 local d = descriptions[u]
275 NC()
276 context("%U",u)
277 NC()
278 context("\\setfontid%i\\relax",id)
279 context.char(u)
280 NC()
281 context("\\setfontid%i\\relax",id)
282 for i=2,n do
283 context.char(s[i])
284 NC()
285 end
286 for i=n+1,max do
287 NC()
288 end
289 context(d.name)
290 NC()
291 context(c.tounicode)
292 NC()
293 NR()
294 end
295 context.stoptabulate()
296 else
297 context("no ligatures found")
298 context.par()
299 end
300end
301 |