summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/font-syn.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/font-syn.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/font-syn.lua592
1 files changed, 334 insertions, 258 deletions
diff --git a/Master/texmf-dist/tex/context/base/font-syn.lua b/Master/texmf-dist/tex/context/base/font-syn.lua
index c4f0e948b87..81e27afd603 100644
--- a/Master/texmf-dist/tex/context/base/font-syn.lua
+++ b/Master/texmf-dist/tex/context/base/font-syn.lua
@@ -8,18 +8,30 @@ if not modules then modules = { } end modules ['font-syn'] = {
-- todo: subs in lookups requests
-local utf = unicode.utf8
-local next, tonumber = next, tonumber
-local gsub, lower, match, find, lower, upper = string.gsub, string.lower, string.match, string.find, string.lower, string.upper
+local next, tonumber, type, tostring = next, tonumber, type, tostring
+local sub, gsub, lower, match, find, lower, upper = string.sub, string.gsub, string.lower, string.match, string.find, string.lower, string.upper
local find, gmatch = string.find, string.gmatch
local concat, sort, format = table.concat, table.sort, string.format
local serialize = table.serialize
local lpegmatch = lpeg.match
-local utfgsub, utflower = utf.gsub, utf.lower
local unpack = unpack or table.unpack
+local formatters = string.formatters
-local allocate = utilities.storage.allocate
-local sparse = utilities.storage.sparse
+local allocate = utilities.storage.allocate
+local sparse = utilities.storage.sparse
+
+local removesuffix = file.removesuffix
+local splitbase = file.splitbase
+local splitname = file.splitname
+local basename = file.basename
+local nameonly = file.nameonly
+local pathpart = file.pathpart
+local filejoin = file.join
+local is_qualified_path = file.is_qualified_path
+
+local findfile = resolvers.findfile
+local cleanpath = resolvers.cleanpath
+local resolveresolved = resolvers.resolve
local trace_names = false trackers.register("fonts.names", function(v) trace_names = v end)
local trace_warnings = false trackers.register("fonts.warnings", function(v) trace_warnings = v end)
@@ -34,13 +46,13 @@ using a table that has keys filtered from the font related files.</p>
fonts = fonts or { } -- also used elsewhere
-local names = { }
+local names = font.names or allocate { }
fonts.names = names
-names.filters = names.filters or { }
-local filters = names.filters
+local filters = names.filters or { }
+names.filters = filters
-names.data = names.data or { }
+names.data = names.data or allocate { }
names.version = 1.110
names.basename = "names"
@@ -121,6 +133,50 @@ local variants = Cs( -- fax casual
local normalized_variants = sparse()
+names.knownweights = {
+ "black",
+ "bold",
+ "demi",
+ "demibold",
+ "extrabold",
+ "heavy",
+ "light",
+ "medium",
+ "mediumbold",
+ "normal",
+ "regular",
+ "semi",
+ "semibold",
+ "ultra",
+ "ultrabold",
+ "ultralight",
+}
+
+names.knownstyles = {
+ "italic",
+ "normal",
+ "oblique",
+ "regular",
+ "reverseitalic",
+ "reverseoblique",
+ "roman",
+ "slanted",
+}
+
+names.knownwidths = {
+ "book",
+ "condensed",
+ "expanded",
+ "normal",
+ "thin",
+}
+
+names.knownvariants = {
+ "normal",
+ "oldstyle",
+ "smallcaps",
+}
+
local any = P(1)
local analyzed_table
@@ -144,13 +200,13 @@ function names.splitspec(askedname)
width = width and lpegmatch(widths, width) or width
variant = variant and lpegmatch(variants,variant) or variant
if trace_names then
- report_names("requested name '%s' split in name '%s', weight '%s', style '%s', width '%s' and variant '%s'",
- askedname,name or '',weight or '',style or '',width or '',variant or '')
+ report_names("requested name %a split in name %a, weight %a, style %a, width %a and variant %a",
+ askedname,name,weight,style,width,variant)
end
if not weight or not weight or not width or not variant then
weight, style, width, variant = weight or "normal", style or "normal", width or "normal", variant or "normal"
if trace_names then
- report_names("request '%s' normalized to '%s-%s-%s-%s-%s'",
+ report_names("request %a normalized to '%s-%s-%s-%s-%s'",
askedname,name,weight,style,width,variant)
end
end
@@ -175,7 +231,7 @@ filters.ttf = fontloader.info
filters.ttc = fontloader.info
filters.dfont = fontloader.info
-function fontloader.fullinfo(...)
+function fontloader.fullinfo(...) -- check with taco what we get / could get
local ff = fontloader.open(...)
if ff then
local d = ff and fontloader.to_table(ff)
@@ -192,9 +248,9 @@ filters.otf = fontloader.fullinfo
function filters.afm(name)
-- we could parse the afm file as well, and then report an error but
-- it's not worth the trouble
- local pfbname = resolvers.findfile(file.removesuffix(name)..".pfb","pfb") or ""
+ local pfbname = findfile(removesuffix(name)..".pfb","pfb") or ""
if pfbname == "" then
- pfbname = resolvers.findfile(file.removesuffix(file.basename(name))..".pfb","pfb") or ""
+ pfbname = findfile(nameonly(name)..".pfb","pfb") or ""
end
if pfbname ~= "" then
local f = io.open(name)
@@ -228,7 +284,7 @@ for combination with the weight of a font.</p>
filters.list = {
"otf", "ttf", "ttc", "dfont", "afm",
---~ "ttc", "otf", "ttf", "dfont", "afm",
+ -- "ttc", "otf", "ttf", "dfont", "afm",
}
names.fontconfigfile = "fonts.conf" -- a bit weird format, bonus feature
@@ -240,11 +296,11 @@ filters.names = { }
function names.getpaths(trace)
local hash, result, r = { }, { }, 0
local function collect(t,where)
- for i=1, #t do
- local v = resolvers.cleanpath(t[i])
+ for i=1,#t do
+ local v = cleanpath(t[i])
v = gsub(v,"/+$","") -- not needed any more
local key = lower(v)
- report_names("adding path from %s: %s",where,v)
+ report_names("%a specifies path %a",where,v)
if not hash[key] then
r = r + 1
result[r] = v
@@ -263,34 +319,34 @@ function names.getpaths(trace)
end
if confname ~= "" then
-- first look in the tex tree
- local name = resolvers.findfile(confname,"fontconfig files") or ""
+ local name = findfile(confname,"fontconfig files") or ""
if name == "" then
-- after all, fontconfig is a unix thing
- name = file.join("/etc",confname)
+ name = filejoin("/etc",confname)
if not lfs.isfile(name) then
name = "" -- force quit
end
end
if name ~= "" and lfs.isfile(name) then
if trace_names then
- report_names("loading fontconfig file: %s",name)
+ report_names("%s fontconfig file %a","loading",name)
end
local xmldata = xml.load(name)
-- begin of untested mess
xml.include(xmldata,"include","",true,function(incname)
- if not file.is_qualified_path(incname) then
- local path = file.dirname(name) -- main name
+ if not is_qualified_path(incname) then
+ local path = pathpart(name) -- main name
if path ~= "" then
- incname = file.join(path,incname)
+ incname = filejoin(path,incname)
end
end
if lfs.isfile(incname) then
if trace_names then
- report_names("merging included fontconfig file: %s",incname)
+ report_names("%s fontconfig file %a","merging included",incname)
end
return io.loaddata(incname)
elseif trace_names then
- report_names("ignoring included fontconfig file: %s",incname)
+ report_names("%s fontconfig file: %a","ignoring included",incname)
end
end)
-- end of untested mess
@@ -310,12 +366,10 @@ end
local function cleanname(name)
return (gsub(lower(name),"[^%a%d]",""))
- -- once we can load files with utf names, we can play with the following:
- -- return (utfgsub(utfgsub(lower(str),"[^%a%A%d]",""),"%s",""))
end
local function cleanfilename(fullname,defaultsuffix)
- local path, name, suffix = file.splitname(fullname)
+ local path, name, suffix = splitname(fullname)
name = gsub(lower(name),"[^%a%d]","")
if suffix and suffix ~= "" then
return name .. ".".. suffix
@@ -345,33 +399,32 @@ local function walk_tree(pathlist,suffix,identify)
if pathlist then
for i=1,#pathlist do
local path = pathlist[i]
- path = resolvers.cleanpath(path .. "/")
+ path = cleanpath(path .. "/")
path = gsub(path,"/+","/")
local pattern = path .. "**." .. suffix -- ** forces recurse
- report_names( "globbing path %s",pattern)
+ report_names("globbing path %a",pattern)
local t = dir.glob(pattern)
sort(t,sorter)
for j=1,#t do
local completename = t[j]
- identify(completename,file.basename(completename),suffix,completename)
+ identify(completename,basename(completename),suffix,completename)
end
end
end
end
-local function check_name(data,result,filename,suffix,subfont)
+local function check_name(data,result,filename,modification,suffix,subfont)
-- shortcuts
local specifications = data.specifications
- local families = data.families
-- prepare
local names = check_names(result)
-- fetch
- local familyname = (names and names.preffamilyname) or result.familyname
- local fullname = (names and names.fullname) or result.fullname
+ local familyname = names and names.preffamilyname or result.familyname
+ local fullname = names and names.fullname or result.fullname
local fontname = result.fontname
- local subfamily = (names and names.subfamily)
- local modifiers = (names and names.prefmodifiers)
- local weight = (names and names.weight) or result.weight
+ local subfamily = names and names.subfamily
+ local modifiers = names and names.prefmodifiers
+ local weight = names and names.weight or result.weight
local italicangle = tonumber(result.italicangle)
local subfont = subfont or nil
local rawname = fullname or fontname or familyname
@@ -382,7 +435,7 @@ local function check_name(data,result,filename,suffix,subfont)
subfamily = subfamily and cleanname(subfamily)
modifiers = modifiers and cleanname(modifiers)
weight = weight and cleanname(weight)
- italicangle = (italicangle == 0) and nil
+ italicangle = italicangle == 0 and nil
-- analyze
local a_name, a_weight, a_style, a_width, a_variant = analyzespec(fullname or fontname or familyname)
-- check
@@ -404,34 +457,38 @@ local function check_name(data,result,filename,suffix,subfont)
if not familyname then
familyname = a_name
end
- fontname = fontname or fullname or familyname or file.basename(filename)
+ fontname = fontname or fullname or familyname or basename(filename)
fullname = fullname or fontname
familyname = familyname or fontname
specifications[#specifications + 1] = {
- filename = filename, -- unresolved
- format = lower(suffix),
- subfont = subfont,
- rawname = rawname,
- familyname = familyname,
- fullname = fullname,
- fontname = fontname,
- subfamily = subfamily,
- modifiers = modifiers,
- weight = weight,
- style = style,
- width = width,
- variant = variant,
- minsize = result.design_range_bottom or 0,
- maxsize = result.design_range_top or 0,
- designsize = result.design_size or 0,
+ filename = filename, -- unresolved
+ format = lower(suffix),
+ subfont = subfont,
+ rawname = rawname,
+ familyname = familyname,
+ fullname = fullname,
+ fontname = fontname,
+ subfamily = subfamily,
+ modifiers = modifiers,
+ weight = weight,
+ style = style,
+ width = width,
+ variant = variant,
+ minsize = result.design_range_bottom or 0,
+ maxsize = result.design_range_top or 0,
+ designsize = result.design_size or 0,
+ modification = modification or 0,
}
end
local function cleanupkeywords()
- local data = names.data
+ local data = names.data
local specifications = names.data.specifications
if specifications then
- local weights, styles, widths, variants = { }, { }, { }, { }
+ local weights = { }
+ local styles = { }
+ local widths = { }
+ local variants = { }
for i=1,#specifications do
local s = specifications[i]
-- fix (sofar styles are taken from the name, and widths from the specification)
@@ -463,29 +520,40 @@ local function cleanupkeywords()
end
local function collectstatistics()
- local data = names.data
+ local data = names.data
local specifications = data.specifications
if specifications then
- local weights, styles, widths, variants = { }, { }, { }, { }
+ local weights = { }
+ local styles = { }
+ local widths = { }
+ local variants = { }
for i=1,#specifications do
- local s = specifications[i]
- local weight, style, width, variant = s.weight, s.style, s.width, s.variant
+ local s = specifications[i]
+ local weight = s.weight
+ local style = s.style
+ local width = s.width
+ local variant = s.variant
if weight then weights [weight ] = (weights [weight ] or 0) + 1 end
if style then styles [style ] = (styles [style ] or 0) + 1 end
if width then widths [width ] = (widths [width ] or 0) + 1 end
if variant then variants[variant] = (variants[variant] or 0) + 1 end
end
- local stats = data.statistics
- stats.weights, stats.styles, stats.widths, stats.variants, stats.fonts = weights, styles, widths, variants, #specifications
+ local stats = data.statistics
+ stats.weights = weights
+ stats.styles = styles
+ stats.widths = widths
+ stats.variants = variants
+ stats.fonts = #specifications
end
end
local function collecthashes()
- local data = names.data
+ local data = names.data
local mappings = data.mappings
local fallbacks = data.fallbacks
local specifications = data.specifications
- local nofmappings, noffallbacks = 0, 0
+ local nofmappings = 0
+ local noffallbacks = 0
if specifications then
-- maybe multiple passes
for index=1,#specifications do
@@ -498,22 +566,20 @@ local function collecthashes()
if fontname and not mf[fontname] then
mf[fontname], nofmappings = index, nofmappings + 1
end
- if familyname and weight then
+ if familyname and weight and weight ~= sub(familyname,#familyname-#weight+1,#familyname) then
local madename = familyname .. weight
if not mf[madename] and not ff[madename] then
ff[madename], noffallbacks = index, noffallbacks + 1
end
end
- if familyname and subfamily then
+ if familyname and subfamily and subfamily ~= sub(familyname,#familyname-#subfamily+1,#familyname) then
local extraname = familyname .. subfamily
if not mf[extraname] and not ff[extraname] then
ff[extraname], noffallbacks = index, noffallbacks + 1
end
end
- if familyname then
- if not mf[familyname] and not ff[familyname] then
- ff[familyname], noffallbacks = index, noffallbacks + 1
- end
+ if familyname and not mf[familyname] and not ff[familyname] then
+ ff[familyname], noffallbacks = index, noffallbacks + 1
end
end
end
@@ -521,12 +587,12 @@ local function collecthashes()
end
local function collectfamilies()
- local data = names.data
+ local data = names.data
local specifications = data.specifications
- local families = data.families
+ local families = data.families
for index=1,#specifications do
local familyname = specifications[index].familyname
- local family = families[familyname]
+ local family = families[familyname]
if not family then
families[familyname] = { index }
else
@@ -536,14 +602,15 @@ local function collectfamilies()
end
local function checkduplicate(where) -- fails on "Romantik" but that's a border case anyway
- local data = names.data
- local mapping = data[where]
- local specifications, loaded = data.specifications, { }
+ local data = names.data
+ local mapping = data[where]
+ local specifications = data.specifications
+ local loaded = { }
if specifications and mapping then
for _, m in next, mapping do
for k, v in next, m do
local s = specifications[v]
- local hash = format("%s-%s-%s-%s-%s",s.familyname,s.weight or "*",s.style or "*",s.width or "*",s.variant or "*")
+ local hash = formatters["%s-%s-%s-%s-%s"](s.familyname,s.weight or "*",s.style or "*",s.width or "*",s.variant or "*")
local h = loaded[hash]
if h then
local ok = true
@@ -569,12 +636,12 @@ local function checkduplicate(where) -- fails on "Romantik" but that's a border
local nv = #v
if nv > 1 then
if trace_warnings then
- report_names( "double lookup: %s => %s",k,concat(v," | "))
+ report_names("lookup %a clashes with %a",k,v)
end
n = n + nv
end
end
- report_names( "%s double lookups in %s",n,where)
+ report_names("%a double lookups in %a",n,where)
end
local function checkduplicates()
@@ -587,13 +654,19 @@ local sorter = function(a,b)
end
local function sorthashes()
- local data, list = names.data, filters.list
- local mappings, fallbacks, sorted_mappings, sorted_fallbacks = data.mappings, data.fallbacks, { }, { }
- data.sorted_mappings, data.sorted_fallbacks = sorted_mappings, sorted_fallbacks
+ local data = names.data
+ local list = filters.list
+ local mappings = data.mappings
+ local fallbacks = data.fallbacks
+ local sorted_mappings = { }
+ local sorted_fallbacks = { }
+ data.sorted_mappings = sorted_mappings
+ data.sorted_fallbacks = sorted_fallbacks
for i=1,#list do
local l = list[i]
- sorted_mappings[l], sorted_fallbacks[l] = table.keys(mappings[l]), table.keys(fallbacks[l])
- sort(sorted_mappings[l],sorter)
+ sorted_mappings [l] = table.keys(mappings[l])
+ sorted_fallbacks[l] = table.keys(fallbacks[l])
+ sort(sorted_mappings [l],sorter)
sort(sorted_fallbacks[l],sorter)
end
data.sorted_families = table.keys(data.families)
@@ -601,7 +674,7 @@ local function sorthashes()
end
local function unpackreferences()
- local data = names.data
+ local data = names.data
local specifications = data.specifications
if specifications then
for k, v in next, data.families do
@@ -628,40 +701,52 @@ local function unpackreferences()
end
end
-local function analyzefiles()
- local data = names.data
- local done, totalnofread, totalnofskipped, totalnofduplicates, nofread, nofskipped, nofduplicates = { }, 0, 0, 0, 0, 0, 0
- local skip_paths, skip_names = filters.paths, filters.names
---~ local trace_warnings = true
+local function analyzefiles(olddata)
+ if not trace_warnings then
+ report_names("warnings are disabled (tracker 'fonts.warnings')")
+ end
+ local data = names.data
+ local done = { }
+ local totalnofread = 0
+ local totalnofskipped = 0
+ local totalnofduplicates = 0
+ local nofread = 0
+ local nofskipped = 0
+ local nofduplicates = 0
+ local skip_paths = filters.paths
+ local skip_names = filters.names
+ local specifications = data.specifications
+ local oldindices = olddata and olddata.indices or { }
+ local oldspecifications = olddata and olddata.specifications or { }
+ local oldrejected = olddata and olddata.rejected or { }
local function identify(completename,name,suffix,storedname)
- local basename = file.basename(completename)
- local basepath = file.dirname(completename)
+ local pathpart, basepart = splitbase(completename)
nofread = nofread + 1
if done[name] then
-- already done (avoid otf afm clash)
if trace_names then
- report_names("%s font %s already done",suffix,completename)
+ report_names("%s font %a already done",suffix,completename)
end
nofduplicates = nofduplicates + 1
nofskipped = nofskipped + 1
elseif not io.exists(completename) then
-- weird error
if trace_names then
- report_names("%s font %s does not really exist",suffix,completename)
+ report_names("%s font %a does not really exist",suffix,completename)
end
nofskipped = nofskipped + 1
- elseif not file.is_qualified_path(completename) and resolvers.findfile(completename,suffix) == "" then
- -- not locateble by backend anyway
+ elseif not is_qualified_path(completename) and findfile(completename,suffix) == "" then
+ -- not locatable by backend anyway
if trace_names then
- report_names("%s font %s cannot be found by backend",suffix,completename)
+ report_names("%s font %a cannot be found by backend",suffix,completename)
end
nofskipped = nofskipped + 1
else
if #skip_paths > 0 then
for i=1,#skip_paths do
- if find(basepath,skip_paths[i]) then
+ if find(pathpart,skip_paths[i]) then
if trace_names then
- report_names("rejecting path of %s font %s",suffix,completename)
+ report_names("rejecting path of %s font %a",suffix,completename)
end
nofskipped = nofskipped + 1
return
@@ -670,10 +755,10 @@ local function analyzefiles()
end
if #skip_names > 0 then
for i=1,#skip_paths do
- if find(basename,skip_names[i]) then
+ if find(basepart,skip_names[i]) then
done[name] = true
if trace_names then
- report_names("rejecting name of %s font %s",suffix,completename)
+ report_names("rejecting name of %s font %a",suffix,completename)
end
nofskipped = nofskipped + 1
return
@@ -681,29 +766,50 @@ local function analyzefiles()
end
end
if trace_names then
- report_names("identifying %s font %s",suffix,completename)
+ report_names("identifying %s font %a",suffix,completename)
end
- local result, message = filters[lower(suffix)](completename)
- if result then
- if result[1] then
- for r=1,#result do
- local ok = check_name(data,result[r],storedname,suffix,r-1) -- subfonts start at zero
+ local result = nil
+ local modification = lfs.attributes(completename,"modification")
+ if olddata and modification and modification > 0 then
+ local oldindex = oldindices[storedname] -- index into specifications
+ if oldindex then
+ local oldspecification = oldspecifications[oldindex]
+ if oldspecification and oldspecification.filename == storedname then -- double check for out of sync
+ local oldmodification = oldspecification.modification
+ if oldmodification == modification then
+ result = oldspecification
+ specifications[#specifications + 1] = result
+ else
+ end
+ else
+ end
+ elseif oldrejected[storedname] == modification then
+ result = false
+ end
+ end
+ if result == nil then
+ local result, message = filters[lower(suffix)](completename)
+ if result then
+ if result[1] then
+ for r=1,#result do
+ local ok = check_name(data,result[r],storedname,modification,suffix,r-1) -- subfonts start at zero
+ -- if not ok then
+ -- nofskipped = nofskipped + 1
+ -- end
+ end
+ else
+ local ok = check_name(data,result,storedname,modification,suffix)
-- if not ok then
-- nofskipped = nofskipped + 1
-- end
end
- else
- local ok = check_name(data,result,storedname,suffix)
- -- if not ok then
- -- nofskipped = nofskipped + 1
- -- end
- end
- if trace_warnings and message and message ~= "" then
- report_names("warning when identifying %s font %s: %s",suffix,completename,message)
+ if trace_warnings and message and message ~= "" then
+ report_names("warning when identifying %s font %a, %s",suffix,completename,message)
+ end
+ elseif trace_warnings then
+ nofskipped = nofskipped + 1
+ report_names("error when identifying %s font %a, %s",suffix,completename,message or "unknown")
end
- elseif trace_warnings then
- nofskipped = nofskipped + 1
- report_names("error when identifying %s font %s: %s",suffix,completename,message or "unknown")
end
done[name] = true
end
@@ -716,73 +822,85 @@ local function analyzefiles()
local t = os.gettimeofday() -- use elapser
nofread, nofskipped, nofduplicates = 0, 0, 0
suffix = lower(suffix)
- report_names( "identifying %s font files with suffix %s",what,suffix)
+ report_names("identifying %s font files with suffix %a",what,suffix)
method(suffix)
suffix = upper(suffix)
- report_names( "identifying %s font files with suffix %s",what,suffix)
+ report_names("identifying %s font files with suffix %a",what,suffix)
method(suffix)
totalnofread, totalnofskipped, totalnofduplicates = totalnofread + nofread, totalnofskipped + nofskipped, totalnofduplicates + nofduplicates
local elapsed = os.gettimeofday() - t
- report_names( "%s %s files identified, %s skipped, %s duplicates, %s hash entries added, runtime %0.3f seconds",nofread,what,nofskipped,nofduplicates,nofread-nofskipped,elapsed)
+ report_names("%s %s files identified, %s skipped, %s duplicates, %s hash entries added, runtime %0.3f seconds",nofread,what,nofskipped,nofduplicates,nofread-nofskipped,elapsed)
end
logs.flush()
end
- if not trace_warnings then
- report_names( "warnings are disabled (tracker 'fonts.warnings')")
- end
- traverse("tree", function(suffix) -- TEXTREE only
+ -- problem .. this will not take care of duplicates
+ local function withtree(suffix)
resolvers.dowithfilesintree(".*%." .. suffix .. "$", function(method,root,path,name)
if method == "file" or method == "tree" then
local completename = root .."/" .. path .. "/" .. name
- completename = resolvers.resolve(completename) -- no shortcut
+ completename = resolveresolved(completename) -- no shortcut
identify(completename,name,suffix,name)
return true
end
end, function(blobtype,blobpath,pattern)
- blobpath = resolvers.resolve(blobpath) -- no shortcut
- report_names( "scanning %s for %s files",blobpath,suffix)
+ blobpath = resolveresolved(blobpath) -- no shortcut
+ report_names("scanning path %a for %s files",blobpath,suffix)
end, function(blobtype,blobpath,pattern,total,checked,done)
- blobpath = resolvers.resolve(blobpath) -- no shortcut
- report_names( "%s entries found, %s %s files checked, %s okay",total,checked,suffix,done)
+ blobpath = resolveresolved(blobpath) -- no shortcut
+ report_names("%s entries found, %s %s files checked, %s okay",total,checked,suffix,done)
end)
- end)
- if texconfig.kpse_init then
+ end
+ local function withlsr(suffix) -- all trees
-- we do this only for a stupid names run, not used for context itself,
- -- using the vars is to clumsy so we just stick to a full scan instead
- traverse("lsr", function(suffix) -- all trees
- local pathlist = resolvers.splitpath(resolvers.showpath("ls-R") or "")
- walk_tree(pathlist,suffix,identify)
- end)
+ -- using the vars is too clumsy so we just stick to a full scan instead
+ local pathlist = resolvers.splitpath(resolvers.showpath("ls-R") or "")
+ walk_tree(pathlist,suffix,identify)
+ end
+ local function withsystem(suffix) -- OSFONTDIR cum suis
+ walk_tree(names.getpaths(trace),suffix,identify)
+ end
+ traverse("tree",withtree) -- TEXTREE only
+ if texconfig.kpse_init then
+ traverse("lsr", withlsr)
else
- traverse("system", function(suffix) -- OSFONTDIR cum suis
- walk_tree(names.getpaths(trace),suffix,identify)
- end)
+ traverse("system", withsystem)
end
- data.statistics.readfiles, data.statistics.skippedfiles, data.statistics.duplicatefiles = totalnofread, totalnofskipped, totalnofduplicates
+ data.statistics.readfiles = totalnofread
+ data.statistics.skippedfiles = totalnofskipped
+ data.statistics.duplicatefiles = totalnofduplicates
end
local function addfilenames()
- local data = names.data
+ local data = names.data
local specifications = data.specifications
- local files = { }
+ local indices = { }
+ local files = { }
for i=1,#specifications do
local fullname = specifications[i].filename
files[cleanfilename(fullname)] = fullname
+ indices[fullname] = i
end
- data.files = files
+ data.files = files
+ data.indices = indices
end
local function rejectclashes() -- just to be sure, so no explicit afm will be found then
- local specifications, used, okay, o = names.data.specifications, { }, { }, 0
+ local specifications = names.data.specifications
+ local used = { }
+ local okay = { }
+ local rejected = { } -- only keep modification
+ local o = 0
for i=1,#specifications do
local s = specifications[i]
local f = s.fontname
if f then
- local fnd, fnm = used[f], s.filename
+ local fnd = used[f]
+ local fnm = s.filename
if fnd then
if trace_warnings then
- report_names( "fontname '%s' clashes, rejecting '%s' in favor of '%s'",f,fnm,fnd)
+ report_names("fontname %a clashes, %a rejected in favor of %a",f,fnm,fnd)
end
+ rejected[f] = s.modification
else
used[f] = fnm
o = o + 1
@@ -795,30 +913,37 @@ local function rejectclashes() -- just to be sure, so no explicit afm will be fo
end
local d = #specifications - #okay
if d > 0 then
- report_names( "%s files rejected due to clashes",d)
+ report_names("%s files rejected due to clashes",d)
end
names.data.specifications = okay
+ names.data.rejected = rejected
end
local function resetdata()
- local mappings, fallbacks = { }, { }
+ local mappings = { }
+ local fallbacks = { }
for _, k in next, filters.list do
- mappings[k], fallbacks[k] = { }, { }
+ mappings [k] = { }
+ fallbacks[k] = { }
end
names.data = {
- version = names.version,
- mappings = mappings,
- fallbacks = fallbacks,
+ version = names.version,
+ mappings = mappings,
+ fallbacks = fallbacks,
specifications = { },
- families = { },
- statistics = { },
- datastate = resolvers.datastate(),
+ families = { },
+ statistics = { },
+ names = { },
+ indices = { },
+ rejected = { },
+ datastate = resolvers.datastate(),
}
end
-function names.identify()
+function names.identify(force)
+ local starttime = os.gettimeofday() -- use elapser
resetdata()
- analyzefiles()
+ analyzefiles(not force and names.readdata(names.basename))
rejectclashes()
collectfamilies()
collectstatistics()
@@ -827,6 +952,7 @@ function names.identify()
checkduplicates()
addfilenames()
-- sorthashes() -- will be resorted when saved
+ report_names("total scan time %0.3f seconds",os.gettimeofday()-starttime)
end
function names.is_permitted(name)
@@ -839,11 +965,11 @@ function names.readdata(name)
return containers.read(names.cache,name)
end
-function names.load(reload,verbose)
+function names.load(reload,force)
if not names.loaded then
if reload then
if names.is_permitted(names.basename) then
- names.identify(verbose)
+ names.identify(force)
names.writedata(names.basename,names.data)
else
report_names("unable to access database cache")
@@ -890,9 +1016,11 @@ function names.list(pattern,reload,all) -- here?
local t = { }
local data = names.data
if data then
- local list = filters.list
- local mappings, sorted_mappings = data.mappings, data.sorted_mappings
- local fallbacks, sorted_fallbacks = data.fallbacks, data.sorted_fallbacks
+ local list = filters.list
+ local mappings = data.mappings
+ local sorted_mappings = data.sorted_mappings
+ local fallbacks = data.fallbacks
+ local sorted_fallbacks = data.sorted_fallbacks
for i=1,#list do
local format = list[i]
list_them(mappings[format],sorted_mappings[format],pattern,t,all)
@@ -954,10 +1082,12 @@ end
-- we could cache a lookup .. maybe some day ... (only when auto loaded!)
local function foundname(name,sub) -- sub is not used currently
- local data = names.data
- local mappings, sorted_mappings = data.mappings, data.sorted_mappings
- local fallbacks, sorted_fallbacks = data.fallbacks, data.sorted_fallbacks
- local list = filters.list
+ local data = names.data
+ local mappings = data.mappings
+ local sorted_mappings = data.sorted_mappings
+ local fallbacks = data.fallbacks
+ local sorted_fallbacks = data.sorted_fallbacks
+ local list = filters.list
-- dilemma: we lookup in the order otf ttf ttc ... afm but now an otf fallback
-- can come after an afm match ... well, one should provide nice names anyway
-- and having two lists is not an option
@@ -966,7 +1096,7 @@ local function foundname(name,sub) -- sub is not used currently
local found = mappings[l][name]
if found then
if trace_names then
- report_names("resolved via direct name match: '%s'",name)
+ report_names("resolved via direct name match: %a",name)
end
return found
end
@@ -976,7 +1106,7 @@ local function foundname(name,sub) -- sub is not used currently
local found, fname = fuzzy(mappings[l],sorted_mappings[l],name,sub)
if found then
if trace_names then
- report_names("resolved via fuzzy name match: '%s' => '%s'",name,fname)
+ report_names("resolved via fuzzy name match: %a onto %a",name,fname)
end
return found
end
@@ -986,7 +1116,7 @@ local function foundname(name,sub) -- sub is not used currently
local found = fallbacks[l][name]
if found then
if trace_names then
- report_names("resolved via direct fallback match: '%s'",name)
+ report_names("resolved via direct fallback match: %a",name)
end
return found
end
@@ -996,13 +1126,13 @@ local function foundname(name,sub) -- sub is not used currently
local found, fname = fuzzy(sorted_mappings[l],sorted_fallbacks[l],name,sub)
if found then
if trace_names then
- report_names("resolved via fuzzy fallback match: '%s' => '%s'",name,fname)
+ report_names("resolved via fuzzy fallback match: %a onto %a",name,fname)
end
return found
end
end
if trace_names then
- report_names("font with name '%s' cannot be found",name)
+ report_names("font with name %a cannot be found",name)
end
end
@@ -1248,40 +1378,39 @@ end
local function collect(stage,found,done,name,weight,style,width,variant,all)
local data = names.data
- local families, sorted = data.families, data.sorted_families
- strictname = "^".. name -- to be checked
+ local families = data.families
+ local sorted = data.sorted_families
+ local strictname = "^".. name -- to be checked
local family = families[name]
if trace_names then
- report_names("resolving name '%s', weight '%s', style '%s', width '%s', variant '%s'",
- name or "?",tostring(weight),tostring(style),tostring(width),tostring(variant))
+ report_names("resolving name %a, weight %a, style %a, width %a, variant %a",name,weight,style,width,variant)
end
- --~ print(name,serialize(family))
if weight and weight ~= "" then
if style and style ~= "" then
if width and width ~= "" then
if variant and variant ~= "" then
if trace_names then
- report_names("resolving stage %s, name '%s', weight '%s', style '%s', width '%s', variant '%s'",stage,name,weight,style,width,variant)
+ report_names("resolving stage %s, name %a, weight %a, style %a, width %a, variant %a",stage,name,weight,style,width,variant)
end
s_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,family)
m_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,families,sorted,strictname)
else
if trace_names then
- report_names("resolving stage %s, name '%s', weight '%s', style '%s', width '%s'",stage,name,weight,style,width)
+ report_names("resolving stage %s, name %a, weight %a, style %a, width %a",stage,name,weight,style,width)
end
s_collect_weight_style_width(found,done,all,weight,style,width,family)
m_collect_weight_style_width(found,done,all,weight,style,width,families,sorted,strictname)
end
else
if trace_names then
- report_names("resolving stage %s, name '%s', weight '%s', style '%s'",stage,name,weight,style)
+ report_names("resolving stage %s, name %a, weight %a, style %a",stage,name,weight,style)
end
s_collect_weight_style(found,done,all,weight,style,family)
m_collect_weight_style(found,done,all,weight,style,families,sorted,strictname)
end
else
if trace_names then
- report_names("resolving stage %s, name '%s', weight '%s'",stage,name,weight)
+ report_names("resolving stage %s, name %a, weight %a",stage,name,weight)
end
s_collect_weight(found,done,all,weight,family)
m_collect_weight(found,done,all,weight,families,sorted,strictname)
@@ -1289,26 +1418,26 @@ local function collect(stage,found,done,name,weight,style,width,variant,all)
elseif style and style ~= "" then
if width and width ~= "" then
if trace_names then
- report_names("resolving stage %s, name '%s', style '%s', width '%s'",stage,name,style,width)
+ report_names("resolving stage %s, name %a, style %a, width %a",stage,name,style,width)
end
s_collect_style_width(found,done,all,style,width,family)
m_collect_style_width(found,done,all,style,width,families,sorted,strictname)
else
if trace_names then
- report_names("resolving stage %s, name '%s', style '%s'",stage,name,style)
+ report_names("resolving stage %s, name %a, style %a",stage,name,style)
end
s_collect_style(found,done,all,style,family)
m_collect_style(found,done,all,style,families,sorted,strictname)
end
elseif width and width ~= "" then
if trace_names then
- report_names("resolving stage %s, name '%s', width '%s'",stage,name,width)
+ report_names("resolving stage %s, name %a, width %a",stage,name,width)
end
s_collect_width(found,done,all,width,family)
m_collect_width(found,done,all,width,families,sorted,strictname)
else
if trace_names then
- report_names("resolving stage %s, name '%s'",stage,name)
+ report_names("resolving stage %s, name %a",stage,name)
end
s_collect(found,done,all,family)
m_collect(found,done,all,families,sorted,strictname)
@@ -1344,11 +1473,11 @@ local function heuristic(name,weight,style,width,variant,all) -- todo: fallbacks
if nf then
local t = { }
for i=1,nf do
- t[i] = format("'%s'",found[i].fontname)
+ t[i] = formatters["%a"](found[i].fontname)
end
- report_names("name '%s' resolved to %s instances: %s",name,nf,concat(t," "))
+ report_names("name %a resolved to %s instances: % t",name,nf,t)
else
- report_names("name '%s' unresolved",name)
+ report_names("name %a unresolved",name)
end
end
if all then
@@ -1402,7 +1531,6 @@ function names.collectfiles(askedname,reload) -- no all
askedname = cleanname(askedname) -- or cleanname
names.load(reload)
local list = { }
- local basename = file.basename
local specifications = names.data.specifications
for i=1,#specifications do
local s = specifications[i]
@@ -1414,77 +1542,25 @@ function names.collectfiles(askedname,reload) -- no all
end
end
---~ --[[ldx--
---~ <p>Fallbacks, not permanent but a transition thing.</p>
---~ --ldx]]--
---~
---~ names.new_to_old = allocate {
---~ ["lmroman10-capsregular"] = "lmromancaps10-oblique",
---~ ["lmroman10-capsoblique"] = "lmromancaps10-regular",
---~ ["lmroman10-demi"] = "lmromandemi10-oblique",
---~ ["lmroman10-demioblique"] = "lmromandemi10-regular",
---~ ["lmroman8-oblique"] = "lmromanslant8-regular",
---~ ["lmroman9-oblique"] = "lmromanslant9-regular",
---~ ["lmroman10-oblique"] = "lmromanslant10-regular",
---~ ["lmroman12-oblique"] = "lmromanslant12-regular",
---~ ["lmroman17-oblique"] = "lmromanslant17-regular",
---~ ["lmroman10-boldoblique"] = "lmromanslant10-bold",
---~ ["lmroman10-dunhill"] = "lmromandunh10-oblique",
---~ ["lmroman10-dunhilloblique"] = "lmromandunh10-regular",
---~ ["lmroman10-unslanted"] = "lmromanunsl10-regular",
---~ ["lmsans10-demicondensed"] = "lmsansdemicond10-regular",
---~ ["lmsans10-demicondensedoblique"] = "lmsansdemicond10-oblique",
---~ ["lmsansquotation8-bold"] = "lmsansquot8-bold",
---~ ["lmsansquotation8-boldoblique"] = "lmsansquot8-boldoblique",
---~ ["lmsansquotation8-oblique"] = "lmsansquot8-oblique",
---~ ["lmsansquotation8-regular"] = "lmsansquot8-regular",
---~ ["lmtypewriter8-regular"] = "lmmono8-regular",
---~ ["lmtypewriter9-regular"] = "lmmono9-regular",
---~ ["lmtypewriter10-regular"] = "lmmono10-regular",
---~ ["lmtypewriter12-regular"] = "lmmono12-regular",
---~ ["lmtypewriter10-italic"] = "lmmono10-italic",
---~ ["lmtypewriter10-oblique"] = "lmmonoslant10-regular",
---~ ["lmtypewriter10-capsoblique"] = "lmmonocaps10-oblique",
---~ ["lmtypewriter10-capsregular"] = "lmmonocaps10-regular",
---~ ["lmtypewriter10-light"] = "lmmonolt10-regular",
---~ ["lmtypewriter10-lightoblique"] = "lmmonolt10-oblique",
---~ ["lmtypewriter10-lightcondensed"] = "lmmonoltcond10-regular",
---~ ["lmtypewriter10-lightcondensedoblique"] = "lmmonoltcond10-oblique",
---~ ["lmtypewriter10-dark"] = "lmmonolt10-bold",
---~ ["lmtypewriter10-darkoblique"] = "lmmonolt10-boldoblique",
---~ ["lmtypewritervarwd10-regular"] = "lmmonoproplt10-regular",
---~ ["lmtypewritervarwd10-oblique"] = "lmmonoproplt10-oblique",
---~ ["lmtypewritervarwd10-light"] = "lmmonoprop10-regular",
---~ ["lmtypewritervarwd10-lightoblique"] = "lmmonoprop10-oblique",
---~ ["lmtypewritervarwd10-dark"] = "lmmonoproplt10-bold",
---~ ["lmtypewritervarwd10-darkoblique"] = "lmmonoproplt10-boldoblique",
---~ }
---~
---~ names.old_to_new = allocate(table.swapped(names.new_to_old))
-
---~ todo:
---~
---~ blacklisted = {
---~ ["cmr10.ttf"] = "completely messed up",
---~ }
+-- todo:
+--
+-- blacklisted = {
+-- ["cmr10.ttf"] = "completely messed up",
+-- }
function names.exists(name)
local found = false
local list = filters.list
for k=1,#list do
local v = list[k]
- found = (resolvers.findfile(name,v) or "") ~= ""
+ found = (findfile(name,v) or "") ~= ""
if found then
return found
end
end
- return ((resolvers.findfile(name,"tfm") or "") ~= "") or ((names.resolve(name) or "") ~= "")
+ return (findfile(name,"tfm") or "") ~= "" or (names.resolve(name) or "") ~= ""
end
--- for i=1,fonts.names.lookup(pattern) do
--- texio.write_nl(fonts.names.getkey("filename",i))
--- end
-
local lastlookups, lastpattern = { }, ""
function names.lookup(pattern,name,reload) -- todo: find
@@ -1499,7 +1575,7 @@ function names.lookup(pattern,name,reload) -- todo: find
lookups = families[pattern]
end
if trace_names then
- report_names("starting with %s lookups for '%s'",#lookups,pattern)
+ report_names("starting with %s lookups for %a",#lookups,pattern)
end
if lookups then
for key, value in gmatch(pattern,"([^=,]+)=([^=,]+)") do
@@ -1523,7 +1599,7 @@ function names.lookup(pattern,name,reload) -- todo: find
end
end
if trace_names then
- report_names("%s matches for key '%s' with value '%s'",#t,key,value)
+ report_names("%s matches for key %a with value %a",#t,key,value)
end
lookups = t
end
@@ -1617,19 +1693,19 @@ end
function names.resolvespec(askedname,sub) -- overloads previous definition
local name, weight, style, width, variant = names.splitspec(askedname)
if trace_specifications then
- report_names("resolving specification: %s -> name=%s, weight=%s, style=%s, width=%s, variant=%s",askedname,name,weight,style,width,variant)
+ report_names("resolving specification: %a to name=%s, weight=%s, style=%s, width=%s, variant=%s",askedname,name,weight,style,width,variant)
end
local found = names.registered(name,weight,style,width,variant)
if found and found.filename then
if trace_specifications then
- report_names("resolved by registered names: %s -> %s",askedname,found.filename)
+ report_names("resolved by registered names: %a to %s",askedname,found.filename)
end
return found.filename, found.subname, found.rawname
else
found = names.specification(name,weight,style,width,variant)
if found and found.filename then
if trace_specifications then
- report_names("resolved by font database: %s -> %s",askedname,found.filename)
+ report_names("resolved by font database: %a to %s",askedname,found.filename)
end
return found.filename, found.subfont and found.rawname
end