diff options
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua')
-rw-r--r-- | Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua | 605 |
1 files changed, 340 insertions, 265 deletions
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua index 099c256dde8..367723be841 100644 --- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua +++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua @@ -1,5 +1,5 @@ if not modules then modules = { } end modules ['luaotfload-database'] = { - version = "2.5", + version = "2.6", comment = "companion to luaotfload-main.lua", author = "Khaled Hosny, Elie Roux, Philipp Gesang", copyright = "Luaotfload Development Team", @@ -39,13 +39,8 @@ if not modules then modules = { } end modules ['luaotfload-database'] = { local lpeg = require "lpeg" local P, Cc, lpegmatch = lpeg.P, lpeg.Cc, lpeg.match -local parsers = luaotfload.parsers -local read_fonts_conf = parsers.read_fonts_conf -local stripslashes = parsers.stripslashes -local splitcomma = parsers.splitcomma - local log = luaotfload.log -local report = log.report +local logreport = log and log.report or print -- overriden later on local report_status = log.names_status local report_status_start = log.names_status_start local report_status_stop = log.names_status_stop @@ -119,19 +114,10 @@ local tablefastcopy = table.fastcopy local tabletofile = table.tofile local tabletohash = table.tohash local tableserialize = table.serialize ---- the font loader namespace is “fonts”, same as in Context ---- we need to put some fallbacks into place for when running ---- as a script -fonts = fonts or { } -fonts.names = fonts.names or { } -fonts.definers = fonts.definers or { } - -local names = fonts.names +local names = fonts and fonts.names or { } + local name_index = nil --> upvalue for names.data local lookup_cache = nil --> for names.lookups -names.version = 2.51 -names.data = nil --- contains the loaded database -names.lookups = nil --- contains the lookup cache --- string -> (string * string) local make_luanames = function (path) @@ -363,7 +349,7 @@ local initialize_namedata = function (formats, created) status = { }, -- was: status; map abspath -> mapping mappings = { }, -- TODO: check if still necessary after rewrite names = { }, --- files = { }, -- created later + files = { }, -- created later meta = { created = created or now, formats = formats, @@ -454,22 +440,19 @@ end --- define locals in scope local access_font_index local collect_families -local font_file_lookup local find_closest local flush_lookup_cache local generate_filedata local get_font_filter local group_modifiers -local load_lookups local load_names +local lookup_font_name local getmetadata local order_design_sizes local ot_fullinfo local read_blacklist local reload_db -local resolve_cached -local resolve_fullpath -local resolve_name +local lookup_fullpath local save_lookups local save_names local set_font_filter @@ -482,18 +465,18 @@ local fonts_reloaded = false --- limit output when approximate font matching (luaotfload-tool -F) local fuzzy_limit = 1 --- display closest only ---- bool? -> dbobj -load_names = function (dry_run) +--- bool? -> -> bool? -> dbobj option +load_names = function (dry_run, no_rebuild) local starttime = osgettimeofday () local foundname, data = load_lua_file (config.luaotfload.paths.index_path_lua) if data then - report ("log", 0, "db", - "Font names database loaded from %s", foundname) - report ("term", 3, "db", - "Font names database loaded from %s", foundname) - report ("info", 3, "db", "Loading took %0.f ms.", - 1000 * (osgettimeofday () - starttime)) + logreport ("log", 0, "db", + "Font names database loaded from %s", foundname) + logreport ("term", 3, "db", + "Font names database loaded from %s", foundname) + logreport ("info", 3, "db", "Loading took %0.f ms.", + 1000 * (osgettimeofday () - starttime)) local db_version, names_version if data.meta then @@ -506,27 +489,32 @@ load_names = function (dry_run) end names_version = names.version if db_version ~= names_version then - report ("both", 0, "db", - [[Version mismatch; expected %4.3f, got %4.3f.]], - names_version, db_version) + logreport ("both", 0, "db", + [[Version mismatch; expected %4.3f, got %4.3f.]], + names_version, db_version) if not fonts_reloaded then - report ("both", 0, "db", [[Force rebuild.]]) + logreport ("both", 0, "db", [[Force rebuild.]]) data = update_names ({ }, true, false) if not data then - report ("both", 0, "db", - "Database creation unsuccessful.") + logreport ("both", 0, "db", + "Database creation unsuccessful.") end end end else - report ("both", 0, "db", - [[Font names database not found, generating new one.]]) - report ("both", 0, "db", - [[This can take several minutes; please be patient.]]) + if no_rebuild == true then + logreport ("both", 2, "db", + [[Database does not exist, skipping rebuild though.]]) + return false + end + logreport ("both", 0, "db", + [[Font names database not found, generating new one.]]) + logreport ("both", 0, "db", + [[This can take several minutes; please be patient.]]) data = update_names (initialize_namedata (get_font_filter ()), nil, dry_run) if not data then - report ("both", 0, "db", "Database creation unsuccessful.") + logreport ("both", 0, "db", "Database creation unsuccessful.") end end return data @@ -545,20 +533,24 @@ access_font_index = function () end getmetadata = function () - if not name_index then name_index = load_names() end - return tablefastcopy (name_index.meta) + if not name_index then + name_index = load_names (false, true) + if name_index then return tablefastcopy (name_index.meta) end + end + return false end --- unit -> unit +local load_lookups load_lookups = function ( ) local foundname, data = load_lua_file(config.luaotfload.paths.lookup_path_lua) if data then - report("log", 0, "cache", "Lookup cache loaded from %s.", foundname) - report("term", 3, "cache", - "Lookup cache loaded from %s.", foundname) + logreport ("log", 0, "cache", "Lookup cache loaded from %s.", foundname) + logreport ("term", 3, "cache", + "Lookup cache loaded from %s.", foundname) else - report("both", 1, "cache", - "No lookup cache, creating empty.") + logreport ("both", 1, "cache", + "No lookup cache, creating empty.") data = { } end lookup_cache = data @@ -630,7 +622,7 @@ end --[[doc-- - font_file_lookup -- The ``file:`` are ultimately delegated here. + lookup_font_file -- The ``file:`` are ultimately delegated here. The lookups are kind of a blunt instrument since they try locating the file using every conceivable method, which is quite inefficient. Nevertheless, resolving files that way is rarely the @@ -639,7 +631,8 @@ end --doc]]-- --- string -> string * string * bool -font_file_lookup = function (filename) +local lookup_font_file +lookup_font_file = function (filename) local found = lookup_filename (filename) if not found then @@ -659,7 +652,7 @@ font_file_lookup = function (filename) if not fonts_reloaded and config.luaotfload.db.update_live == true then return reload_db (stringformat ("File not found: %s.", filename), - font_file_lookup, + lookup_font_file, filename) end return filename, nil, false @@ -707,7 +700,7 @@ font managment we have to check both the system path and the texmf. --doc]]-- local verify_font_file = function (basename) - local path = resolve_fullpath (basename) + local path = lookup_fullpath (basename) if path and lfsisfile(path) then return true end @@ -740,7 +733,7 @@ Idk what the “spec” resolver is for. spec: name, sub resolved, sub, name, forced [*] name: contains both the name resolver from luatex-fonts and - resolve_name() below + lookup_font_name () below From my reading of font-def.lua, what a resolver does is basically rewrite the “name” field of the specification record @@ -769,46 +762,48 @@ local hash_request = function (specification) end --- 'a -> 'a -> table -> (string * int|boolean * boolean) -resolve_cached = function (specification) +local lookup_font_name_cached +lookup_font_name_cached = function (specification) if not lookup_cache then load_lookups () end local request = hash_request(specification) - report("both", 4, "cache", "Looking for %q in cache ...", - request) + logreport ("both", 4, "cache", "Looking for %q in cache ...", + request) local found = lookup_cache [request] --- case 1) cache positive ---------------------------------------- if found then --- replay fields from cache hit - report("info", 4, "cache", "Found!") + logreport ("info", 4, "cache", "Found!") local basename = found[1] --- check the presence of the file in case it’s been removed local success = verify_font_file (basename) if success == true then return basename, found[2], true end - report("both", 4, "cache", "Cached file not found; resolving again.") + logreport ("both", 4, "cache", + "Cached file not found; resolving again.") else - report("both", 4, "cache", "Not cached; resolving.") + logreport ("both", 4, "cache", "Not cached; resolving.") end --- case 2) cache negative ---------------------------------------- --- first we resolve normally ... - local filename, subfont = resolve_name (specification) + local filename, subfont = lookup_font_name (specification) if not filename then return nil, nil end --- ... then we add the fields to the cache ... ... local entry = { filename, subfont } - report("both", 4, "cache", "New entry: %s.", request) + logreport ("both", 4, "cache", "New entry: %s.", request) lookup_cache [request] = entry --- obviously, the updated cache needs to be stored. --- TODO this should trigger a save only once the --- document is compiled (finish_pdffile callback?) - report("both", 5, "cache", "Saving updated cache.") + logreport ("both", 5, "cache", "Saving updated cache.") local success = save_lookups () if not success then --- sad, but not critical - report("both", 0, "cache", "Error writing cache.") + logreport ("both", 0, "cache", "Error writing cache.") end return filename, subfont end @@ -927,13 +922,13 @@ end --[[doc-- - resolve_familyname -- Query the families table for an entry + lookup_familyname -- Query the families table for an entry matching the specification. The parameters “name” and “style” are pre-sanitized. --doc]]-- --- spec -> string -> string -> int -> string * int -local resolve_familyname = function (specification, name, style, askedsize) +local lookup_familyname = function (specification, name, style, askedsize) local families = name_index.families local mappings = name_index.mappings local candidates = nil @@ -965,12 +960,12 @@ local resolve_familyname = function (specification, name, style, askedsize) if not success then return nil, nil end - report ("info", 2, "db", "Match found: %s(%d).", - resolved, subfont or 0) + logreport ("info", 2, "db", "Match found: %s(%d).", + resolved, subfont or 0) return resolved, subfont end -local resolve_fontname = function (specification, name, style) +local lookup_fontname = function (specification, name, style) local mappings = name_index.mappings local fallback = nil local lastresort = nil @@ -1013,7 +1008,7 @@ end --[[doc-- - resolve_name -- Perform a name: lookup. This first queries the + lookup_font_name -- Perform a name: lookup. This first queries the font families table and, if there is no match for the spec, the font names table. The return value is a pair consisting of the file name and the @@ -1051,7 +1046,7 @@ end multiple design sizes to a given font/style combination, we put a workaround in place that chooses that unmarked version. - The first return value of “resolve_name” is the file name of the + The first return value of “lookup_font_name” is the file name of the requested font (string). It can be passed to the fullname resolver get_font_file(). The second value is either “false” or an integer indicating the @@ -1060,7 +1055,7 @@ end --doc]]-- --- table -> string * (int | bool) -resolve_name = function (specification) +lookup_font_name = function (specification) local resolved, subfont if not name_index then name_index = load_names () end local name = sanitize_fontname (specification.name) @@ -1078,28 +1073,28 @@ resolve_name = function (specification) end end - resolved, subfont = resolve_familyname (specification, - name, - style, - askedsize) + resolved, subfont = lookup_familyname (specification, + name, + style, + askedsize) if not resolved then - resolved, subfont = resolve_fontname (specification, - name, - style) + resolved, subfont = lookup_fontname (specification, + name, + style) end if not resolved then if not fonts_reloaded and config.luaotfload.db.update_live == true then return reload_db (stringformat ("Font %s not found.", specification.name or "<?>"), - resolve_name, + lookup_font_name, specification) end end return resolved, subfont end -resolve_fullpath = function (fontname, ext) --- getfilename() +lookup_fullpath = function (fontname, ext) --- getfilename() if not name_index then name_index = load_names () end local files = name_index.files local basedata = files.base @@ -1132,9 +1127,9 @@ reload_db = function (why, caller, ...) local namedata = name_index local formats = tableconcat (namedata.meta.formats, ",") - report ("both", 0, "db", - "Reload initiated (formats: %s); reason: %q.", - formats, why) + logreport ("both", 0, "db", + "Reload initiated (formats: %s); reason: %q.", + formats, why) set_font_filter (formats) namedata = update_names (namedata, false, false) @@ -1145,7 +1140,7 @@ reload_db = function (why, caller, ...) return caller (...) end - report ("both", 0, "db", "Database update unsuccessful.") + logreport ("both", 0, "db", "Database update unsuccessful.") end --- string -> string -> int @@ -1176,6 +1171,25 @@ local iterative_levenshtein = function (s1, s2) return costs[len2]--- lower right has the distance end +--- string list -> string list +local delete_dupes = function (lst) + local n0 = #lst + if n0 == 0 then return lst end + tablesort (lst) + local ret = { } + local last + for i = 1, n0 do + local cur = lst[i] + if cur ~= last then + last = cur + ret[#ret + 1] = cur + end + end + logreport (false, 8, "query", + "Removed %d duplicate names.", n0 - #ret) + return ret +end + --- string -> int -> bool find_closest = function (name, limit) local name = sanitize_fontname (name) @@ -1221,6 +1235,7 @@ find_closest = function (name, limit) else --- append namelst[#namelst+1] = fullname end + by_distance[dist] = namelst end @@ -1229,16 +1244,16 @@ find_closest = function (name, limit) if n_distances > 0 then --- got some data tablesort(distances) limit = mathmin(n_distances, limit) - report(false, 1, "query", - "Displaying %d distance levels.", limit) + logreport (false, 1, "query", + "Displaying %d distance levels.", limit) for i = 1, limit do local dist = distances[i] - local namelst = by_distance[dist] - report(false, 0, "query", - "Distance from \"%s\": %s\n " - .. tableconcat (namelst, "\n "), - name, dist) + local namelst = delete_dupes (by_distance[dist]) + logreport (false, 0, "query", + "Distance from \"%s\": %s\n " + .. tableconcat (namelst, "\n "), + name, dist) end return true @@ -1265,7 +1280,7 @@ local load_font_file = function (filename, subfont) local rawfont, _msg = fontloaderopen (filename, subfont) --local rawfont, _msg = fontloaderinfo (filename, subfont) if not rawfont then - report ("log", 1, "db", "ERROR: failed to open %s.", filename) + logreport ("log", 1, "db", "ERROR: failed to open %s.", filename) return end return rawfont @@ -1308,8 +1323,8 @@ local get_english_names = function (metadata) end -- no (English) names table, probably a broken font - report("both", 3, "db", - "%s: missing or broken English names table.", basename) + logreport ("both", 3, "db", + "%s: missing or broken English names table.", basename) return { fontname = metadata.fontname, fullname = metadata.fullname, } end @@ -1335,9 +1350,9 @@ local get_raw_info = function (metadata, basename) --- Broken names table, e.g. avkv.ttf with UTF-16 strings; --- we put some dummies in place like the fontloader --- (font-otf.lua) does. - report("both", 3, "db", - "%s has invalid postscript font names, using dummies.", - basename) + logreport ("both", 3, "db", + "%s has invalid postscript font names, using dummies.", + basename) fontname = "bad-fontname-" .. basename fullname = "bad-fullname-" .. basename end @@ -1611,7 +1626,7 @@ local compare_timestamps = function (fullname, if targetentrystatus ~= nil and targetentrystatus.timestamp == targettimestamp then - report ("log", 3, "db", "Font %q already read.", fullname) + logreport ("log", 3, "db", "Font %q already read.", fullname) return false end @@ -1633,7 +1648,7 @@ local compare_timestamps = function (fullname, targetentrystatus.index [targetindex + 1] = location end - report ("log", 3, "db", "Font %q already indexed.", fullname) + logreport ("log", 3, "db", "Font %q already indexed.", fullname) return false end @@ -1713,8 +1728,8 @@ local read_font_names = function (fullname, --- 1) skip if blacklisted if names.blacklist[fullname] or names.blacklist[basename] then - report("log", 2, "db", - "Ignoring blacklisted font %q.", fullname) + logreport ("log", 2, "db", + "Ignoring blacklisted font %q.", fullname) return false end @@ -1737,8 +1752,8 @@ local read_font_names = function (fullname, local loader = loaders [format] --- ot_fullinfo, t1_fullinfo if not loader then - report ("both", 0, "db", - "Unknown format: %q, skipping.", format) + logreport ("both", 0, "db", + "Unknown format: %q, skipping.", format) return false end @@ -1747,8 +1762,8 @@ local read_font_names = function (fullname, local info = fontloaderinfo (fullname) if not info then - report ("log", 1, "db", - "Failed to read basic information from %q", basename) + logreport ("log", 1, "db", + "Failed to read basic information from %q", basename) return false end @@ -1820,11 +1835,7 @@ do end end -fonts.path_normalize = path_normalize - -names.blacklist = { } - -local blacklist = names.blacklist +local blacklist = { } local p_blacklist --- prefixes of dirs --- string list -> string list @@ -1853,8 +1864,8 @@ local create_blacklist = function (blacklist, whitelist) local result = { } local dirs = { } - report("info", 2, "db", "Blacklisting %d files and directories.", - #blacklist) + logreport ("info", 2, "db", "Blacklisting %d files and directories.", + #blacklist) for i=1, #blacklist do local entry = blacklist[i] if lfsisdir(entry) then @@ -1864,7 +1875,7 @@ local create_blacklist = function (blacklist, whitelist) end end - report("info", 2, "db", "Whitelisting %d files.", #whitelist) + logreport ("info", 2, "db", "Whitelisting %d files.", #whitelist) for i=1, #whitelist do result[whitelist[i]] = nil end @@ -1906,9 +1917,9 @@ read_blacklist = function () if first_chr == "%" or stringis_empty(line) then -- comment or empty line elseif first_chr == "-" then - report ("both", 3, "db", - "Whitelisted file %q via %q.", - line, path) + logreport ("both", 3, "db", + "Whitelisted file %q via %q.", + line, path) whitelist[#whitelist+1] = stringsub(line, 2, -1) else local cmt = stringfind(line, "%%") @@ -1916,9 +1927,9 @@ read_blacklist = function () line = stringsub(line, 1, cmt - 1) end line = stringstrip(line) - report ("both", 3, "db", - "Blacklisted file %q via %q.", - line, path) + logreport ("both", 3, "db", + "Blacklisted file %q via %q.", + line, path) blacklist[#blacklist+1] = line end end @@ -1930,9 +1941,8 @@ end local p_font_filter do - local current_formats = { } - local extension_pattern = function (list) + if type (list) ~= "table" or #list == 0 then return P(-1) end local pat for i=#list, 1, -1 do local e = list[i] @@ -1949,12 +1959,17 @@ do --- small helper to adjust the font filter pattern (--formats --- option) + local current_formats = { } + set_font_filter = function (formats) if not formats or type (formats) ~= "string" then return end + if splitcomma == nil then + splitcomma = luaotfload.parsers and luaotfload.parsers.splitcomma + end if stringsub (formats, 1, 1) == "+" then -- add formats = lpegmatch (splitcomma, stringsub (formats, 2)) if formats then @@ -2115,24 +2130,24 @@ end --- string -> string -> string * string list local collect_font_filenames_dir = function (dirname, location) if lpegmatch (p_blacklist, dirname) then - report ("both", 4, "db", - "Skipping blacklisted directory %s.", dirname) + logreport ("both", 4, "db", + "Skipping blacklisted directory %s.", dirname) --- ignore return { } end local found = find_font_files (dirname, location ~= "texmf" and location ~= "local") if not found then - report ("both", 4, "db", - "No such directory: %q; skipping.", dirname) + logreport ("both", 4, "db", + "No such directory: %q; skipping.", dirname) return { } end local nfound = #found local files = { } - report ("both", 4, "db", - "%d font files detected in %s.", - nfound, dirname) + logreport ("both", 4, "db", + "%d font files detected in %s.", + nfound, dirname) for j = 1, nfound do local fullname = found[j] files[#files + 1] = { path_normalize (fullname), location } @@ -2140,23 +2155,29 @@ local collect_font_filenames_dir = function (dirname, location) return files end - --- string list -> string list local filter_out_pwd = function (dirs) local result = { } + if stripslashes == nil then + stripslashes = luaotfload.parsers and luaotfload.parsers.stripslashes + end local pwd = path_normalize (lpegmatch (stripslashes, lfscurrentdir ())) for i = 1, #dirs do --- better safe than sorry local dir = path_normalize (lpegmatch (stripslashes, dirs[i])) - if not (dir == "." or dir == pwd) then + if dir == "." or dir == pwd then + logreport ("both", 3, "db", + "Path “%s” matches $PWD (“%s”), skipping.", + dir, pwd) + else result[#result+1] = dir end end return result end -local path_separator = ostype == "windows" and ";" or ":" +local path_separator = os.type == "windows" and ";" or ":" --[[doc-- @@ -2176,14 +2197,14 @@ local collect_font_filenames_texmf = function () local osfontdir = kpseexpand_path "$OSFONTDIR" if stringis_empty (osfontdir) then - report ("info", 1, "db", "Scanning TEXMF for fonts...") + logreport ("both", 1, "db", "Scanning TEXMF for fonts...") else - report ("info", 1, "db", "Scanning TEXMF and $OSFONTDIR for fonts...") + logreport ("both", 1, "db", "Scanning TEXMF and $OSFONTDIR for fonts...") if log.get_loglevel () > 3 then local osdirs = filesplitpath (osfontdir) - report ("info", 0, "db", "$OSFONTDIR has %d entries:", #osdirs) + logreport ("both", 0, "db", "$OSFONTDIR has %d entries:", #osdirs) for i = 1, #osdirs do - report ("info", 0, "db", "[%d] %s", i, osdirs[i]) + logreport ("both", 0, "db", "[%d] %s", i, osdirs[i]) end end end @@ -2197,14 +2218,14 @@ local collect_font_filenames_texmf = function () end local tasks = filter_out_pwd (filesplitpath (fontdirs)) - report ("info", 3, "db", - "Initiating scan of %d directories.", #tasks) + logreport ("both", 3, "db", + "Initiating scan of %d directories.", #tasks) local files = { } for _, dir in next, tasks do files = tableappend (files, collect_font_filenames_dir (dir, "texmf")) end - report ("term", 3, "db", "Collected %d files.", #files) + logreport ("both", 3, "db", "Collected %d files.", #files) return files end @@ -2225,7 +2246,10 @@ local function get_os_dirs () "/usr/local/etc/fonts/fonts.conf", "/etc/fonts/fonts.conf", } - local os_dirs = read_fonts_conf(fonts_conves, find_files) + if not luaotfload.parsers then + logreport ("log", 0, "db", "Fatal: no fonts.conf parser.") + end + local os_dirs = luaotfload.parsers.read_fonts_conf(fonts_conves, find_files) return os_dirs end return {} @@ -2233,6 +2257,33 @@ end --[[doc-- + count_removed -- Count paths that do not exist in the file system. + +--doc]]-- + +--- string list -> size_t +local count_removed = function (files) + if not files or not files.full then + logreport ("log", 4, "db", "Empty file store; no data to work with.") + return 0 + end + local old = files.full + logreport ("log", 4, "db", "Checking removed files.") + local nrem = 0 + local nold = #old + for i = 1, nold do + local f = old[i] + if not kpsereadable_file (f) then + logreport ("log", 2, "db", + "File %s does not exist in file system.") + nrem = nrem + 1 + end + end + return nrem +end + +--[[doc-- + retrieve_namedata -- Scan the list of collected fonts and populate the list of namedata. @@ -2245,13 +2296,13 @@ end --doc]]-- ---- string * string list -> dbobj -> dbobj -> bool? -> int +--- string * string list -> dbobj -> dbobj -> bool? -> int * int local retrieve_namedata = function (files, currentnames, targetnames, dry_run) local nfiles = #files local nnew = 0 - report ("info", 1, "db", "Scanning %d collected font files ...", nfiles) + logreport ("info", 1, "db", "Scanning %d collected font files ...", nfiles) local bylocation = { texmf = { 0, 0 } , ["local"] = { 0, 0 } @@ -2264,12 +2315,12 @@ local retrieve_namedata = function (files, currentnames, targetnames, dry_run) count[1] = count[1] + 1 if dry_run == true then local truncated = truncate_string (fullname, 43) - report ("log", 2, "db", "Would have been loading %s.", fullname) + logreport ("log", 2, "db", "Would have been loading %s.", fullname) report_status ("term", "db", "Would have been loading %s", truncated) --- skip the read_font_names part else local truncated = truncate_string (fullname, 32) - report ("log", 2, "db", "Loading font %s.", fullname) + logreport ("log", 2, "db", "Loading font %s.", fullname) report_status ("term", "db", "Loading font %s", truncated) local new = read_font_names (fullname, currentnames, targetnames, location) @@ -2281,8 +2332,8 @@ local retrieve_namedata = function (files, currentnames, targetnames, dry_run) end report_status_stop ("term", "db", "Scanned %d files, %d new.", nfiles, nnew) for location, count in next, bylocation do - report ("term", 4, "db", " * %s: %d files, %d new", - location, count[1], count[2]) + logreport ("term", 4, "db", " * %s: %d files, %d new", + location, count[1], count[2]) end return nnew end @@ -2291,15 +2342,15 @@ end local collect_font_filenames_system = function () local n_scanned, n_new = 0, 0 - report ("info", 1, "db", "Scanning system fonts...") - report ("info", 2, "db", - "Searching in static system directories...") + logreport ("info", 1, "db", "Scanning system fonts...") + logreport ("info", 2, "db", + "Searching in static system directories...") local files = { } for _, dir in next, get_os_dirs () do tableappend (files, collect_font_filenames_dir (dir, "system")) end - report ("term", 3, "db", "Collected %d files.", #files) + logreport ("term", 3, "db", "Collected %d files.", #files) return files end @@ -2325,28 +2376,25 @@ end --- unit -> string * string list local collect_font_filenames_local = function () local pwd = lfscurrentdir () - report ("both", 1, "db", "Scanning for fonts in $PWD (%q) ...", pwd) + logreport ("both", 1, "db", "Scanning for fonts in $PWD (%q) ...", pwd) local files = collect_font_filenames_dir (pwd, "local") local nfiles = #files if nfiles > 0 then targetnames.meta["local"] = true --- prevent saving to disk - report ("term", 1, "db", "Found %d files.", pwd) + logreport ("term", 1, "db", "Found %d files.", pwd) else - report ("term", 1, "db", - "Couldn’t find a thing here. What a waste.", pwd) + logreport ("term", 1, "db", + "Couldn’t find a thing here. What a waste.", pwd) end - report ("term", 3, "db", "Collected %d files.", #files) + logreport ("term", 3, "db", "Collected %d files.", #files) return files end ---- dbobj -> dbobj -> int * int - --- fontentry list -> filemap - generate_filedata = function (mappings) - report ("both", 2, "db", "Creating filename map.") + logreport ("both", 2, "db", "Creating filename map.") local nmappings = #mappings @@ -2375,7 +2423,6 @@ generate_filedata = function (mappings) for index = 1, nmappings do local entry = mappings [index] - local filedata = entry.file local format local location @@ -2409,10 +2456,10 @@ generate_filedata = function (mappings) if inbase then local present = inbase [basename] if present then - report ("both", 4, "db", - "Conflicting basename: %q already indexed \z - in category %s, ignoring.", - barename, location) + logreport ("both", 4, "db", + "Conflicting basename: %q already indexed \z + in category %s, ignoring.", + barename, location) conflicts.basenames = conflicts.basenames + 1 --- track conflicts per font @@ -2439,10 +2486,10 @@ generate_filedata = function (mappings) if inbare then local present = inbare [barename] if present then - report ("both", 4, "db", - "Conflicting barename: %q already indexed \z - in category %s/%s, ignoring.", - barename, location, format) + logreport ("both", 4, "db", + "Conflicting barename: %q already indexed \z + in category %s/%s, ignoring.", + barename, location, format) conflicts.barenames = conflicts.barenames + 1 --- track conflicts per font @@ -2465,7 +2512,7 @@ generate_filedata = function (mappings) --- 3) add to fullpath map full [index] = fullpath - end + end --- mapping traversal return files end @@ -2624,7 +2671,7 @@ end collect_families = function (mappings) - report ("info", 2, "db", "Analyzing families.") + logreport ("info", 2, "db", "Analyzing families.") local families = { ["local"] = { }, @@ -2720,7 +2767,7 @@ local style_categories = { "r", "b", "i", "bi" } local bold_categories = { "b", "bi" } group_modifiers = function (mappings, families) - report ("info", 2, "db", "Analyzing shapes, weights, and styles.") + logreport ("info", 2, "db", "Analyzing shapes, weights, and styles.") for location, location_data in next, families do for format, format_data in next, location_data do for familyname, collected in next, format_data do @@ -2819,7 +2866,7 @@ end order_design_sizes = function (families) - report ("info", 2, "db", "Ordering design sizes.") + logreport ("info", 2, "db", "Ordering design sizes.") for location, data in next, families do for format, data in next, data do @@ -2841,10 +2888,10 @@ end --doc]]-- ---- unit -> string * bool list +--- unit -> string * string list local collect_font_filenames = function () - report ("info", 4, "db", "Scanning the filesystem for font files.") + logreport ("info", 4, "db", "Scanning the filesystem for font files.") local filenames = { } local bisect = config.luaotfload.misc.bisect @@ -2874,7 +2921,7 @@ end --- int -> string local nth_font_filename = function (n) - report ("info", 4, "db", "Picking font file no. %d.", n) + logreport ("info", 4, "db", "Picking font file no. %d.", n) if not p_blacklist then read_blacklist () end @@ -2889,7 +2936,7 @@ end --doc]]-- local font_slice = function (lo, hi) - report ("info", 4, "db", "Retrieving font files nos. %d--%d.", lo, hi) + logreport ("info", 4, "db", "Retrieving font files nos. %d--%d.", lo, hi) if not p_blacklist then read_blacklist () end @@ -2911,7 +2958,7 @@ end --- unit -> int local count_font_files = function () - report ("info", 4, "db", "Counting font files.") + logreport ("info", 4, "db", "Counting font files.") if not p_blacklist then read_blacklist () end @@ -3037,31 +3084,31 @@ local collect_statistics = function (mappings) itemlist = tableconcat (itemlist, ", ") end - report ("both", 0, "db", - " · %4d × %s.", - freq, itemlist) + logreport ("both", 0, "db", + " · %4d × %s.", + freq, itemlist) end end - report ("both", 0, "", "~~~~ font index statistics ~~~~") - report ("both", 0, "db", - " · Collected %d fonts (%d names) in %d families.", - #mappings, n_fullname, n_family) + logreport ("both", 0, "", "~~~~ font index statistics ~~~~") + logreport ("both", 0, "db", + " · Collected %d fonts (%d names) in %d families.", + #mappings, n_fullname, n_family) pprint_top (families, 4, true) - report ("both", 0, "db", - " · %d different “subfamily” kinds.", - setsize (subfamily)) + logreport ("both", 0, "db", + " · %d different “subfamily” kinds.", + setsize (subfamily)) pprint_top (subfamily, 4) - report ("both", 0, "db", - " · %d different “prefmodifiers” kinds.", - setsize (prefmodifiers)) + logreport ("both", 0, "db", + " · %d different “prefmodifiers” kinds.", + setsize (prefmodifiers)) pprint_top (prefmodifiers, 4) - report ("both", 0, "db", - " · %d different “fontstyle_name” kinds.", - setsize (fontstyle_name)) + logreport ("both", 0, "db", + " · %d different “fontstyle_name” kinds.", + setsize (fontstyle_name)) pprint_top (fontstyle_name, 4) end @@ -3090,10 +3137,12 @@ end --- dbobj? -> bool? -> bool? -> dbobj update_names = function (currentnames, force, dry_run) local targetnames + local n_new = 0 + local n_rem = 0 local conf = config.luaotfload if conf.run.live ~= false and conf.db.update_live == false then - report ("info", 2, "db", "Skipping database update.") + logreport ("info", 2, "db", "Skipping database update.") --- skip all db updates return currentnames or name_index end @@ -3105,15 +3154,16 @@ update_names = function (currentnames, force, dry_run) - “targetnames” is the final table to return - force is whether we rebuild it from scratch or not ]] - report("both", 1, "db", "Updating the font names database" - .. (force and " forcefully." or ".")) + logreport ("both", 1, "db", + "Updating the font names database" + .. (force and " forcefully." or ".")) if config.luaotfload.db.skip_read == true then --- the difference to a “dry run” is that we don’t search --- for font files entirely. we also ignore the “force” --- parameter since it concerns only the font files. - report ("info", 2, "db", - "Ignoring font files, reusing old data.") + logreport ("info", 2, "db", + "Ignoring font files, reusing old data.") currentnames = load_names (false) targetnames = currentnames else @@ -3124,8 +3174,9 @@ update_names = function (currentnames, force, dry_run) currentnames = load_names (dry_run) end if currentnames.meta.version ~= names.version then - report ("both", 1, "db", "No font names database or old " - .. "one found; generating new one.") + logreport ("both", 1, "db", + "No font names database or old \z + one found; generating new one.") currentnames = initialize_namedata (get_font_filter ()) end end @@ -3141,13 +3192,16 @@ update_names = function (currentnames, force, dry_run) --- pass 2: read font files (normal case) or reuse information --- present in index + n_rem = count_removed (currentnames.files) + n_new = retrieve_namedata (font_filenames, currentnames, targetnames, dry_run) - report ("info", 3, "db", - "Found %d font files; %d new entries.", - #font_filenames, n_new) + + logreport ("info", 3, "db", + "Found %d font files; %d new, %d stale entries.", + #font_filenames, n_new, n_rem) end --- pass 3 (optional): collect some stats about the raw font info @@ -3173,27 +3227,27 @@ update_names = function (currentnames, force, dry_run) --- pass 7: order design size tables targetnames.families = order_design_sizes (targetnames.families) - - report ("info", 3, "db", - "Rebuilt in %0.f ms.", - 1000 * (osgettimeofday () - starttime)) + logreport ("info", 3, "db", + "Rebuilt in %0.f ms.", + 1000 * (osgettimeofday () - starttime)) name_index = targetnames if dry_run ~= true then - if n_new == 0 then - report ("info", 2, "db", "No new fonts found, skip saving to disk.") + if n_new + n_rem == 0 then + logreport ("info", 2, "db", + "No new or removed fonts, skip saving to disk.") else local success, reason = save_names () if not success then - report ("both", 0, "db", - "Failed to save database to disk: %s", - reason) + logreport ("both", 0, "db", + "Failed to save database to disk: %s", + reason) end end if flush_lookup_cache () and save_lookups () then - report ("both", 2, "cache", "Lookup cache emptied.") + logreport ("both", 2, "cache", "Lookup cache emptied.") return targetnames end end @@ -3210,18 +3264,18 @@ save_lookups = function ( ) caches.compile (lookup_cache, luaname, lucname) --- double check ... if lfsisfile (luaname) and lfsisfile (lucname) then - report ("both", 3, "cache", "Lookup cache saved.") + logreport ("both", 3, "cache", "Lookup cache saved.") return true end - report ("info", 0, "cache", "Could not compile lookup cache.") + logreport ("info", 0, "cache", "Could not compile lookup cache.") return false end - report ("info", 0, "cache", "Lookup cache file not writable.") + logreport ("info", 0, "cache", "Lookup cache file not writable.") if not fileiswritable (luaname) then - report ("info", 0, "cache", "Failed to write %s.", luaname) + logreport ("info", 0, "cache", "Failed to write %s.", luaname) end if not fileiswritable (lucname) then - report ("info", 0, "cache", "Failed to write %s.", lucname) + logreport ("info", 0, "cache", "Failed to write %s.", lucname) end return false end @@ -3250,33 +3304,33 @@ save_names = function (currentnames) tabletofile (luaname, currentnames, true) caches.compile (currentnames, luaname, lucname) end - report ("info", 2, "db", "Font index saved at ...") + logreport ("info", 2, "db", "Font index saved at ...") local success = false if lfsisfile (luaname) then - report ("info", 2, "db", "Text: " .. luaname) + logreport ("info", 2, "db", "Text: " .. luaname) success = true end if lfsisfile (gzname) then - report ("info", 2, "db", "Gzip: " .. gzname) + logreport ("info", 2, "db", "Gzip: " .. gzname) success = true end if lfsisfile (lucname) then - report ("info", 2, "db", "Byte: " .. lucname) + logreport ("info", 2, "db", "Byte: " .. lucname) success = true end if success then return true else - report ("info", 0, "db", "Could not compile font index.") + logreport ("info", 0, "db", "Could not compile font index.") return false end end - report ("info", 0, "db", "Index file not writable") + logreport ("info", 0, "db", "Index file not writable") if not fileiswritable (luaname) then - report ("info", 0, "db", "Failed to write %s.", luaname) + logreport ("info", 0, "db", "Failed to write %s.", luaname) end if not fileiswritable (lucname) then - report ("info", 0, "db", "Failed to write %s.", lucname) + logreport ("info", 0, "db", "Failed to write %s.", lucname) end return false end @@ -3290,7 +3344,7 @@ end --- string -> string -> string list -> string list -> string list -> unit local print_cache = function (category, path, luanames, lucnames, rest) local report_indeed = function (...) - report("info", 0, "cache", ...) + logreport ("info", 0, "cache", ...) end report_indeed("Luaotfload cache: %s", category) report_indeed("location: %s", path) @@ -3302,15 +3356,15 @@ end --- string -> string -> string list -> bool -> bool local purge_from_cache = function (category, path, list, all) - report("info", 1, "cache", "Luaotfload cache: %s %s", - (all and "erase" or "purge"), category) - report("info", 1, "cache", "location: %s",path) + logreport ("info", 1, "cache", "Luaotfload cache: %s %s", + (all and "erase" or "purge"), category) + logreport ("info", 1, "cache", "location: %s", path) local n = 0 for i=1,#list do local filename = list[i] if stringfind(filename,"luatex%-cache") then -- safeguard if all then - report("info", 5, "cache", "Removing %s.", filename) + logreport ("info", 5, "cache", "Removing %s.", filename) osremove(filename) n = n + 1 else @@ -3319,7 +3373,7 @@ local purge_from_cache = function (category, path, list, all) local checkname = file.replacesuffix( filename, "lua", "luc") if lfsisfile(checkname) then - report("info", 5, "cache", "Removing %s.", filename) + logreport ("info", 5, "cache", "Removing %s.", filename) osremove(filename) n = n + 1 end @@ -3327,7 +3381,7 @@ local purge_from_cache = function (category, path, list, all) end end end - report("info", 1, "cache", "Removed lua files : %i", n) + logreport ("info", 1, "cache", "Removed lua files : %i", n) return true end @@ -3360,7 +3414,7 @@ end local getwritablecachepath = function ( ) --- fonts.handlers.otf doesn’t exist outside a Luatex run, --- so we have to improvise - local writable = getwritablepath (config.luaotfload.paths.cache_dir) + local writable = getwritablepath (config.luaotfload.paths.cache_dir, "") if writable then return writable end @@ -3404,7 +3458,7 @@ local erase_cache = function ( ) end local separator = function ( ) - report("info", 0, string.rep("-", 67)) + logreport ("info", 0, string.rep("-", 67)) end --- unit -> unit @@ -3433,34 +3487,55 @@ end --- export functionality to the namespace “fonts.names” ----------------------------------------------------------------------- -names.set_font_filter = set_font_filter -names.flush_lookup_cache = flush_lookup_cache -names.save_lookups = save_lookups -names.load = load_names -names.access_font_index = access_font_index -names.data = function () return name_index end -names.save = save_names -names.update = update_names -names.font_file_lookup = font_file_lookup -names.read_blacklist = read_blacklist -names.sanitize_fontname = sanitize_fontname -names.getfilename = resolve_fullpath -names.getmetadata = getmetadata -names.set_location_precedence = set_location_precedence -names.count_font_files = count_font_files -names.nth_font_filename = nth_font_filename -names.font_slice = font_slice -names.resolve_cached = resolve_cached -names.resolve_name = resolve_name - ---- font cache -names.purge_cache = purge_cache -names.erase_cache = erase_cache -names.show_cache = show_cache - -names.find_closest = find_closest - --- for testing purpose -names.read_fonts_conf = read_fonts_conf +local export = { + set_font_filter = set_font_filter, + flush_lookup_cache = flush_lookup_cache, + save_lookups = save_lookups, + load = load_names, + access_font_index = access_font_index, + data = function () return name_index end, + save = save_names, + update = update_names, + lookup_font_file = lookup_font_file, + lookup_font_name = lookup_font_name, + lookup_font_name_cached = lookup_font_name_cached, + getfilename = lookup_fullpath, + lookup_fullpath = lookup_fullpath, + read_blacklist = read_blacklist, + sanitize_fontname = sanitize_fontname, + getmetadata = getmetadata, + set_location_precedence = set_location_precedence, + count_font_files = count_font_files, + nth_font_filename = nth_font_filename, + font_slice = font_slice, + --- font cache + purge_cache = purge_cache, + erase_cache = erase_cache, + show_cache = show_cache, + find_closest = find_closest, + -- for testing purpose +} + +return { + init = function () + --- the font loader namespace is “fonts”, same as in Context + --- we need to put some fallbacks into place for when running + --- as a script + if not fonts then return false end + logreport = luaotfload.log.report + local fonts = fonts + fonts.names = fonts.names or names + fonts.formats = fonts.formats or { } + fonts.definers = fonts.definers or { resolvers = { } } + + names.blacklist = blacklist + names.version = 2.6 + names.data = nil --- contains the loaded database + names.lookups = nil --- contains the lookup cache + + for sym, ref in next, export do names[sym] = ref end + return true + end +} -- vim:tw=71:sw=4:ts=4:expandtab |