luatex-fonts.lua /size: 15 Kb    last modification: 2025-02-21 11:03
1if not modules then modules = { } end modules ['luatex-fonts'] = {
2    version   = 1.001,
3    comment   = "companion to luatex-fonts.tex",
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-- A merged file is generated with:
10--
11--   mtxrun --script package --merge --stripcontext luatex-fonts.lua
12--
13-- A needed resource file is made by:
14--
15--   mtxrun --script context luatex-basics-prepare.tex
16--
17-- A font (generic) database is created with:
18--
19--   mtxrun --script font --reload --simple
20
21-- The following code isolates the generic context code from already defined or to be defined
22-- namespaces. This is the reference loader for plain tex. This generic code is also used in
23-- luaotfload which is a low level lualatex opentype font loader but somehow has gotten a bit
24-- too generic name / prefix, originally set up and maintained by Khaled Hosny. Later that
25-- set of derived files was maintained by a larger team lead by Philipp Gesang, but afaik
26-- maintainance moved to latex team and the wrapper code in the meantime likely differs quite
27-- a bit from what was started with. So, issues with luaotfload shoudl be reported to the latex
28-- folk. If you suspect somethign wong in these files, it makes sense then to first check if
29-- context has the same issue:
30--
31-- mtxrun --script context          contextfile  (mkxl aka lmtx)
32--
33-- mtxrun --script context --luatex contextfile  (mkiv)
34--
35-- mtxrun --script plain   --make
36-- mtxrun --script plain            plaintexfile (tex)
37--
38-- We only backport from context lmtx (luametatex) to context mkiv (luatex) if needed and to
39-- this file set (generic) when we think it makes sense. Keep in mind that not all features in
40-- context are supported in generic.
41--
42-- The code base is rather stable now, especially if you stay away from the non generic code. All
43-- relevant data is organized in tables within the main table of a font instance. There are a few
44-- places where in context other code is plugged in, but this does not affect the core code. Users
45-- can (given that their macro package provides this option) access the font data (characters,
46-- descriptions, properties, parameters, etc) of this main table. The documentation is part of
47-- context. There is also a manual for the helper libraries (maintained as part of the cld manuals).
48--
49-- Future versions will probably have some more specific context code removed, like tracing and
50-- obscure hooks, so that we have a more efficient version (and less files too). So, don't depend
51-- too much on low level code that is meant for context as it can change without notice. We might
52-- also add more helper code here, but that depends to what extend metatex (sidetrack of context)
53-- evolves into a low level layer (depends on time, as usual).
54
55-- The code here is the same as in context version 2015.09.11 (in the meantime 2024.06.14) but the
56-- rendering in context can be different from generic. This can be a side effect of additional
57-- callbacks, additional features and interferences between mechanisms between macro packages. We
58-- use the rendering in context and luatex-plain as reference for issues (see above for running).
59
60-- I might as well remove some code that is not used in generic (or not used by generic users)
61-- like color fonts (emoji etc) and variable fonts thereby making the code base smaller. However
62-- I might keep ity just for the sake of testing the plain loader that comes with context. We'll
63-- see.
64
65-- As a side effect of cleaning up some context code, like code meant for older version of luatex,
66-- as well replacing code for more recent versions (post 1.12) there can be changes in the modules
67-- used here, especially where we check for 'context' being used. Hopefully there are no side
68-- effects. Because we can now assume that the the glyph injection callback is in recent texlive
69-- installations, the variable font code is now enabled in the generic version that comes with
70-- context (as unofficial bonus; when it was demonstrated at bachotex 2017 it worked ok for the
71-- generic loader but was kind of disabled there as no one needs it). I waited with adding the
72-- pending code for type 3 support till texlive 2020 was fozen but it will be in texlive 2021 (it
73-- is already tested in context back in 2019 and I wanted to release it at the canceled BT 2020
74-- meeting, so I consider it stable, read: this is it). To what extend and when I will adapt the
75-- generic code (for color support) to that is yet to be decided because in context we do things
76-- a bit differently. We anyway have to wait a few years till that callback is omnipresent so I'm
77-- not in that much of a hurry. (There will be a TB article about it first and after that I will
78-- add some examples to the manual.)
79--
80-- Fonts evolve over time. So if something doesn't work one might want to test older or newer
81-- version. We don't implement heuristics with regards to script/language combinations so that is
82-- often the first to test: what langauge, script, features are available and set. When the backend
83-- is involved macro package dependencies creep in. We've seen reports on something not working as
84-- that was just a matter configuration and not a bug. But we're always willing to fix real bugs,
85-- for which we need the font files then.
86
87utf = utf or (unicode and unicode.utf8) or { }
88
89-- We have some (global) hooks (for latex). Maybe I'll use this signal to disable some of the
90-- more tricky features like variable fonts and emoji (because afaik latex uses hb for that).
91
92if not non_generic_context then
93    non_generic_context = { }
94end
95
96if not non_generic_context.luatex_fonts then
97    non_generic_context.luatex_fonts = {
98     -- load_before  = nil,
99     -- load_after   = nil,
100     -- skip_loading = nil,
101    }
102end
103
104if not generic_context then
105    generic_context  = { }
106end
107
108if not generic_context.push_namespaces then
109
110    function generic_context.push_namespaces()
111     -- logs.report("system","push namespace")
112        local normalglobal = { }
113        for k, v in next, _G do
114            normalglobal[k] = v
115        end
116        return normalglobal
117    end
118
119    function generic_context.pop_namespaces(normalglobal,isolate)
120        if normalglobal then
121         -- logs.report("system","pop namespace")
122            for k, v in next, _G do
123                if not normalglobal[k] then
124                    generic_context[k] = v
125                    if isolate then
126                        _G[k] = nil
127                    end
128                end
129            end
130            for k, v in next, normalglobal do
131                _G[k] = v
132            end
133            -- just to be sure:
134            setmetatable(generic_context,_G)
135        else
136            logs.report("system","fatal error: invalid pop of generic_context")
137            os.exit()
138        end
139    end
140
141end
142
143local whatever = generic_context.push_namespaces()
144
145-- We keep track of load time by storing the current time. That way we cannot be accused
146-- of slowing down loading too much. Anyhow, there is no reason for this library to perform
147-- slower in any other package as it does in context.
148--
149-- Please don't update to this version without proper testing. It might be that this version
150-- lags behind stock context and the only formal release takes place around tex live code
151-- freeze.
152
153local starttime = os.gettimeofday()
154
155-- As we don't use the context file searching, we need to initialize the kpse library. As the
156-- progname can be anything we will temporary switch to the context namespace if needed. Just
157-- adding the context paths to the path specification is somewhat faster.
158--
159-- Now, with lua 5.2 being used we might create a special ENV for this.
160
161-- kpse.set_program_name("luatex")
162
163-- One can define texio.reporter as alternative terminal/log writer. That's as far
164-- as I want to go with this.
165
166local ctxkpse = nil
167local verbose = true
168
169if not logs or not logs.report then
170    if not logs then
171        logs = { }
172    end
173    function logs.report(c,f,...)
174        local r = texio.reporter or texio.write_nl
175        if f then
176            r(c .. " : " .. string.format(f,...))
177        else
178            r("")
179        end
180    end
181end
182
183local function loadmodule(name,continue)
184    local foundname = kpse.find_file(name,"tex") or ""
185    if not foundname then
186        if not ctxkpse then
187            ctxkpse = kpse.new("luatex","context")
188        end
189        foundname = ctxkpse:find_file(name,"tex") or ""
190    end
191    if foundname == "" then
192        if not continue then
193            logs.report("system","unable to locate file '%s'",name)
194            os.exit()
195        end
196    else
197        if verbose then
198            logs.report("system","loading '%s'",foundname) -- no file.basename yet
199        end
200        dofile(foundname)
201    end
202end
203
204if non_generic_context.luatex_fonts.load_before then
205    loadmodule(non_generic_context.luatex_fonts.load_before,true)
206end
207
208if non_generic_context.luatex_fonts.skip_loading ~= true then
209
210    loadmodule('luatex-fonts-merged.lua',true)
211
212    if fonts then
213
214        if not fonts._merge_loaded_message_done_ then
215            texio.write_nl("log", "!")
216            texio.write_nl("log", "! I am using the merged version of 'luatex-fonts.lua' here. If")
217            texio.write_nl("log", "! you run into problems or experience unexpected behaviour, and")
218            texio.write_nl("log", "! if you have ConTeXt installed you can try to delete the file")
219            texio.write_nl("log", "! 'luatex-font-merged.lua' as I might then use the possibly")
220            texio.write_nl("log", "! updated libraries. The merged version is not supported as it")
221            texio.write_nl("log", "! is a frozen instance. Problems can be reported to the ConTeXt")
222            texio.write_nl("log", "! mailing list.")
223            texio.write_nl("log", "!")
224        end
225
226        fonts._merge_loaded_message_done_ = true
227
228    else
229
230        -- The following helpers are a bit overkill but I don't want to mess up
231        -- context code for the sake of general generality. Around version 1.0
232        -- there will be an official api defined.
233        --
234        -- So, I will strip these libraries and see what is really needed so that
235        -- we don't have this overhead in the generic modules. The next section
236        -- is only there for the packager, so stick to using luatex-fonts with
237        -- luatex-fonts-merged.lua and forget about the rest. The following list
238        -- might change without prior notice (for instance because we shuffled
239        -- code around).
240
241        loadmodule("l-lua.lua")
242        loadmodule("l-lpeg.lua")
243        loadmodule("l-function.lua")
244        loadmodule("l-string.lua")
245        loadmodule("l-table.lua")
246        loadmodule("l-io.lua")
247        loadmodule("l-file.lua")
248        loadmodule("l-boolean.lua")
249        loadmodule("l-math.lua")
250
251        -- A few slightly higher level support modules:
252
253        loadmodule("util-str.lua") -- future versions can ship without this one
254        loadmodule("util-fil.lua") -- future versions can ship without this one
255
256        -- The following modules contain code that is either not used at all
257        -- outside context or will fail when enabled due to lack of other
258        -- modules.
259
260        -- First we load a few helper modules. This is about the miminum needed
261        -- to let the font modules do their work. Don't depend on their functions
262        -- as we might strip them in future versions of this generic variant.
263
264        loadmodule('luatex-basics-gen.lua')
265        loadmodule('data-con.lua')
266
267        -- We do need some basic node support. The code in there is not for
268        -- general use as it might change.
269
270        loadmodule('luatex-basics-nod.lua')
271
272        -- We ship a resources needed for font handling (more might end up here).
273
274        loadmodule('luatex-basics-chr.lua')
275
276        -- Now come the font modules that deal with traditional tex fonts as well
277        -- as open type fonts.
278        --
279        -- The font database file (if used at all) must be put someplace visible
280        -- for kpse and is not shared with context. The mtx-fonts script can be
281        -- used to generate this file (using the --reload --force --simple option).
282
283        loadmodule('font-ini.lua')
284        loadmodule('luatex-fonts-mis.lua')
285        loadmodule('font-con.lua')
286        loadmodule('luatex-fonts-enc.lua')
287        loadmodule('font-cid.lua')
288        loadmodule('font-map.lua')
289
290        -- We use a bit simpler database because using the context one demands
291        -- loading more helper code and although it is more flexible (more ways
292        -- to resolve and so) it will never be uses in plain/latex anyway, so
293        -- let's stick to a simple approach.
294
295        loadmodule('luatex-fonts-syn.lua')
296
297        -- We need some helpers.
298
299        loadmodule('font-vfc.lua')
300
301        -- This is the bulk of opentype code. The color and variable font support (as for
302        -- emoji) can (and might) actually go away here because it has never been used
303        -- outside context so in retrospect there was no need for it being generic.
304
305        loadmodule('font-otr.lua')
306        loadmodule('font-cff.lua')
307        loadmodule('font-ttf.lua')
308        loadmodule('font-dsp.lua')
309        loadmodule('font-oti.lua')
310        loadmodule('font-ott.lua')
311        loadmodule('font-otl.lua')
312        loadmodule('font-oto.lua')
313        loadmodule('font-otj.lua')
314        loadmodule('font-oup.lua')
315        loadmodule('font-ota.lua')
316        loadmodule('font-ots.lua')
317        loadmodule('font-otc.lua')
318        loadmodule('font-osd.lua')
319        loadmodule('font-ocl.lua')
320
321        -- The code for type one fonts.
322
323        loadmodule('font-onr.lua')
324        loadmodule('font-one.lua')
325        loadmodule('font-afk.lua')
326
327        -- And for traditional TeX fonts.
328
329        loadmodule('luatex-fonts-tfm.lua')
330
331        -- Some common code.
332
333        loadmodule('font-lua.lua')
334        loadmodule('font-def.lua')
335        loadmodule('font-shp.lua')
336
337        -- We support xetex compatible specifiers (plain/latex only).
338
339        loadmodule('luatex-fonts-def.lua') -- was font-xtx.lua
340
341        -- Here come some additional features.
342
343        loadmodule('luatex-fonts-ext.lua')
344        loadmodule('font-imp-tex.lua')
345        loadmodule('font-imp-ligatures.lua')
346        loadmodule('font-imp-italics.lua')
347        loadmodule('font-imp-effects.lua')
348        loadmodule('luatex-fonts-lig.lua')
349
350        -- We need to plug into a callback and the following module implements the
351        -- handlers. Actual plugging in happens later.
352
353        loadmodule('luatex-fonts-gbn.lua')
354
355    end
356
357end
358
359if non_generic_context.luatex_fonts.load_after then
360    loadmodule(non_generic_context.luatex_fonts.load_after,true)
361end
362
363resolvers.loadmodule = loadmodule
364
365-- In order to deal with the fonts we need to initialize some callbacks. One can overload them later
366-- on if needed. First a bit of abstraction.
367
368generic_context.callback_ligaturing           = false
369generic_context.callback_kerning              = false
370generic_context.callback_pre_linebreak_filter = nodes.simple_font_handler
371generic_context.callback_hpack_filter         = nodes.simple_font_handler
372generic_context.callback_define_font          = fonts.definers.read
373
374-- The next ones can be done at a different moment if needed. You can create a generic_context namespace
375-- and set no_callbacks_yet to true, load this module, and enable the callbacks later. So, there is really
376-- *no* need to create a alternative for luatex-fonts.lua and luatex-fonts-merged.lua: just load this one
377-- and overload if needed.
378
379if not generic_context.no_callbacks_yet then
380
381    callback.register('ligaturing',           generic_context.callback_ligaturing)
382    callback.register('kerning',              generic_context.callback_kerning)
383    callback.register('pre_linebreak_filter', generic_context.callback_pre_linebreak_filter)
384    callback.register('hpack_filter',         generic_context.callback_hpack_filter)
385    callback.register('define_font' ,         generic_context.callback_define_font)
386
387end
388
389-- We're done.
390
391logs.report("system","luatex-fonts.lua loaded in %0.3f seconds", os.gettimeofday()-starttime)
392
393generic_context.pop_namespaces(whatever)
394