1if not modules then modules = { } end modules [ ' good-ini ' ] = {
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
9
10
11local type , next = type , next
12local gmatch = string . gmatch
13local sortedhash , insert = table . sortedhash , table . insert
14
15local fonts = fonts
16
17local trace_goodies = false trackers . register ( " fonts.goodies " , function ( v ) trace_goodies = v end )
18local report_goodies = logs . reporter ( " fonts " , " goodies " )
19
20local allocate = utilities . storage . allocate
21local implement = interfaces . implement
22local findfile = resolvers . findfile
23local formatters = string . formatters
24
25local otf = fonts . handlers . otf
26local afm = fonts . handlers . afm
27local tfm = fonts . handlers . tfm
28
29local registerotffeature = otf . features . register
30local registerafmfeature = afm . features . register
31local registertfmfeature = tfm . features . register
32
33local addotffeature = otf . enhancers . addfeature
34
35local fontgoodies = fonts . goodies or { }
36fonts . goodies = fontgoodies
37
38local data = fontgoodies . data or { }
39fontgoodies . data = data
40
41local list = fontgoodies . list or { }
42fontgoodies . list = list
43
44fontgoodies . suffixes = { " lfg " , " lua " }
45
46local contextsetups = fonts . specifiers . contextsetups
47
48function fontgoodies . report ( what , trace , goodies )
49 if trace_goodies or trace then
50 local whatever = goodies [ what ]
51 if whatever then
52 report_goodies ( " goodie %a found in %a " , what , goodies . name )
53 end
54 end
55end
56
57local function locate ( filename )
58 local suffixes = fontgoodies . suffixes
59 for i = 1 , # suffixes do
60 local suffix = suffixes [ i ]
61 local fullname = findfile ( file . addsuffix ( filename , suffix ) )
62 if fullname and fullname ~ = " " then
63 return fullname
64 end
65 end
66end
67
68local function loadgoodies ( filename )
69 local goodies = data [ filename ]
70 if goodies ~ = nil then
71
72 elseif type ( filename ) = = " string " then
73 local fullname = locate ( filename )
74 if not fullname or fullname = = " " then
75 report_goodies ( " goodie file %a is not found (suffixes: % t) " , filename , fontgoodies . suffixes )
76 data [ filename ] = false
77 else
78 goodies = dofile ( fullname ) or false
79 if not goodies then
80 report_goodies ( " goodie file %a is invalid " , fullname )
81 return nil
82 elseif trace_goodies then
83 report_goodies ( " goodie file %a is loaded " , fullname )
84 end
85 goodies . name = goodies . name or " no name "
86 for i = 1 , # list do
87 local g = list [ i ]
88 if trace_goodies then
89 report_goodies ( " handling goodie %a " , g [ 1 ] )
90 end
91 g [ 2 ] ( goodies )
92 end
93 goodies . initialized = true
94 data [ filename ] = goodies
95 end
96 end
97 return goodies
98end
99
100function fontgoodies . register ( name , fnc , prepend )
101 for i = 1 , # list do
102 local g = list [ i ]
103 if g [ 1 ] = = name then
104 g [ 2 ] = fnc
105 return
106 end
107 end
108 local g = { name , fnc }
109 if prepend then
110 insert ( list , g , prepend = = true and 1 or prepend )
111 else
112 insert ( list , g )
113 end
114end
115
116fontgoodies . load = loadgoodies
117
118if implement then
119
120 implement {
121 name = " loadfontgoodies " ,
122 actions = loadgoodies ,
123 arguments = " string " ,
124 overload = true ,
125 }
126
127end
128
129
130
131local function setgoodies ( tfmdata , value )
132 local goodies = tfmdata . goodies
133 if not goodies then
134 goodies = { }
135 tfmdata . goodies = goodies
136 end
137 for filename in gmatch ( value , " [^, ]+ " ) do
138
139 local ok = loadgoodies ( filename )
140 if ok then
141 if trace_goodies then
142 report_goodies ( " assigning goodie %a " , filename )
143 end
144 goodies [ # goodies + 1 ] = ok
145 end
146 end
147end
148
149
150
151local function flattenedfeatures ( t , tt )
152
153 local tt = tt or { }
154 for i = 1 , # t do
155 local ti = t [ i ]
156 local ty = type ( ti )
157 if ty = = " table " then
158 flattenedfeatures ( ti , tt )
159 elseif ty = = " string " then
160 local set = contextsetups [ ti ]
161 if set then
162 for k , v in next , set do
163 if k ~ = " number " then
164 tt [ k ] = v or nil
165 end
166 end
167 else
168
169 end
170 elseif tt [ ti ] = = nil then
171 tt [ ti ] = true
172 end
173 end
174 for k , v in next , t do
175 if type ( k ) ~ = " number " then
176 if type ( v ) = = " table " then
177 flattenedfeatures ( v , tt )
178 elseif tt [ k ] = = nil then
179 tt [ k ] = v
180 end
181 end
182 end
183 return tt
184end
185
186
187
188local function prepare_features ( goodies , name , set )
189 if set then
190 local ff = flattenedfeatures ( set )
191 local fullname = goodies . name . . " :: " . . name
192 local n , s = fonts . specifiers . presetcontext ( fullname , " " , ff )
193 goodies . featuresets [ name ] = s
194 if trace_goodies then
195 report_goodies ( " feature set %a gets number %a and name %a " , name , n , fullname )
196 end
197 return n
198 end
199end
200
201fontgoodies . prepare_features = prepare_features
202
203local function initialize ( goodies )
204 local featuresets = goodies . featuresets
205 if featuresets then
206 if trace_goodies then
207 report_goodies ( " checking featuresets in %a " , goodies . name )
208 end
209 for name , set in next , featuresets do
210 prepare_features ( goodies , name , set )
211 end
212 end
213end
214
215fontgoodies . register ( " featureset " , initialize )
216
217local function setfeatureset ( tfmdata , set , features )
218 local goodies = tfmdata . goodies
219 if goodies then
220 local properties = tfmdata . properties
221 local what
222 for i = 1 , # goodies do
223
224 local g = goodies [ i ]
225 what = g . featuresets and g . featuresets [ set ] or what
226 end
227 if what then
228 for feature , value in next , what do
229 if features [ feature ] = = nil then
230 features [ feature ] = value
231 end
232 end
233 properties . mode = what . mode or properties . mode
234 end
235 end
236end
237
238
239
240function fontgoodies . registerpostprocessor ( tfmdata , f , prepend )
241 local postprocessors = tfmdata . postprocessors
242 if not postprocessors then
243 tfmdata . postprocessors = { f }
244 elseif prepend then
245 insert ( postprocessors , f , prepend = = true and 1 or prepend )
246 else
247 insert ( postprocessors , f )
248 end
249end
250
251local function setpostprocessor ( tfmdata , processor )
252 local goodies = tfmdata . goodies
253 if goodies and type ( processor ) = = " string " then
254 local found = { }
255 local asked = utilities . parsers . settings_to_array ( processor )
256 for i = 1 , # goodies do
257 local g = goodies [ i ]
258 local p = g . postprocessors
259 if p then
260 for i = 1 , # asked do
261 local a = asked [ i ]
262 local f = p [ a ]
263 if type ( f ) = = " function " then
264 found [ a ] = f
265 end
266 end
267 end
268 end
269 local postprocessors = tfmdata . postprocessors or { }
270 for i = 1 , # asked do
271 local a = asked [ i ]
272 local f = found [ a ]
273 if f then
274 postprocessors [ # postprocessors + 1 ] = f
275 end
276 end
277 if # postprocessors > 0 then
278 tfmdata . postprocessors = postprocessors
279 end
280 end
281end
282
283local function setextrafeatures ( tfmdata )
284 local goodies = tfmdata . goodies
285 if goodies then
286 for i = 1 , # goodies do
287 local g = goodies [ i ]
288 local f = g . features
289 if f then
290 local rawdata = tfmdata . shared . rawdata
291 local done = { }
292
293 for i = 1 , # f do
294 local specification = f [ i ]
295 local feature = specification . name
296 if feature then
297 addotffeature ( rawdata , feature , specification )
298 registerotffeature {
299 name = feature ,
300 description = formatters [ " extra: %s " ] ( feature )
301 }
302 end
303 done [ i ] = true
304 end
305
306 for feature , specification in sortedhash ( f ) do
307 if not done [ feature ] then
308 feature = specification . name or feature
309 specification . name = feature
310 addotffeature ( rawdata , feature , specification )
311 registerotffeature {
312 name = feature ,
313 description = formatters [ " extra: %s " ] ( feature )
314 }
315 end
316 end
317 end
318 end
319 end
320end
321
322local function setextensions ( tfmdata )
323 local goodies = tfmdata . goodies
324 if goodies then
325 for i = 1 , # goodies do
326 local g = goodies [ i ]
327 local e = g . extensions
328 if e then
329 local goodie = g . name or " unknown "
330 for i = 1 , # e do
331 local name = " extension- " . . i
332
333 otf . enhancers . addfeature ( tfmdata . shared . rawdata , name , e [ i ] )
334 end
335 end
336 end
337 end
338end
339
340
341
342local goodies_specification = {
343 name = " goodies " ,
344 description = " goodies on top of built in features " ,
345 initializers = {
346 position = 1 ,
347 base = setgoodies ,
348 node = setgoodies ,
349 }
350}
351
352registerotffeature ( goodies_specification )
353registerafmfeature ( goodies_specification )
354registertfmfeature ( goodies_specification )
355
356
357
358registerotffeature {
359 name = " extrafeatures " ,
360 description = " extra features " ,
361 default = true ,
362 initializers = {
363 position = 2 ,
364 base = setextrafeatures ,
365 node = setextrafeatures ,
366 }
367}
368
369registerotffeature {
370 name = " extensions " ,
371 description = " extensions to features " ,
372 default = true ,
373 initializers = {
374 position = 2 ,
375 base = setextensions ,
376 node = setextensions ,
377 }
378}
379
380registerotffeature {
381 name = " featureset " ,
382 description = " goodie feature set " ,
383 initializers = {
384 position = 3 ,
385 base = setfeatureset ,
386 node = setfeatureset ,
387 }
388}
389
390registerotffeature {
391 name = " postprocessor " ,
392 description = " goodie postprocessor " ,
393 initializers = {
394 base = setpostprocessor ,
395 node = setpostprocessor ,
396 }
397}
398 |