diff options
Diffstat (limited to 'tex/context/base/mkiv/font-syn.lua')
-rw-r--r-- | tex/context/base/mkiv/font-syn.lua | 119 |
1 files changed, 95 insertions, 24 deletions
diff --git a/tex/context/base/mkiv/font-syn.lua b/tex/context/base/mkiv/font-syn.lua index c4dcf0bcd..52f425db3 100644 --- a/tex/context/base/mkiv/font-syn.lua +++ b/tex/context/base/mkiv/font-syn.lua @@ -14,9 +14,11 @@ if not modules then modules = { } end modules ['font-syn'] = { -- old ff loader: 140 sec -- new lua loader: 5 sec +-- maybe find(...,strictname,1,true) + local next, tonumber, type, tostring = next, tonumber, type, tostring local sub, gsub, match, find, lower, upper = string.sub, string.gsub, string.match, string.find, string.lower, string.upper -local concat, sort, fastcopy = table.concat, table.sort, table.fastcopy +local concat, sort, fastcopy, tohash = table.concat, table.sort, table.fastcopy, table.tohash local serialize, sortedhash = table.serialize, table.sortedhash local lpegmatch = lpeg.match local unpack = unpack or table.unpack @@ -35,6 +37,7 @@ local splitname = file.splitname local basename = file.basename local nameonly = file.nameonly local pathpart = file.pathpart +local suffixonly = file.suffix local filejoin = file.join local is_qualified_path = file.is_qualified_path local exists = io.exists @@ -393,11 +396,11 @@ filters.ttc = filters.otf -- local hash = { } -- local okay = false -- for line in f:lines() do -- slow but only a few lines at the beginning --- if find(line,"dict begin") then +-- if find(line,"dict begin",1,true) then -- okay = true -- elseif not okay then -- -- go on --- elseif find(line,"currentdict end") then +-- elseif find(line,"currentdict end",1,true) then -- break -- else -- local key, value = lpegmatch(p_entry,line) @@ -423,8 +426,10 @@ filters.list = { -- to be considered: loop over paths per list entry (so first all otf ttf etc) -names.fontconfigfile = "fonts.conf" -- a bit weird format, bonus feature -names.osfontdirvariable = "OSFONTDIR" -- the official way, in minimals etc +names.fontconfigfile = "fonts.conf" -- a bit weird format, bonus feature +names.osfontdirvariable = "OSFONTDIR" -- the official way, in minimals etc +names.extrafontsvariable = "EXTRAFONTS" -- the official way, in minimals etc +names.runtimefontsvariable = "RUNTIMEFONTS" -- the official way, in minimals etc filters.paths = { } filters.names = { } @@ -436,7 +441,7 @@ function names.getpaths(trace) local v = cleanpath(t[i]) v = gsub(v,"/+$","") -- not needed any more local key = lower(v) - report_names("%a specifies path %a",where,v) + report_names("variable %a specifies path %a",where,v) if not hash[key] then r = r + 1 result[r] = v @@ -448,6 +453,10 @@ function names.getpaths(trace) if path ~= "" then collect(resolvers.expandedpathlist(path),path) end + local path = names.extrafontsvariable or "" + if path ~= "" then + collect(resolvers.expandedpathlist(path),path) + end if xml then local confname = resolvers.expansion("FONTCONFIG_FILE") or "" if confname == "" then @@ -539,23 +548,6 @@ names.cleanfilename = cleanfilename -- return result -- end -local function walk_tree(pathlist,suffix,identify) - if pathlist then - for i=1,#pathlist do - local path = pathlist[i] - path = cleanpath(path .. "/") - path = gsub(path,"/+","/") - local pattern = path .. "**." .. suffix -- ** forces recurse - 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,basename(completename),suffix,completename) - end - end - end -end local function check_name(data,result,filename,modification,suffix,subfont) -- shortcuts @@ -1002,9 +994,11 @@ local function unpackreferences() end 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 @@ -1020,6 +1014,26 @@ local function analyzefiles(olddata) local oldspecifications = olddata and olddata.specifications or { } local oldrejected = olddata and olddata.rejected or { } local treatmentdata = treatments.data or { } -- when used outside context + ----- walked = setmetatableindex("number") + + local function walk_tree(pathlist,suffix,identify) + if pathlist then + for i=1,#pathlist do + local path = pathlist[i] + path = cleanpath(path .. "/") + path = gsub(path,"/+","/") + local pattern = path .. "**." .. suffix -- ** forces recurse + 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,basename(completename),suffix,completename) + end + -- walked[path] = walked[path] + #t + end + end + end local function identify(completename,name,suffix,storedname) local pathpart, basepart = splitbase(completename) @@ -1123,6 +1137,7 @@ local function analyzefiles(olddata) end logs.flush() -- a bit overkill for each font, maybe not needed here end + local function traverse(what, method) local list = filters.list for n=1,#list do @@ -1141,7 +1156,9 @@ local function analyzefiles(olddata) end logs.flush() end + -- 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 @@ -1158,16 +1175,20 @@ local function analyzefiles(olddata) report_names("%s entries found, %s %s files checked, %s okay",total,checked,suffix,done) end) 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 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 not usesystemfonts then report_names("ignoring system fonts") elseif texconfig.kpse_init then @@ -1175,9 +1196,15 @@ local function analyzefiles(olddata) else traverse("system", withsystem) end + data.statistics.readfiles = totalnofread data.statistics.skippedfiles = totalnofskipped data.statistics.duplicatefiles = totalnofduplicates + + -- for k, v in sortedhash(walked) do + -- report_names("%s : %i",k,v) + -- end + end local function addfilenames() @@ -1492,10 +1519,54 @@ end -- end -- end +local runtimefiles = { } +local runtimedone = false + +local function addruntimepath(path) + names.load() + local paths = type(path) == "table" and path or { path } + local suffixes = tohash(filters.list) + for i=1,#paths do + local path = resolveprefix(paths[i]) + if path ~= "" then + local list = dir.glob(path.."/*") + for i=1,#list do + local fullname = list[i] + local suffix = lower(suffixonly(fullname)) + if suffixes[suffix] then + local c = cleanfilename(fullname) + runtimefiles[c] = fullname + if trace_names then + report_names("adding runtime filename %a for %a",c,fullname) + end + end + end + end + end +end + +local function addruntimefiles(variable) + local paths = variable and resolvers.expandedpathlistfromvariable(variable) + if paths and #paths > 0 then + addruntimepath(paths) + end +end + +names.addruntimepath = addruntimepath +names.addruntimefiles = addruntimefiles + function names.getfilename(askedname,suffix) -- last resort, strip funny chars + if not runtimedone then + addruntimefiles(names.runtimefontsvariable) + runtimedone = true + end + local cleanname = cleanfilename(askedname,suffix) + local found = runtimefiles[cleanname] + if found then + return found + end names.load() local files = names.data.files - local cleanname = cleanfilename(askedname,suffix) local found = files and files[cleanname] or "" if found == "" and is_reloaded() then files = names.data.files |