summaryrefslogtreecommitdiff
path: root/luaotfload-database.lua
diff options
context:
space:
mode:
authorPhilipp Gesang <phg42.2a@gmail.com>2013-07-10 09:44:59 -0700
committerPhilipp Gesang <phg42.2a@gmail.com>2013-07-10 09:44:59 -0700
commit36abb3e8cf8d2d24bf5cfb770cdba2731de655c5 (patch)
tree91b5dc821ed404eb9618ae69f0a8d5481326aa46 /luaotfload-database.lua
parent9bb68613ca57d6486906317f0b5f832ea4deceea (diff)
parentc005b2dc2c002b970536ae3acf9532e1f673b478 (diff)
downloadluaotfload-36abb3e8cf8d2d24bf5cfb770cdba2731de655c5.tar.gz
Merge pull request #110 from phi-gamma/master
v2.3a
Diffstat (limited to 'luaotfload-database.lua')
-rw-r--r--luaotfload-database.lua184
1 files changed, 105 insertions, 79 deletions
diff --git a/luaotfload-database.lua b/luaotfload-database.lua
index c0aadaf..e0b977b 100644
--- a/luaotfload-database.lua
+++ b/luaotfload-database.lua
@@ -1,5 +1,5 @@
if not modules then modules = { } end modules ['luaotfload-database'] = {
- version = 2.3,
+ version = "2.3a",
comment = "companion to luaotfload.lua",
author = "Khaled Hosny, Elie Roux, Philipp Gesang",
copyright = "Luaotfload Development Team",
@@ -27,6 +27,7 @@ local require = require
local tonumber = tonumber
local unpack = table.unpack
+
local fontloaderinfo = fontloader.info
local fontloaderopen = fontloader.open
local iolines = io.lines
@@ -40,6 +41,7 @@ local lfsattributes = lfs.attributes
local lfsdir = lfs.dir
local mathabs = math.abs
local mathmin = math.min
+local osremove = os.remove
local stringfind = string.find
local stringformat = string.format
local stringgmatch = string.gmatch
@@ -52,8 +54,8 @@ local tablesort = table.sort
local texiowrite_nl = texio.write_nl
local utf8gsub = unicode.utf8.gsub
local utf8lower = unicode.utf8.lower
-
--- these come from Lualibs/Context
+local getwritablepath = caches.getwritablepath
local filebasename = file.basename
local filecollapsepath = file.collapsepath or file.collapse_path
local filedirname = file.dirname
@@ -95,27 +97,57 @@ end
names.version = 2.207
names.data = nil --- contains the loaded database
names.lookups = nil --- contains the lookup cache
-names.path = {
- dir = "", --- db and cache directory
- basename = config.luaotfload.names_file
+
+names.path = { index = { }, lookups = { } }
+names.path.globals = {
+ prefix = "", --- writable_path/names_dir
+ names_dir = config.luaotfload.names_dir or "names",
+ index_file = config.luaotfload.index_file
or "luaotfload-names.lua",
- path = "", --- full path to db file
- lookup_basename = "luaotfload-lookup-cache.lua", --- cache file name
- lookup_path = "", --- cache full path
+ lookups_file = "luaotfload-lookup-cache.lua",
}
--- We use the cache.* of ConTeXt (see luat-basics-gen), we can
--- use it safely (all checks and directory creations are already done). It
--- uses TEXMFCACHE or TEXMFVAR as starting points.
-local writable_path
+--- string -> (string * string)
+local make_luanames = function (path)
+ return filereplacesuffix(path, "lua"),
+ filereplacesuffix(path, "luc")
+end
+
+local report = logs.names_report
+
+--[[doc--
+ We use the functions in the cache.* namespace that come with the
+ fontloader (see luat-basics-gen). it’s safe to use for the most part
+ since most checks and directory creations are already done. It
+ uses TEXMFCACHE or TEXMFVAR as starting points.
+
+ There is one quirk, though: ``getwritablepath()`` will always
+ assume that files in subdirectories of the cache tree are writable.
+ It gives no feedback at all if it fails to open a file in write
+ mode. This may cause trouble when the index or lookup cache were
+ created by different user.
+--doc]]--
+
if caches then
- writable_path = caches.getwritablepath "names"
- if not writable_path then
- luaotfload.error("Impossible to find a suitable writeable cache...")
+ local globals = names.path.globals
+ local names_dir = globals.names_dir
+
+ prefix = getwritablepath (names_dir, "")
+ if not prefix then
+ luaotfload.error
+ ("Impossible to find a suitable writeable cache...")
+ else
+ report ("log", 0, "db",
+ "root cache directory is " .. prefix)
end
- 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)
+
+ globals.prefix = prefix
+ local lookups = names.path.lookups
+ local index = names.path.index
+ local lookups_file = filejoin (prefix, globals.lookups_file)
+ local index_file = filejoin (prefix, globals.index_file)
+ lookups.lua, lookups.luc = make_luanames (lookups_file)
+ index.lua, index.luc = make_luanames (index_file)
else --- running as script, inject some dummies
caches = { }
logs = { report = function () end }
@@ -126,9 +158,6 @@ end
Auxiliary functions
--doc]]--
-
-local report = logs.names_report
-
--- string -> string
local sanitize_string = function (str)
if str ~= nil then
@@ -267,12 +296,6 @@ local fontnames_init = function (keep_cache) --- returns dbobj
}
end
---- string -> (string * string)
-local make_savenames = function (path)
- return filereplacesuffix(path, "lua"),
- filereplacesuffix(path, "luc")
-end
-
--- When loading a lua file we try its binary complement first, which
--- is assumed to be located at an identical path, carrying the suffix
--- .luc.
@@ -330,7 +353,7 @@ local fuzzy_limit = 1 --- display closest only
--- bool? -> dbobj
load_names = function (dry_run)
local starttime = os.gettimeofday()
- local foundname, data = load_lua_file(names.path.path)
+ local foundname, data = load_lua_file(names.path.index.lua)
if data then
report("both", 2, "db",
@@ -352,7 +375,7 @@ load_names = function (dry_run)
report("both", 0, "db",
[[Font names database not found, generating new one.]])
report("both", 0, "db",
- [[This can take several minutes; please be patient.]])
+ [[This can take several minutes; please be patient.]])
data = update_names(fontnames_init(false), nil, dry_run)
local success = save_names(data)
if not success then
@@ -365,7 +388,7 @@ end
--- unit -> dbobj
load_lookups = function ( )
- local foundname, data = load_lua_file(names.path.lookup_path)
+ local foundname, data = load_lua_file(names.path.lookups.lua)
if data then
report("both", 3, "cache",
"Lookup cache loaded (%s)", foundname)
@@ -776,7 +799,7 @@ resolve = function (_, _, specification) -- the 1st two parameters are used by C
if facenames then
family = facenames.family
subfamily = facenames.subfamily
- prefmodifiers = facenames.prefmodifiers
+ prefmodifiers = facenames.prefmodifiers or facenames.subfamily
fullname = facenames.fullname
psname = facenames.psname
fontname = facenames.fontname
@@ -795,16 +818,19 @@ resolve = function (_, _, specification) -- the 1st two parameters are used by C
if continue == false then break end
elseif style == subfamily then
exact = add_to_match(exact, askedsize, face)
+ elseif synonym_set[style] and synonym_set[style][prefmodifiers]
+ or synonym_set.regular[prefmodifiers]
+ then
+ --- treat synonyms for prefmodifiers as first-class
+ --- (needed to prioritize DejaVu Book over Condensed)
+ exact = add_to_match(exact, askedsize, face)
elseif name == fullname
or name == pfullname
or name == fontname
or name == psname
then
- synonymous, continue = add_to_match(synonymous, askedsize, face)
- elseif synonym_set[style] and
- (synonym_set[style][prefmodifiers] or
- synonym_set[style][subfamily])
- or synonym_set.regular[prefmodifiers]
+ synonymous = add_to_match(synonymous, askedsize, face)
+ elseif synonym_set[style] and synonym_set[style][subfamily]
or synonym_set.regular[subfamily]
then
synonymous = add_to_match(synonymous, askedsize, face)
@@ -1909,15 +1935,6 @@ update_names = function (fontnames, force, dry_run)
return newfontnames
end
---- unit -> string
-local ensure_names_path = function ( )
- local path = names.path.dir
- if not lfsisdir(path) then
- lfsmkdirs(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
@@ -1925,23 +1942,28 @@ end
--- unit -> bool
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_savenames(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("both", 3, "cache", "Lookup cache saved")
- return true
- end
+ local lookups = names.lookups
+ local path = names.path.lookups
+ local luaname, lucname = path.lua, path.luc
+ if fileiswritable (luaname) and fileiswritable (lucname) then
+ tabletofile (luaname, lookups, true)
+ osremove (lucname)
+ caches.compile (lookups, luaname, lucname)
+ --- double check ...
+ if lfsisfile (luaname) and lfsisfile (lucname) then
+ report ("both", 3, "cache", "Lookup cache saved")
+ return true
end
+ report ("info", 0, "cache", "Could not compile lookup cache")
+ return false
+ end
+ report ("info", 0, "cache", "Lookup cache file not writable")
+ if not fileiswritable (luaname) then
+ report ("info", 0, "cache", "Failed to write %s", luaname)
+ end
+ if not fileiswritable (lucname) then
+ report ("info", 0, "cache", "Failed to write %s", lucname)
end
- report("info", 0, "cache", "Could not write lookup cache")
return false
end
@@ -1949,23 +1971,28 @@ end
--- dbobj? -> bool
save_names = function (fontnames)
if not fontnames then fontnames = names.data end
- local path = ensure_names_path()
- if fileiswritable(path) then
- local luaname, lucname = make_savenames(names.path.path)
- if luaname then
- --tabletofile(luaname, fontnames, true, { reduce=true })
- tabletofile(luaname, fontnames, true)
- if lucname and type(caches.compile) == "function" then
- os.remove(lucname)
- caches.compile(fontnames, luaname, lucname)
- report("info", 1, "db", "Font names database saved")
- report("info", 3, "db", "Text: " .. luaname)
- report("info", 3, "db", "Byte: " .. lucname)
- return true
- end
+ local path = names.path.index
+ local luaname, lucname = path.lua, path.luc
+ if fileiswritable (luaname) and fileiswritable (lucname) then
+ tabletofile (luaname, fontnames, true)
+ osremove (lucname)
+ caches.compile (fontnames, luaname, lucname)
+ if lfsisfile (luaname) and lfsisfile (lucname) then
+ report ("info", 1, "db", "Font index saved")
+ report ("info", 3, "db", "Text: " .. luaname)
+ report ("info", 3, "db", "Byte: " .. lucname)
+ return true
end
+ report ("info", 0, "db", "Could not compile font index")
+ return false
+ end
+ report ("info", 0, "db", "Index file not writable")
+ if not fileiswritable (luaname) then
+ report ("info", 0, "db", "Failed to write %s", luaname)
+ end
+ if not fileiswritable (lucname) then
+ report ("info", 0, "db", "Failed to write %s", lucname)
end
- report("both", 0, "db", "Failed to save names database")
return false
end
@@ -1999,7 +2026,7 @@ local purge_from_cache = function (category, path, list, all)
if string.find(filename,"luatex%-cache") then -- safeguard
if all then
report("info", 5, "cache", "removing %s", filename)
- os.remove(filename)
+ osremove(filename)
n = n + 1
else
local suffix = file.suffix(filename)
@@ -2008,7 +2035,7 @@ local purge_from_cache = function (category, path, list, all)
filename, "lua", "luc")
if lfs.isfile(checkname) then
report("info", 5, "cache", "Removing %s", filename)
- os.remove(filename)
+ osremove(filename)
n = n + 1
end
end
@@ -2048,8 +2075,7 @@ end
local getwritablecachepath = function ( )
--- fonts.handlers.otf doesn’t exist outside a Luatex run,
--- so we have to improvise
- local writable = caches.getwritablepath
- (config.luaotfload.cache_dir)
+ local writable = getwritablepath (config.luaotfload.cache_dir)
if writable then
return writable
end