From c63c0a57f15b491b56b82104a6896e3f0630a778 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sun, 12 May 2013 22:44:11 +0000 Subject: luaotfload (12may13) git-svn-id: svn://tug.org/texlive/trunk@30425 c570f23f-e606-0410-a88d-b1316a301751 --- .../scripts/luaotfload/luaotfload-legacy-tool.lua | 105 ++++++++ .../scripts/luaotfload/luaotfload-tool.lua | 287 ++++++++++++++++++--- Master/texmf-dist/scripts/luaotfload/mkglyphlist | 22 +- 3 files changed, 383 insertions(+), 31 deletions(-) create mode 100755 Master/texmf-dist/scripts/luaotfload/luaotfload-legacy-tool.lua (limited to 'Master/texmf-dist/scripts') diff --git a/Master/texmf-dist/scripts/luaotfload/luaotfload-legacy-tool.lua b/Master/texmf-dist/scripts/luaotfload/luaotfload-legacy-tool.lua new file mode 100755 index 00000000000..30ab13b6e3a --- /dev/null +++ b/Master/texmf-dist/scripts/luaotfload/luaotfload-legacy-tool.lua @@ -0,0 +1,105 @@ +#!/usr/bin/env texlua +--[[ +This file is copyright 2010 Elie Roux and Khaled Hosny and is under CC0 +license (see http://creativecommons.org/publicdomain/zero/1.0/legalcode). + +This file is a wrapper for the luaotfload's font names module. It is part of the +luaotfload bundle, please see the luaotfload documentation for more info. +--]] + +kpse.set_program_name("luatex") + +require("lualibs") ---> current +require("luaotfload-legacy-database") ---> old +require("alt_getopt") ---> ? + +local name = "mkluatexfontdb" +local version = "1.31 (legacy)" + +local names = fonts.names + +local function help_msg() + texio.write(string.format([[ +Usage: %s [OPTION]... + +================================================================================ + please update your luatex binary + this version is unsupported and likely to break things +================================================================================ + +Rebuild the LuaTeX font database. + +Valid options: + -f --force force re-indexing all fonts + -q --quiet don't output anything + -v --verbose=LEVEL be more verbose (print the searched directories) + -vv print the loaded fonts + -vvv print all steps of directory searching + -V --version print version and exit + -h --help print this message + +The output database file is named otfl-names.lua and is placed under: + + %s + +contact: https://github.com/lualatex/luaotfload + +]], name, names.path.localdir)) +end + +local function version_msg() + texio.write(string.format( + "%s version %s, database version %s.\n", name, version, names.version)) +end + +--[[ +Command-line processing. +Here we fill cmdargs with the good values, and then analyze it. +--]] + +local long_opts = { + force = "f", + quiet = "q", + help = "h", + verbose = 1 , + version = "V", +} + +local short_opts = "fqpvVh" + +local force_reload = nil + +local function process_cmdline() + local opts, optind, optarg = alt_getopt.get_ordered_opts (arg, short_opts, long_opts) + local log_level = 1 + for i,v in ipairs(opts) do + if v == "q" then + log_level = 0 + elseif v == "v" then + if log_level > 0 then + log_level = log_level + 1 + else + log_level = 2 + end + elseif v == "V" then + version_msg() + os.exit(0) + elseif v == "h" then + help_msg() + os.exit(0) + elseif v == "f" then + force_reload = 1 + end + end + names.set_log_level(log_level) +end + +local function generate(force) + local fontnames, saved + fontnames = names.update(fontnames, force) + logs.report("%s fonts in the database", #fontnames.mappings) + saved = names.save(fontnames) +end + +process_cmdline() +generate(force_reload) diff --git a/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua b/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua index 0cd19b1d3a4..352697ced37 100755 --- a/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua +++ b/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua @@ -26,12 +26,29 @@ see the luaotfload documentation for more info. Report bugs to --doc]]-- +--[[doc-- + + We test for Lua 5.1 by means of capability detection to see if + we’re running an outdated Luatex. If so, we hand over control to + the legacy db runner. + + \url{http://lua-users.org/wiki/LuaVersionCompatibility} + +--doc]]-- + kpse.set_program_name"luatex" +if _G.getfenv then + local oldscript = kpse.find_file"luaotfload-legacy-tool.lua" + return require(oldscript) +end + 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 +81,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 @@ -90,6 +105,19 @@ config.lualibs.load_extended = false require"lualibs" +--- prepare directories: the cache function in Luatex-Fonts +--- checks for writable directory only on startup, so everything +--- has to be laid out before we load basics-gen + +local cachepath = kpse.expand_var"$TEXMFVAR" +if not lfs.isdir(cachepath) then + dir.mkdirs(cachepath) + if not lfs.isdir(cachepath) then + texiowrite(stringformat( + "ERROR could not create directory %s", cachepath)) + end +end + --[[doc-- \fileent{luatex-basics-gen.lua} calls functions from the \luafunction{texio.*} library; too much for our taste. @@ -129,17 +157,21 @@ This tool is part of the luaotfload package. Valid options are: -v --verbose=LEVEL be more verbose (print the searched directories) -vv print the loaded fonts -vvv print all steps of directory searching + --log=stdout redirect log output to stdout + -V --version print version and exit -h --help print this message --alias= force behavior of “luaotfload-tool” or legacy “mkluatexfontdb” + ------------------------------------------------------------------------------- DATABASE -u --update update the database -f --force force re-indexing all fonts - -c --flush-cache empty cache of font requests + -l --flush-lookups empty lookup cache of font requests + -D --dry-run skip loading of fonts, just scan --find="font name" query the database for a font name -F --fuzzy look for approximate matches if --find fails @@ -147,18 +179,26 @@ This tool is part of the luaotfload package. Valid options are: (default: n = 1) -i --info display font metadata - --log=stdout redirect log output to stdout + --list= output list of entries by field + --list=: restrict to entries with = + --fields=,,…, which fields to print with --list The font database will be saved to %s %s +------------------------------------------------------------------------------- + FONT CACHE + + --cache= operate on font cache, where is + “show”, “purge”, or “erase” + ]], mkluatexfontdb = [[ Usage: %s [OPTION]... -Rebuild the LuaTeX font database. +Rebuild or update the LuaTeX font database. Valid options: -f --force force re-indexing all fonts @@ -228,7 +268,8 @@ set. --]]-- local action_sequence = { - "loglevel", "help", "version", "flush", "generate", "query" + "loglevel", "help", "version", "cache", + "flush", "generate", "list", "query", } local action_pending = table.tohash(action_sequence, false) @@ -241,6 +282,7 @@ actions.loglevel = function (job) logs.set_loglevel(job.log_level) logs.names_report("info", 3, "util", "setting log level", "%d", job.log_level) + logs.names_report("log", 0, "util", "lua=%s", _VERSION) return true, true end @@ -256,28 +298,47 @@ end actions.generate = function (job) local fontnames, savedname - fontnames = names.update(fontnames, job.force_reload) + fontnames = names.update(fontnames, job.force_reload, job.dry_run) logs.names_report("info", 2, "db", "Fonts in the database: %i", #fontnames.mappings) - savedname = names.save(fontnames) - if savedname then --- FIXME have names.save return bool + local success = names.save(fontnames) + if success then return true, true end return false, false end actions.flush = function (job) - local success, lookups = names.flush_cache() + local success, lookups = names.flush_lookup_cache() if success then - local savedname = names.save_lookups() - logs.names_report("info", 2, "cache", "Cache emptied") - if savedname then + local success = names.save_lookups() + if success then + logs.names_report("info", 2, "cache", "Lookup cache emptied") return true, true end end return false, false end +local cache_directives = { + ["purge"] = names.purge_cache, + ["erase"] = names.erase_cache, + ["show"] = names.show_cache, +} + +actions.cache = function (job) + local directive = cache_directives[job.cache] + if not directive or type(directive) ~= "function" then + logs.names_report("info", 2, "cache", + "Invalid font cache directive %s.", job.cache) + return false, false + end + if directive() then + return true, true + end + return false, false +end + actions.query = function (job) local query = job.query @@ -286,7 +347,7 @@ actions.query = function (job) lookup = "name", specification = "name:" .. query, optsize = 0, - } + } local foundname, subfont, success = fonts.names.resolve(nil, nil, tmpspec) @@ -317,6 +378,158 @@ actions.query = function (job) return true, true end +--- --list= +--- --list=: +--- +--- --list= --fields=,,,... + +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] = "" + 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 = { } + if asked_value then --- only those whose value matches + logs.names_report(false, 2, "list", "restricting to value %s", asked_value) + 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 + + else --- whichever have the field, sorted + local categories, by_category = { }, { } + for i=1, nmappings do + local entry = mappings[i] + local value = entry[criterion] + if value then + --value = tostring(value) + local entries = by_category[value] + if not entries then + entries = { entry } + categories[#categories+1] = value + else + entries[#entries+1] = entry + end + by_category[value] = entries + end + end + table.sort(categories) + + for i=1, #categories do + local entries = by_category[categories[i]] + for j=1, #entries do + targets[#targets+1] = entries[j] + end + end + end + local ntargets = #targets + 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,27 +543,32 @@ 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 } local long_options = { - alias = 1, - ["flush-cache"] = "c", - find = 1, - force = "f", - fuzzy = "F", - help = "h", - info = "i", - limit = 1, - log = 1, - quiet = "q", - update = "u", - verbose = 1 , - version = "V", + alias = 1, + cache = 1, + ["dry-run"] = "D", + ["flush-lookups"] = "l", + fields = 1, + find = 1, + force = "f", + fuzzy = "F", + help = "h", + info = "i", + limit = 1, + list = 1, + log = 1, + quiet = "q", + update = "u", + verbose = 1 , + version = "V", } - local short_options = "cfFiquvVh" + local short_options = "DfFilquvVh" local options, _, optarg = alt_getopt.get_ordered_opts (arg, short_options, long_options) @@ -399,14 +617,25 @@ local process_cmdline = function ( ) -- unit -> jobspec result.show_info = true elseif v == "alias" then config.luaotfload.self = optarg[n] - elseif v == "c" then + elseif v == "l" 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] + elseif v == "cache" then + action_pending["cache"] = true + result.cache = optarg[n] + elseif v == "D" then + result.dry_run = true end end if config.luaotfload.self == "mkluatexfontdb" then action_pending["generate"] = true result.log_level = math.max(2, result.log_level) + logs.set_logout"stdout" end return result end diff --git a/Master/texmf-dist/scripts/luaotfload/mkglyphlist b/Master/texmf-dist/scripts/luaotfload/mkglyphlist index 281c7368a73..94aac39d7a1 100755 --- a/Master/texmf-dist/scripts/luaotfload/mkglyphlist +++ b/Master/texmf-dist/scripts/luaotfload/mkglyphlist @@ -17,9 +17,24 @@ -- config ----------------------------------------------------------------------- local glyphfile = "./glyphlist.txt" -local font_age = "./font-age.lua" +local font_age = "./luaotfload-glyphlist.lua" local glyph_source = "http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt" +----------------------------------------------------------------------- +-- fallbacks +----------------------------------------------------------------------- +--- Hans adds a small list of mappings that are not in the original +--- glyph list but seem to be normalizations of some sort. I trust his +--- experience, so I’ll just include them here. Background: +--- http://www.ntg.nl/pipermail/ntg-context/2013/073089.html + +local fallbacks = { + ["SF10000"]=9484, ["SF20000"]=9492, ["SF30000"]=9488, + ["SF40000"]=9496, ["SF50000"]=9532, ["SF60000"]=9516, + ["SF70000"]=9524, ["SF80000"]=9500, ["SF90000"]=9508, + ["afii208"]=8213, +} + ----------------------------------------------------------------------- -- includes ----------------------------------------------------------------------- @@ -73,6 +88,9 @@ local get_glyphs = function (data) print("error: could not parse glyph list") os.exit(-1) end + for name, glyph in next, fallbacks do + res[name] = res[name] or glyph + end return res end @@ -93,7 +111,7 @@ end --[[doc-- Everything below has been autogenerated. Run mkglyphlist to rebuild -font-age.lua. +luaotfload-glyphlist.lua. --doc]]-- ]==] -- cgit v1.2.3