diff options
-rw-r--r-- | luaotfload-database.lua | 116 | ||||
-rw-r--r-- | luaotfload.dtx | 96 |
2 files changed, 89 insertions, 123 deletions
diff --git a/luaotfload-database.lua b/luaotfload-database.lua index 529cdf3..f78cc67 100644 --- a/luaotfload-database.lua +++ b/luaotfload-database.lua @@ -71,12 +71,15 @@ fonts.definers = fonts.definers or { } local names = fonts.names -names.version = 2.202 -names.data = nil +names.version = 2.203 +names.data = nil --- contains the loaded database +names.lookups = nil --- contains the lookup cache names.path = { - basename = "luaotfload-names.lua", - dir = "", - path = "", + dir = "", --- db and cache directory + basename = "luaotfload-names.lua", --- db file name + path = "", --- full path to db file + lookup_basename = "luaotfload-lookup-cache.lua", --- cache file name + lookup_path = "", --- cache full path } config = config or { } @@ -97,8 +100,9 @@ if caches then if not writable_path then error("Impossible to find a suitable writeable cache...") end - names.path.dir = writable_path - names.path.path = filejoin(writable_path, names.path.basename) + names.path.dir = writable_path + names.path.path = filejoin(writable_path, names.path.basename) + names.path.lookup_path = filejoin(writable_path, names.path.lookup_basename) else --- running as script, inject some dummies caches = { } logs = { report = function () end } @@ -188,12 +192,6 @@ mtx-fonts has in names.tma: --doc]]-- local fontnames_init = function (keep_cache) --- returns dbobj - local request_cache - if keep_cache and names.data and names.data.request_cache then - request_cache = names.data.request_cache - else - request_cache = { } - end return { mappings = { }, status = { }, @@ -206,7 +204,6 @@ local fontnames_init = function (keep_cache) --- returns dbobj basenames = { }, -- fullnames = { }, version = names.version, - request_cache = request_cache, } end @@ -250,11 +247,13 @@ local find_closest local flush_cache local font_fullinfo local load_names +local load_lookups local read_fonts_conf local reload_db local resolve local resolve_cached local save_names +local save_lookups local scan_external_dir local update_names @@ -283,6 +282,20 @@ load_names = function ( ) return data end +--- unit -> dbobj +load_lookups = function ( ) + local foundname, data = load_lua_file(names.path.lookup_path) + if data then + report("both", 1, "cache", + "Lookup cache loaded (%s)", foundname) + else + report("both", 1, "cache", + "No lookup cache, creating empty.") + data = { } + end + return data +end + local fuzzy_limit = 1 --- display closest only local style_synonyms = { set = { } } @@ -428,20 +441,20 @@ resolver, lest we want to worry if we caught all the details. --- 'a -> 'a -> table -> (string * int|boolean * boolean) resolve_cached = function (_, _, specification) - if not names.data then names.data = load_names() end - local request_cache = names.data.request_cache + --if not names.data then names.data = load_names() end + if not names.lookups then names.lookups = load_lookups() end local request = specification.specification - report("log", 4, "cache", "looking for “%s” in cache ...", + report("both", 4, "cache", "looking for “%s” in cache ...", request) - local found = names.data.request_cache[request] + local found = names.lookups[request] --- case 1) cache positive ---------------------------------------- if found then --- replay fields from cache hit report("info", 4, "cache", "found!") return found[1], found[2], true end - report("log", 4, "cache", "not cached; resolving") + report("both", 4, "cache", "not cached; resolving") --- case 2) cache negative ---------------------------------------- --- first we resolve normally ... @@ -449,8 +462,8 @@ resolve_cached = function (_, _, specification) if not success then return filename, subfont, false end --- ... then we add the fields to the cache ... ... local entry = { filename, subfont } - report("log", 4, "cache", "new entry: %s", request) - names.data.request_cache[request] = entry + report("both", 4, "cache", "new entry: %s", request) + names.lookups[request] = entry --- obviously, the updated cache needs to be stored. --- for the moment, we write the entire db to disk @@ -459,8 +472,8 @@ resolve_cached = function (_, _, specification) --- document is compiled (finish_pdffile callback?) --- TODO we should speed up writing by separating --- the cache from the db - report("log", 5, "cache", "saving updated cache") - save_names() + report("both", 5, "cache", "saving updated cache") + save_lookups() return filename, subfont, true end @@ -468,9 +481,10 @@ end Luatex-fonts, the font-loader package luaotfload imports, comes with basic file location facilities (see luatex-fonts-syn.lua). -However, the builtin functionality is too limited to be of more than -basic use, which is why we supply our own resolver that accesses the -font database created by the mkluatexfontdb script. +However, not only does the builtin functionality rely on Context’s font +name database, it is also too limited to be of more than basic use. +For this reason, luaotfload supplies its own resolvers that accesses +the font database created by the luaotfload-tool script. --doc]]-- @@ -684,7 +698,7 @@ end --- resolve() reload_db = function (why, caller, ...) report("both", 1, "db", "reload initiated; reason: “%s”", why) names.data = update_names() - save_names(names.data) + save_names() fonts_reloaded = true return caller(...) end @@ -1389,10 +1403,10 @@ local function scan_os_fonts(fontnames, newfontnames) end flush_cache = function () - if not names.data then names.data = load_names() end - names.data.request_cache = { } + if not names.lookups then names.lookups = load_lookups() end + names.lookups = { } collectgarbage"collect" - return true, names.data + return true, names.lookups end --- dbobj -> bool -> dbobj @@ -1448,13 +1462,47 @@ update_names = function (fontnames, force) return newfontnames end +--- unit -> string +local ensure_names_path = function ( ) + local path = names.path.dir + if not lfsisdir(path) then + dirmkdirs(path) + end + return path +end + +--- The lookup cache is an experimental feature of version 2.2; +--- instead of incorporating it into the database it gets its own +--- file. As we update it after every single addition this saves us +--- quite some time. + +--- unit -> string +save_lookups = function ( ) + ---- this is boilerplate and should be refactored into something + ---- usable by both the db and the cache writers + local lookups = names.lookups + local path = ensure_names_path() + if fileiswritable(path) then + local luaname, lucname = make_name(names.path.lookup_path) + if luaname then + tabletofile(luaname, lookups, true) + if lucname and type(caches.compile) == "function" then + os.remove(lucname) + caches.compile(lookups, luaname, lucname) + report("info", 1, "cache", "Lookup cache saved") + return names.path.lookup_path + end + end + end + report("info", 0, "cache", "Could not write lookup cache") + return nil +end + +--- save_names() is usually called without the argument --- dbobj -> unit save_names = function (fontnames) if not fontnames then fontnames = names.data end - local path = names.path.dir - if not lfs.isdir(path) then - dirmkdirs(path) - end + local path = ensure_names_path() if fileiswritable(path) then local luaname, lucname = make_name(names.path.path) if luaname then diff --git a/luaotfload.dtx b/luaotfload.dtx index e18c205..8f7c8a1 100644 --- a/luaotfload.dtx +++ b/luaotfload.dtx @@ -835,7 +835,7 @@ and the derived files % The complete list is is given in table \ref{table-searchpaths}. % Other paths can be specified by setting the environment variable % \verb+OSFONTDIR+. -% If it is non-empty, then search will be limited to the included +% If it is non-empty, then search will be extended to the included % directories. % % \begin{table}[t] @@ -900,7 +900,7 @@ and the derived files % using the \verb|-i| option (\verb|--info|). % \begin{quote} % \begin{verbatim} -% luaotfload-tool -F --find="Iwona Light Italic" +% luaotfload-tool -i --find="Iwona Light Italic" % \end{verbatim} % \end{quote} % \noindent @@ -1181,6 +1181,7 @@ local luaotfload = luaotfload config = config or { } config.luaotfload = config.luaotfload or { } config.luaotfload.resolver = config.luaotfload.resolver or "normal" +config.luaotfload.definer = config.luaotfload.definer or "patch" --luaotfload.prefer_merge = config.luaotfload.prefer_merge or true luaotfload.module = { @@ -1642,54 +1643,6 @@ end create_callback("luaotfload.patch_font", "simple", dummy_function) % \end{macrocode} -% This is a wrapper for the imported font loader. -% As of 2013, everything it does appear to be redundand, so we won’t use -% it unless somebody points out a cogent reason. -% Nevertheless, it has been adapted to work with the current structure of -% font data objects and will stay here for reference / until breakage is -% reported. -% \emphasis{TODO} -% This one also enables patching fonts. -% The current fontloader apparently comes with a dedicated mechanism for -% that already: enhancers. -% How those work remains to be figured out. -% -% \begin{macrocode} -local define_font_wrapper = function (...) - --- we use “tfmdata” (not “fontdata”) for consistency with the - --- font loader - local tfmdata = fonts.definers.read(...) - if type(tfmdata) == "table" and tfmdata.shared then - local metadata = tfmdata.shared.rawdata.metadata - local mathdata = metadata.math --- do all fonts have this field? - if mathdata then - local mathconstants = { } --- why new hash, not modify in place? - local units_per_em = metadata.units_per_em - local size = tfmdata.size - for k,v in next, mathdata do - --- afaics this is alread taken care of by - --- definers.read - if stringfind(k, "Percent") then - -- keep percent values as is - --print(k,v) - mathconstants[k] = v - else - mathconstants[k] = v / units_per_em * size - end - end - --- for \overwithdelims - --- done by definers.read as well - mathconstants.FractionDelimiterSize = 1.01 * size - --- fontloader has 2.4 × size - mathconstants.FractionDelimiterDisplayStyleSize = 2.39 * size - tfmdata.MathConstants = mathconstants - end - call_callback("luaotfload.patch_font", tfmdata) - end - return tfmdata -end - -% \end{macrocode} % \subsection{\CONTEXT override} % We provide a simplified version of the original font definition % callback. @@ -1716,55 +1669,20 @@ reset_callback("define_font") % % \begin{macrocode} -if luaotfload.font_definer == "old" then - add_to_callback("define_font", - define_font_wrapper, - "luaotfload.define_font", - 1) -elseif luaotfload.font_definer == "generic" then +local font_definer = config.luaotfload.definer + +if font_definer == "generic" then add_to_callback("define_font", fonts.definers.read, "luaotfload.define_font", 1) -elseif luaotfload.font_definer == "patch" then +elseif font_definer == "patch" then add_to_callback("define_font", patch_defined_font, "luaotfload.define_font", 1) end ---[[todo-- ---- The manual promises coercion of the file: lookup if ---- the asked name is enclosed in brackets. ---- A couple things make me doubt that this is the case: ---- ---- 1) there doesn’t appear to be code for these cases ---- 2) the brackets remain part of the file name ---- 3) we still get calls to names.resolve which ---- ignores the “lookup” field of the spec it gets ---- ---- For this reason here is some code that a) coerces ---- file: lookups in these cases and b) strips the brackets ---- from the file name. As we *still* get name: lookups even ---- though this code is active I’ll just leave it here ---- for reference, ineffective as it is. -do - local getspecification, makespecification = - fonts.definers.getspecification, fonts.definers.makespecification - - local analyze = function (specification, size) - local lookup, name, sub, method, detail = getspecification(specification or "") - local filename = stringmatch(name, "^%[(.*)%]$") - if filename then - lookup = "file" --> coerce file: - name = filename --> remove brackets - end - return makespecification(specification, lookup, name, sub, method, detail, size) - end - fonts.definers.analyze = analyze -end ---]]-- - loadmodule"features.lua" --- contains what was “font-ltx” and “font-otc” -- vim:tw=71:sw=4:ts=4:expandtab |