summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--luaotfload-auxiliary.lua4
-rw-r--r--luaotfload-database.lua26
-rwxr-xr-xluaotfload-tool.lua147
3 files changed, 162 insertions, 15 deletions
diff --git a/luaotfload-auxiliary.lua b/luaotfload-auxiliary.lua
index 2d459d0..9f7974a 100644
--- a/luaotfload-auxiliary.lua
+++ b/luaotfload-auxiliary.lua
@@ -64,6 +64,10 @@ local add_fontdata_fallbacks = function (fontdata)
metadata = fontdata.shared.rawdata.metadata
fontdata.units = fontparameters.units
local resources = fontdata.resources
+ --- the next line is a hack that fixes scaling of fonts with
+ --- non-standard em-sizes (most ms fonts have 2048, others
+ --- come with 256)
+ --- this is considered a bug in the font loader
fontdata.size = fontparameters.size * fontdata.units / 1000
--- for legacy fontspec.lua and unicode-math.lua
fontdata.shared.otfdata = metadata
diff --git a/luaotfload-database.lua b/luaotfload-database.lua
index 576341f..96db195 100644
--- a/luaotfload-database.lua
+++ b/luaotfload-database.lua
@@ -146,10 +146,11 @@ This is a sketch of the luaotfload db:
psname : string;
subfamily : string;
}
- size : int list;
- slant : int;
- weight : int;
- width : int;
+ size : int list;
+ slant : int;
+ weight : int;
+ width : int;
+ units_per_em : int; // mainly 1000, but also 2048 or 256
}
and filestatus = (fullname, { index : int list; timestamp : int }) dict
@@ -836,13 +837,16 @@ font_fullinfo = function (filename, subfont)
report("log", 1, "db", "broken font rejected", "%s", basefile)
return
end
- tfmdata.fontname = metadata.fontname
- tfmdata.fullname = metadata.fullname
- tfmdata.familyname = metadata.familyname
- tfmdata.filename = { filename, subfont } -- always store full path
- tfmdata.weight = metadata.pfminfo.weight
- tfmdata.width = metadata.pfminfo.width
- tfmdata.slant = metadata.italicangle
+ tfmdata.fontname = metadata.fontname
+ tfmdata.fullname = metadata.fullname
+ tfmdata.familyname = metadata.familyname
+ tfmdata.filename = { filename, subfont } -- always store full path
+ tfmdata.weight = metadata.pfminfo.weight
+ tfmdata.width = metadata.pfminfo.width
+ tfmdata.slant = metadata.italicangle
+ --- this is for querying
+ tfmdata.units_per_em = metadata.units_per_em
+ tfmdata.version = metadata.version
-- don't waste the space with zero values
tfmdata.size = {
metadata.design_size ~= 0 and metadata.design_size or nil,
diff --git a/luaotfload-tool.lua b/luaotfload-tool.lua
index 0cd19b1..6662291 100755
--- a/luaotfload-tool.lua
+++ b/luaotfload-tool.lua
@@ -32,6 +32,8 @@ local stringformat = string.format
local texiowrite_nl = texio.write_nl
local stringlower = string.lower
+local C, Ct, P = lpeg.C, lpeg.Ct, lpeg.P
+local lpegmatch = lpeg.match
local loader_file = "luatexbase.loader.lua"
local loader_path = assert(kpse.find_file(loader_file, "lua"),
@@ -64,8 +66,6 @@ local config = config
config.luaotfload = config.luaotfload or { }
do -- we don’t have file.basename and the likes yet, so inline parser ftw
- local C, P = lpeg.C, lpeg.P
- local lpegmatch = lpeg.match
local slash = P"/"
local dot = P"."
local noslash = 1 - slash
@@ -228,7 +228,7 @@ set.
--]]--
local action_sequence = {
- "loglevel", "help", "version", "flush", "generate", "query"
+ "loglevel", "help", "version", "flush", "generate", "list", "query"
}
local action_pending = table.tohash(action_sequence, false)
@@ -286,7 +286,7 @@ actions.query = function (job)
lookup = "name",
specification = "name:" .. query,
optsize = 0,
- }
+ }
local foundname, subfont, success =
fonts.names.resolve(nil, nil, tmpspec)
@@ -317,6 +317,137 @@ actions.query = function (job)
return true, true
end
+--- --list=<criterion>
+--- --list=<criterion>:<value>
+---
+--- --list=<criterion> --fields=<f1>,<f2>,<f3>,...<fn>
+
+local get_fields get_fields = function (entry, fields, acc, n)
+ if not acc then
+ return get_fields(entry, fields, { }, 1)
+ end
+
+ local field = fields[n]
+ if field then
+ local value = entry[field]
+ acc[#acc+1] = value or false
+ return get_fields(entry, fields, acc, n+1)
+ end
+ return acc
+end
+
+local comma = P","
+local noncomma = 1-comma
+local split_comma = Ct((C(noncomma^1) + comma)^1)
+
+local texiowrite_nl = texio.write_nl
+local tableconcat = table.concat
+local stringexplode = string.explode
+
+local separator = "\t" --- could be “,” for csv
+
+local format_fields format_fields = function (fields, acc, n)
+ if not acc then
+ return format_fields(fields, { }, 1)
+ end
+
+ local field = fields[n]
+ if field ~= nil then
+ if field == false then
+ acc[#acc+1] = "<none>"
+ else
+ acc[#acc+1] = tostring(field)
+ end
+ return format_fields(fields, acc, n+1)
+ end
+ return tableconcat(acc, separator)
+end
+
+local set_primary_field
+set_primary_field = function (fields, addme, acc, n)
+ if not acc then
+ return set_primary_field(fields, addme, { addme }, 1)
+ end
+
+ local field = fields[n]
+ if field then
+ if field ~= addme then
+ acc[#acc+1] = field
+ end
+ return set_primary_field(fields, addme, acc, n+1)
+ end
+ return acc
+end
+
+actions.list = function (job)
+ local criterion = job.criterion
+
+ local asked_fields = job.asked_fields
+ if asked_fields then
+ asked_fields = lpegmatch(split_comma, asked_fields)
+ else
+ --- some defaults
+ asked_fields = { "fullname", "version", }
+ end
+
+ if not names.data then
+ names.data = names.load()
+ end
+
+ local mappings = names.data.mappings
+ local nmappings = #mappings
+
+ if criterion == "*" then
+ logs.names_report(false, 1, "list", "all %d entries", nmappings)
+ for i=1, nmappings do
+ local entry = mappings[i]
+ local fields = get_fields(entry, asked_fields)
+ --- we could collect these instead ...
+ local formatted = format_fields(fields)
+ texiowrite_nl(formatted)
+ end
+
+ else
+ criterion = stringexplode(criterion, ":") --> { field, value }
+ local asked_value = criterion[2]
+ criterion = criterion[1]
+ asked_fields = set_primary_field(asked_fields, criterion)
+
+ logs.names_report(false, 1, "list", "by %s", criterion)
+
+ --- firstly, build a list of fonts to operate on
+ local targets, ntargets
+
+ if asked_value then
+ logs.names_report(false, 2, "list", "restricting to value %s", asked_value)
+ targets = { }
+ for i=1, nmappings do
+ local entry = mappings[i]
+ if entry[criterion]
+ and tostring(entry[criterion]) == asked_value
+ then
+ targets[#targets+1] = entry
+ end
+ end
+ ntargets = #targets
+ else --- all
+ targets = mappings
+ ntargets = nmappings
+ end
+ logs.names_report(false, 2, "list", "%d entries", ntargets)
+
+ --- now, output the collection
+ for i=1, ntargets do
+ local entry = targets[i]
+ local fields = get_fields(entry, asked_fields)
+ local formatted = format_fields(fields)
+ texiowrite_nl(formatted)
+ end
+ end
+
+ return true, true
+end
+
--[[--
Command-line processing.
mkluatexfontdb.lua relies on the script alt_getopt to process argv and
@@ -330,6 +461,7 @@ alt_getopt.
local process_cmdline = function ( ) -- unit -> jobspec
local result = { -- jobspec
force_reload = nil,
+ criterion = "",
query = "",
log_level = 1, --- 2 is approx. the old behavior
}
@@ -337,12 +469,14 @@ local process_cmdline = function ( ) -- unit -> jobspec
local long_options = {
alias = 1,
["flush-cache"] = "c",
+ fields = 1,
find = 1,
force = "f",
fuzzy = "F",
help = "h",
info = "i",
limit = 1,
+ list = 1,
log = 1,
quiet = "q",
update = "u",
@@ -401,6 +535,11 @@ local process_cmdline = function ( ) -- unit -> jobspec
config.luaotfload.self = optarg[n]
elseif v == "c" then
action_pending["flush"] = true
+ elseif v == "list" then
+ action_pending["list"] = true
+ result.criterion = optarg[n]
+ elseif v == "fields" then
+ result.asked_fields = optarg[n]
end
end