summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/luaotfload-database.lua63
-rw-r--r--src/luaotfload-init.lua2
-rw-r--r--src/luaotfload-main.lua234
-rw-r--r--src/luaotfload-resolvers.lua256
4 files changed, 295 insertions, 260 deletions
diff --git a/src/luaotfload-database.lua b/src/luaotfload-database.lua
index 1831ca3..381185b 100644
--- a/src/luaotfload-database.lua
+++ b/src/luaotfload-database.lua
@@ -454,22 +454,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
@@ -558,6 +555,7 @@ getmetadata = function ()
end
--- unit -> unit
+local load_lookups
load_lookups = function ( )
local foundname, data = load_lua_file(config.luaotfload.paths.lookup_path_lua)
if data then
@@ -638,7 +636,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
@@ -647,7 +645,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
@@ -667,7 +666,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
@@ -715,7 +714,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
@@ -748,7 +747,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
@@ -777,7 +776,8 @@ 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 ...",
@@ -801,7 +801,7 @@ resolve_cached = function (specification)
--- 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
@@ -935,13 +935,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
@@ -978,7 +978,7 @@ local resolve_familyname = function (specification, name, style, askedsize)
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
@@ -1021,7 +1021,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
@@ -1059,7 +1059,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
@@ -1068,7 +1068,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)
@@ -1086,28 +1086,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
@@ -3449,17 +3449,18 @@ 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.lookup_font_file = lookup_font_file
+names.lookup_font_name = lookup_font_name
+names.lookup_font_name_cached = lookup_font_name_cached
+names.getfilename = lookup_fullpath
+names.lookup_fullpath = lookup_fullpath
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
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index 0ef968d..a493cc1 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -9,6 +9,8 @@
-----------------------------------------------------------------------
--
+local setmetatable = setmetatable
+
--[[doc--
Initialization phases:
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 5ac1421..b633ed7 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -65,16 +65,8 @@ luaotfload.module = {
--doc]]--
local luatexbase = luatexbase
-
local require = require
-local setmetatable = setmetatable
-local type, next = type, next
-local stringlower = string.lower
-local stringformat = string.format
-
-local kpsefind_file = kpse.find_file
-local lfsisfile = lfs.isfile
-
+local type = type
local add_to_callback = luatexbase.add_to_callback
local create_callback = luatexbase.create_callback
local reset_callback = luatexbase.reset_callback
@@ -177,228 +169,12 @@ load_luaotfload_module "loaders" --- Type1 font wrappers
load_luaotfload_module "database" --- Font management.
load_luaotfload_module "colors" --- Per-font colors.
-if not config.actions.reconfigure () then
- logreport ("log", 0, "load", "Post-configuration hooks failed.")
-end
-
---[[doc--
-
- Relying on the \verb|name:| resolver for everything has been the
- source of permanent trouble with the database.
- With the introduction of the new syntax parser we now have enough
- granularity to distinguish between the \XETEX emulation layer and
- the genuine \verb|name:| and \verb|file:| lookups of \LUATEX-Fonts.
- Another benefit is that we can now easily plug in or replace new
- lookup behaviors if necessary.
- The name resolver remains untouched, but it calls
- \luafunction{fonts.names.resolve()} internally anyways (see
- \fileent{luaotfload-database.lua}).
-
---doc]]--
-
-local filesuffix = file.suffix
-local fileremovesuffix = file.removesuffix
-local request_resolvers = fonts.definers.resolvers
-local formats = fonts.formats
-local names = fonts.names
-formats.ofm = "type1"
-
-fonts.encodings.known = fonts.encodings.known or { }
-
---[[doc--
+luaotfload.resolvers = load_luaotfload_module "resolvers" --- Font lookup
- \identifier{luaotfload} promises easy access to system fonts.
- Without additional precautions, this cannot be achieved by
- \identifier{kpathsea} alone, because it searches only the
- \fileent{texmf} directories by default.
- Although it is possible for \identifier{kpathsea} to include extra
- paths by adding them to the \verb|OSFONTDIR| environment variable,
- this is still short of the goal »\emphasis{it just works!}«.
- When building the font database \identifier{luaotfload} scans
- system font directories anyways, so we already have all the
- information for looking sytem fonts.
- With the release version 2.2 the file names are indexed in the
- database as well and we are ready to resolve \verb|file:| lookups
- this way.
- Thus we no longer need to call the \identifier{kpathsea} library in
- most cases when looking up font files, only when generating the
- database, and when verifying the existence of a file in the
- \fileent{texmf} tree.
-
---doc]]--
-
-local resolve_file = names.font_file_lookup
-
-local file_resolver = function (specification)
- local name = resolve_file (specification.name)
- local suffix = filesuffix(name)
- if formats[suffix] then
- specification.forced = stringlower (suffix)
- specification.forcedname = file.removesuffix(name)
- else
- specification.name = name
- end
-end
-
-request_resolvers.file = file_resolver
-
---[[doc--
-
- We classify as \verb|anon:| those requests that have neither a
- prefix nor brackets. According to Khaled\footnote{%
- \url{https://github.com/phi-gamma/luaotfload/issues/4#issuecomment-17090553}.
- }
- they are the \XETEX equivalent of a \verb|name:| request, so we
- will be treating them as such.
-
---doc]]--
-
---request_resolvers.anon = request_resolvers.name
-
---[[doc--
-
- There is one drawback, though.
- This syntax is also used for requesting fonts in \identifier{Type1}
- (\abbrev{tfm}, \abbrev{ofm}) format.
- These are essentially \verb|file:| lookups and must be caught
- before the \verb|name:| resolver kicks in, lest they cause the
- database to update.
- Even if we were to require the \verb|file:| prefix for all
- \identifier{Type1} requests, tests have shown that certain fonts
- still include further fonts (e.~g. \fileent{omlgcb.ofm} will ask
- for \fileent{omsecob.tfm}) \emphasis{using the old syntax}.
- For this reason, we introduce an extra check with an early return.
-
---doc]]--
-
-local type1_formats = { "tfm", "ofm", "TFM", "OFM", }
-
-request_resolvers.anon = function (specification)
- local name = specification.name
- for i=1, #type1_formats do
- local format = type1_formats[i]
- local suffix = filesuffix (name)
- if resolvers.findfile(name, format) then
- local usename = suffix == format and file.removesuffix (name) or name
- specification.forcedname = file.addsuffix (usename, format)
- specification.forced = format
- return
- end
- end
- --- under some weird circumstances absolute paths get
- --- passed to the definer; we have to catch them
- --- before the name: resolver misinterprets them.
- name = specification.specification
- local exists, _ = lfsisfile(name)
- if exists then --- garbage; we do this because we are nice,
- --- not because it is correct
- logreport ("log", 1, "load", "file %q exists", name)
- logreport ("log", 1, "load",
- "... overriding borked anon: lookup with path: lookup")
- specification.name = name
- request_resolvers.path(specification)
- return
- end
- request_resolvers.name(specification)
-end
+luaotfload.resolvers.install ()
---[[doc--
-
- Prior to version 2.2, \identifier{luaotfload} did not distinguish
- \verb|file:| and \verb|path:| lookups, causing complications with
- the resolver.
- Now we test if the requested name is an absolute path in the file
- system, otherwise we fall back to the \verb|file:| lookup.
-
---doc]]--
-
-request_resolvers.path = function (specification)
- local name = specification.name
- local exists, _ = lfsisfile(name)
- if not exists then -- resort to file: lookup
- logreport ("log", 0, "load",
- "path lookup of %q unsuccessful, falling back to file:",
- name)
- file_resolver (specification)
- else
- local suffix = filesuffix (name)
- if formats[suffix] then
- specification.forced = stringlower (suffix)
- specification.name = file.removesuffix(name)
- specification.forcedname = name
- else
- specification.name = name
- end
- end
-end
-
---[[doc--
-
- {\bfseries EXPERIMENTAL}:
- \identifier{kpse}-only resolver, for those who can do without
- system fonts.
-
---doc]]--
-
-request_resolvers.kpse = function (specification)
- local name = specification.name
- local suffix = filesuffix(name)
- if suffix and formats[suffix] then
- name = file.removesuffix(name)
- if resolvers.findfile(name, suffix) then
- specification.forced = stringlower (suffix)
- specification.forcedname = name
- return
- end
- end
- for t, format in next, formats do --- brute force
- if kpse.find_file (name, format) then
- specification.forced = t
- specification.name = name
- return
- end
- end
-end
-
---[[doc--
-
- The \verb|name:| resolver.
-
---doc]]--
-
---- fonts.names.resolvers.name -- Customized version of the
---- generic name resolver.
-
-request_resolvers.name = function (specification)
- local resolver = names.resolve_cached
- if config.luaotfload.run.resolver == "normal" then
- resolver = names.resolve_name
- end
- local resolved, subfont = resolver (specification)
- if resolved then
- logreport ("log", 0, "load", "Lookup/name: %q -> \"%s%s\"",
- specification.name,
- resolved,
- subfont and stringformat ("(%d)", subfont) or "")
- specification.resolved = resolved
- specification.sub = subfont
- specification.forced = stringlower (filesuffix (resolved) or "")
- specification.forcedname = resolved
- specification.name = fileremovesuffix (resolved)
- else
- file_resolver (specification)
- end
-end
-
---[[doc--
-
- Also {\bfseries EXPERIMENTAL}: custom file resolvers via callback.
-
---doc]]--
-create_callback("luaotfload.resolve_font", "simple", dummy_function)
-
-request_resolvers.my = function (specification)
- call_callback("luaotfload.resolve_font", specification)
+if not config.actions.reconfigure () then
+ logreport ("log", 0, "load", "Post-configuration hooks failed.")
end
--[[doc--
diff --git a/src/luaotfload-resolvers.lua b/src/luaotfload-resolvers.lua
new file mode 100644
index 0000000..42ea2fd
--- /dev/null
+++ b/src/luaotfload-resolvers.lua
@@ -0,0 +1,256 @@
+#!/usr/bin/env texlua
+-----------------------------------------------------------------------
+-- FILE: luaotfload-resolvers.lua
+-- USAGE: ./luaotfload-resolvers.lua
+-- DESCRIPTION: Resolvers for hooking into the fontloader
+-- REQUIREMENTS: Luaotfload and a decent bit of courage
+-- AUTHOR: Philipp Gesang (Phg), <phg@phi-gamma.net>
+-- VERSION: 1.0
+-- CREATED: 2015-07-23 07:31:50+0200
+-----------------------------------------------------------------------
+--
+--- The bare fontloader uses a set of simplistic file name resolvers
+--- that must be overloaded by the user (i. e. us).
+
+if not lualibs then error "this module requires Luaotfload" end
+if not luaotfload then error "this module requires Luaotfload" end
+
+--[[doc--
+
+ Relying on the \verb|name:| resolver for everything has been the
+ source of permanent trouble with the database.
+ With the introduction of the new syntax parser we now have enough
+ granularity to distinguish between the \XETEX emulation layer and
+ the genuine \verb|name:| and \verb|file:| lookups of \LUATEX-Fonts.
+ Another benefit is that we can now easily plug in or replace new
+ lookup behaviors if necessary.
+ The name resolver remains untouched, but it calls
+ \luafunction{fonts.names.resolve()} internally anyways (see
+ \fileent{luaotfload-database.lua}).
+
+--doc]]--
+
+local next = next
+local kpsefind_file = kpse.find_file
+local lfsisfile = lfs.isfile
+local stringlower = string.lower
+local stringformat = string.format
+local filesuffix = file.suffix
+local fileremovesuffix = file.removesuffix
+local formats = fonts.formats
+local names = fonts.names
+local encodings = fonts.encodings
+local luatexbase = luatexbase
+local logreport = luaotfload.log.report
+
+formats.ofm = "type1"
+encodings.known = encodings.known or { }
+
+--[[doc--
+
+ \identifier{luaotfload} promises easy access to system fonts.
+ Without additional precautions, this cannot be achieved by
+ \identifier{kpathsea} alone, because it searches only the
+ \fileent{texmf} directories by default.
+ Although it is possible for \identifier{kpathsea} to include extra
+ paths by adding them to the \verb|OSFONTDIR| environment variable,
+ this is still short of the goal »\emphasis{it just works!}«.
+ When building the font database \identifier{luaotfload} scans
+ system font directories anyways, so we already have all the
+ information for looking sytem fonts.
+ With the release version 2.2 the file names are indexed in the
+ database as well and we are ready to resolve \verb|file:| lookups
+ this way.
+ Thus we no longer need to call the \identifier{kpathsea} library in
+ most cases when looking up font files, only when generating the
+ database, and when verifying the existence of a file in the
+ \fileent{texmf} tree.
+
+--doc]]--
+
+local resolve_file
+resolve_file = function (specification)
+ local name = names.lookup_font_file (specification.name)
+ local suffix = filesuffix (name)
+ if formats[suffix] then
+ specification.forced = stringlower (suffix)
+ specification.forcedname = fileremovesuffix(name)
+ else
+ specification.name = name
+ end
+end
+
+--[[doc--
+
+ Prior to version 2.2, \identifier{luaotfload} did not distinguish
+ \verb|file:| and \verb|path:| lookups, causing complications with
+ the resolver.
+ Now we test if the requested name is an absolute path in the file
+ system, otherwise we fall back to the \verb|file:| lookup.
+
+--doc]]--
+
+local resolve_path
+resolve_path = function (specification)
+ local name = specification.name
+ local exists, _ = lfsisfile(name)
+ if not exists then -- resort to file: lookup
+ logreport ("log", 0, "load",
+ "path lookup of %q unsuccessful, falling back to file:",
+ name)
+ resolve_file (specification)
+ else
+ local suffix = filesuffix (name)
+ if formats[suffix] then
+ specification.forced = stringlower (suffix)
+ specification.name = fileremovesuffix(name)
+ specification.forcedname = name
+ else
+ specification.name = name
+ end
+ end
+end
+
+--[[doc--
+
+ The \verb|name:| resolver.
+
+--doc]]--
+
+--- fonts.names.resolvers.name -- Customized version of the
+--- generic name resolver.
+
+local resolve_name
+resolve_name = function (specification)
+ local resolver = names.lookup_font_name_cached
+ if config.luaotfload.run.resolver == "normal" then
+ resolver = names.lookup_font_name
+ end
+ local resolved, subfont = resolver (specification)
+ if resolved then
+ logreport ("log", 0, "load", "Lookup/name: %q -> \"%s%s\"",
+ specification.name,
+ resolved,
+ subfont and stringformat ("(%d)", subfont) or "")
+ specification.resolved = resolved
+ specification.sub = subfont
+ specification.forced = stringlower (filesuffix (resolved) or "")
+ specification.forcedname = resolved
+ specification.name = fileremovesuffix (resolved)
+ else
+ resolve_file (specification)
+ end
+end
+
+--[[doc--
+
+ We classify as \verb|anon:| those requests that have neither a
+ prefix nor brackets. According to Khaled\footnote{%
+ % XXX dead link‽
+ \url{https://github.com/phi-gamma/luaotfload/issues/4#issuecomment-17090553}.
+ }
+ they are the \XETEX equivalent of a \verb|name:| request, so we
+ will be treating them as such or, at least, in a similar fashion.
+
+ Not distinguishing between “anon” and “name” requests has a serious
+ drawback: The syntax is overloaded for requesting fonts in
+ \identifier{Type1} (\abbrev{tfm}, \abbrev{ofm}) format.
+ These are essentially \verb|file:| lookups and must be caught
+ before the \verb|name:| resolver kicks in, lest they cause the
+ database to update.
+ Even if we were to require the \verb|file:| prefix for all
+ \identifier{Type1} requests, tests have shown that certain fonts
+ still include further fonts (e.~g. \fileent{omlgcb.ofm} will ask
+ for \fileent{omsecob.tfm}) \emphasis{using the old syntax}.
+ For this reason, we introduce an extra check with an early return.
+
+--doc]]--
+
+local type1_formats = { "tfm", "ofm", "TFM", "OFM", }
+
+local resolve_anon
+resolve_anon = function (specification)
+ local name = specification.name
+ for i=1, #type1_formats do
+ local format = type1_formats[i]
+ local suffix = filesuffix (name)
+ if resolvers.findfile(name, format) then
+ local usename = suffix == format and fileremovesuffix (name) or name
+ specification.forcedname = file.addsuffix (usename, format)
+ specification.forced = format
+ return
+ end
+ end
+ --- under some weird circumstances absolute paths get
+ --- passed to the definer; we have to catch them
+ --- before the name: resolver misinterprets them.
+ name = specification.specification
+ local exists, _ = lfsisfile(name)
+ if exists then --- garbage; we do this because we are nice,
+ --- not because it is correct
+ logreport ("log", 1, "load", "file %q exists", name)
+ logreport ("log", 1, "load",
+ "... overriding borked anon: lookup with path: lookup")
+ specification.name = name
+ resolve_path (specification)
+ return
+ end
+ resolve_name (specification)
+end
+
+--[[doc--
+
+ {\bfseries EXPERIMENTAL}:
+ \identifier{kpse}-only resolver, for those who can do without
+ system fonts.
+
+--doc]]--
+
+local resolve_kpse
+resolve_kpse = function (specification)
+ local name = specification.name
+ local suffix = filesuffix (name)
+ if suffix and formats[suffix] then
+ name = fileremovesuffix (name)
+ if resolvers.findfile (name, suffix) then
+ specification.forced = stringlower (suffix)
+ specification.forcedname = name
+ return
+ end
+ end
+ for t, format in next, formats do --- brute force
+ if kpsefind_file (name, format) then
+ specification.forced = t
+ specification.name = name
+ return
+ end
+ end
+end
+
+--[[doc--
+
+ Also {\bfseries EXPERIMENTAL}: custom file resolvers via callback.
+
+--doc]]--
+
+local resolve_my = function (specification)
+ luatexbase.call_callback ("luaotfload.resolve_font", specification)
+end
+
+return {
+ install = function ( )
+ luatexbase.create_callback ("luaotfload.resolve_font", "simple", function () end)
+ logreport ("log", 5, "resolvers", "installing font resolvers", name)
+ local request_resolvers = fonts.definers.resolvers
+ request_resolvers.file = resolve_file
+ request_resolvers.name = resolve_name
+ request_resolvers.anon = resolve_anon
+ request_resolvers.path = resolve_path
+ request_resolvers.kpse = resolve_kpse
+ request_resolvers.my = resolve_my
+ return true
+ end, --- [.install]
+}
+
+--- vim:ft=lua:ts=8:sw=4:et
+