diff options
-rw-r--r-- | luaotfload-database.lua | 140 |
1 files changed, 45 insertions, 95 deletions
diff --git a/luaotfload-database.lua b/luaotfload-database.lua index 4980766..e23902a 100644 --- a/luaotfload-database.lua +++ b/luaotfload-database.lua @@ -21,6 +21,7 @@ local tonumber = tonumber local fontloaderinfo = fontloader.info local iolines = io.lines local ioopen = io.open +local iopopen = io.popen local kpseexpand_path = kpse.expand_path local kpseexpand_var = kpse.expand_var local kpselookup = kpse.lookup @@ -234,7 +235,6 @@ local find_closest local flush_cache local font_fullinfo local load_names -local read_fonts_conf local reload_db local resolve local save_names @@ -1141,6 +1141,29 @@ local function scan_texmf_fonts(fontnames, newfontnames) return n_scanned, n_new end +--- fc-cat outputs every directory it finds fonts in, +--- so we have to remove all subdirectories from the +--- list. + +--- dir list -> dir list +local collapse_paths = function (dir_lst) + tablesort(dir_lst) + local last = dir_lst[1] + local res = { last } + local ndirs = #dir_lst + if ndirs > 1 then + for i=2, ndirs do + local dir = dir_lst[i] + if stringsub(dir, 1, #last) ~= last then + --- new prefix + res[#res+1] = dir + last = dir + end + end + end + return res +end + --[[ For the OS fonts, there are several options: - if OSFONTDIR is set (which is the case under windows by default but @@ -1148,99 +1171,32 @@ end in the scan_texmf_fonts. - if not: - under Windows and Mac OSX, we take a look at some hardcoded directories - - under Unix, we read /etc/fonts/fonts.conf and read the directories in it + - under Unix, we parse the output of “fc-cat -v” This means that if you have fonts in fancy directories, you need to set them in OSFONTDIR. ]] ---- (string -> tab -> tab -> tab) -read_fonts_conf = function (path, results, passed_paths) - --[[ - This function parses /etc/fonts/fonts.conf and returns all the dir - it finds. The code is minimal, please report any error it may - generate. - - TODO fonts.conf are some kind of XML so in theory the following - is totally inappropriate. Maybe a future version of the - lualibs will include the lxml-* files from Context so we - can write something presentable instead. - ]] - local fh = ioopen(path) - passed_paths[#passed_paths+1] = path - passed_paths_set = tabletohash(passed_paths, true) - if not fh then - report("log", 2, "db", "cannot open file %s", path) - return results - end - local incomments = false - for line in fh:lines() do - while line and line ~= "" do - -- spaghetti code... hmmm... - if incomments then - local tmp = stringfind(line, '-->') --- wtf? - if tmp then - incomments = false - line = stringsub(line, tmp+3) - else - line = nil - end - else - local tmp = stringfind(line, '<!--') - local newline = line - if tmp then - -- for the analysis, we take everything that is before the - -- comment sign - newline = stringsub(line, 1, tmp-1) - -- and we loop again with the comment - incomments = true - line = stringsub(line, tmp+4) - else - -- if there is no comment start, the block after that will - -- end the analysis, we exit the while loop - line = nil - end - for dir in stringgmatch(newline, '<dir>([^<]+)</dir>') do - -- now we need to replace ~ by kpse.expand_path('~') - if stringsub(dir, 1, 1) == '~' then - dir = filejoin(kpseexpand_path('~'), stringsub(dir, 2)) - end - -- we exclude paths with texmf in them, as they should be - -- found anyway - if not stringfind(dir, 'texmf') then - results[#results+1] = dir - end - end - for include in stringgmatch(newline, '<include[^<]*>([^<]+)</include>') do - -- include here can be four things: a directory or a file, - -- in absolute or relative path. - if stringsub(include, 1, 1) == '~' then - include = filejoin(kpseexpand_path('~'),stringsub(include, 2)) - -- First if the path is relative, we make it absolute: - elseif not lfs.isfile(include) and not lfs.isdir(include) then - include = filejoin(file.dirname(path), include) - end - if lfs.isfile(include) - and kpsereadable_file(include) - and not passed_paths_set[include] - then - -- maybe we should prevent loops here? - -- we exclude path with texmf in them, as they should - -- be found otherwise - read_fonts_conf(include, results, passed_paths) - elseif lfs.isdir(include) then - for _,f in next, dirglob(filejoin(include, "*.conf")) do - if not passed_paths_set[f] then - read_fonts_conf(f, results, passed_paths) - end - end - end - end - end +--[[doc-- +Instead of processing the fontconfig configuration files with a +haphazarad XML parser, we scan the output of fc-cache for search paths +and use these. This way we don’t need to resolve possible included +files. +--doc]]-- +local get_fontconfig_paths = function ( ) + local fc_cat_cmd = "fc-cat -v 2> /dev/null" + local res = { } + local chan = assert(iopopen(fc_cat_cmd, "r"), + "cannot read from pipe") + local nlines = 0 + for line in chan:lines() do + nlines = nlines + 1 + if stringsub(line, 1, 11) == "Directory: " then + res[#res+1] = string.explode(line, " ")[2] .. "/" end end - fh:close() - return results + chan:close() + return collapse_paths(res) end -- for testing purpose @@ -1259,13 +1215,7 @@ local function get_os_dirs() local windir = os.getenv("WINDIR") return { filejoin(windir, 'Fonts') } else - local passed_paths = {} - local os_dirs = {} - for _,p in next, {"/usr/local/etc/fonts/fonts.conf", "/etc/fonts/fonts.conf"} do - if lfs.isfile(p) then - read_fonts_conf(p, os_dirs, passed_paths) - end - end + local os_dirs = get_fontconfig_paths() return os_dirs end return {} @@ -1275,7 +1225,7 @@ local function scan_os_fonts(fontnames, newfontnames) local n_scanned, n_new = 0, 0 --[[ This function scans the OS fonts through - - fontcache for Unix (reads the fonts.conf file and scans the directories) + - fontcache for Unix (runs fc-cat -v and scans the directories) - a static set of directories for Windows and MacOSX ]] report("info", 2, "db", "Scanning OS fonts...") |