summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--luaotfload-database.lua140
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...")