From b309379ef546b7fa819f493fa3cb1dc559d4c3b8 Mon Sep 17 00:00:00 2001
From: Hans Hagen
A few helpers.
+--ldx]]-- + +local P, C, Cc, Cs, Carg = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Carg + +local weights = Cs ( -- not extra + P("demibold") + + P("semibold") + + P("mediumbold") + + P("ultrabold") + + P("extrabold") + + P("ultralight") + + P("bold") + + P("demi") + + P("semi") + + P("light") + + P("medium") + + P("heavy") + + P("ultra") + + P("black") + + P("bol") + + P("regular") / "normal" +) + +local styles = Cs ( + P("reverseoblique") / "reverseitalic" + + P("regular") / "normal" + + P("italic") + + P("oblique") / "italic" + + P("slanted") + + P("roman") / "normal" + + P("ital") / "italic" + + P("ita") / "italic" +) + +local widths = Cs( + P("condensed") + + P("thin") + + P("expanded") + + P("cond") / "condensed" + + P("normal") + + P("book") / "normal" +) + +local any = P(1) + +local analysed_table + +local analyser = Cs ( + ( + weights / function(s) analysed_table[1] = s return "" end + + styles / function(s) analysed_table[2] = s return "" end + + widths / function(s) analysed_table[3] = s return "" end + + any + )^0 +) + +local splitter = lpeg.splitat("-") + +function names.splitspec(askedname) + local name, weight, style, width = splitter:match(askedname) + weight = weight and weights:match(weight) or weight + style = style and styles :match(style) or style + width = width and widths :match(width) or width + if trace_names then + logs.report("fonts","requested name '%s' split in name '%s', weight '%s', style '%s' and width '%s'",askedname,name or '',weight or '',style or '',width or '') + end + if not weight or not weight or not width then + weight, style, width = weight or "normal", style or "normal", width or "normal" + if trace_names then + logs.report("fonts","request '%s' normalized to '%s-%s-%s-%s'",askedname,name,weight,style,width) + end + end + return name or askedname, weight, style, width +end + +local function analysespec(somename) + if somename then + analysed_table = { } + local name = analyser:match(somename) + return name, analysed_table[1], analysed_table[2],analysed_table[3] + end +end + --[[ldx--It would make sense to implement the filters in the related modules, but to keep the overview, we define them here.
@@ -104,16 +192,6 @@ filters.list = { "otf", "ttf", "ttc", "dfont", "afm", } -filters.fixes = { -- can be lpeg - { "bolita$", "bolditalic", }, - { "ital$", "italic", }, - { "cond$", "condensed", }, - { "book$", "", }, - { "reg$", "regular", }, - { "ita$", "italic", }, - { "bol$", "bold", }, -} - names.xml_configuration_file = "fonts.conf" -- a bit weird format, bonus feature names.environment_path_variable = "OSFONTDIR" -- the official way, in minimals etc @@ -149,7 +227,7 @@ function names.getpaths(trace) end end if name ~= "" and lfs.isfile(name) then - if trace then + if trace_names then logs.report("fontnames","loading fontconfig file: %s",name) end local xmldata = xml.load(name) @@ -162,17 +240,17 @@ function names.getpaths(trace) end end if lfs.isfile(incname) then - if trace then + if trace_names then logs.report("fontnames","merging included fontconfig file: %s",incname) end return io.loaddata(incname) - elseif trace then + elseif trace_names then logs.report("fontnames","ignoring included fontconfig file: %s",incname) end end) -- end of untested mess local fontdirs = xml.collect_texts(xmldata,"dir",true) - if trace then + if trace_names then logs.report("fontnames","%s dirs found in fontconfig",#fontdirs) end collect(fontdirs) @@ -185,77 +263,299 @@ function names.getpaths(trace) return result end -function names.cleanname(name) +local function cleanname(name) return (gsub(lower(name),"[^%a%d]","")) end -function names.identify(verbose) -- lsr is for kpse - names.data = { - version = names.version, - mapping = { }, - -- sorted = { }, - fallback_mapping = { }, - -- fallback_sorted = { }, +names.cleanname = cleanname + +local function check_names(result) + local names = result.names + if names then + for i=1,#names do + local name = names[i] + if name.lang == "English (US)" then + return name.names + end + end + end +end + +local function walk_tree(pathlist,suffix,identify) + if pathlist then + for _, path in ipairs(pathlist) do + path = resolvers.clean_path(path .. "/") + path = gsub(path,"/+","/") + local pattern = path .. "**." .. suffix -- ** forces recurse + logs.report("fontnames", "globbing path %s",pattern) + local t = dir.glob(pattern) + for _, completename in pairs(t) do -- ipairs + identify(completename,file.basename(completename),suffix,completename) + end + end + end +end + +local function check_name(data,result,filename,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 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 italicangle = tonumber(result.italicangle) + local subfont = subfont or nil + local rawname = fullname or fontname or familyname + -- normalize + familyname = familyname and cleanname(familyname) + fullname = fullname and cleanname(fullname) + fontname = fontname and cleanname(fontname) + subfamily = subfamily and cleanname(subfamily) + modifiers = modifiers and cleanname(modifiers) + weight = weight and cleanname(weight) + italicangle = (italicangle == 0) and nil + -- analyse + local a_name, a_weight, a_style, a_width = analysespec(fullname or fontname or familyname) + -- check + local width = a_width + local style = modifiers and gsub(modifiers,"[^%a]","") + if not style and italicangle then + style = "italic" + end + if not weight or weight == "" then + weight = a_weight + end + if not style or style == "" then + style = a_style + end + if not familyname then + familyname = a_name + end + fontname = fontname or fullname or familyname or basename + fullname = fullname or fontname + familyname = familyname or fontname + -- register + local index = #specifications + 1 + specifications[index] = { + filename = filename, + format = lower(suffix), + subfont = subfont, + rawname = rawname, + familyname = familyname, + fullname = fullname, + fontname = fontname, + subfamily = subfamily, + modifiers = modifiers, + weight = weight, + style = style, + width = width, } - local done, mapping, fallback_mapping, nofread, nofok = { }, names.data.mapping, names.data.fallback_mapping, 0, 0 - local cleanname = names.cleanname - local function check(result, filename, suffix, is_sub) -- unlocal this one - local fontname = result.fullname - if fontname then - local n = cleanname(result.fullname) - if not mapping[n] then - mapping[n], nofok = { lower(suffix), fontname, filename, is_sub }, nofok + 1 - end - end - if result.fontname then - fontname = result.fontname or fontname - local n = cleanname(result.fontname) - if not mapping[n] then - mapping[n], nofok = { lower(suffix), fontname, filename, is_sub }, nofok + 1 - end - end - if result.familyname and result.weight and result.italicangle == 0 then - local madename = result.familyname .. " " .. result.weight - fontname = madename or fontname - local n = cleanname(fontname) - if not mapping[n] and not fallback_mapping[n] then - fallback_mapping[n], nofok = { lower(suffix), fontname, filename, is_sub }, nofok + 1 - end - end - if result.names then - for k, v in ipairs(result.names) do - local lang, names = v.lang, v.names - if lang == "English (US)" then - local family, subfamily, fullnamet = names.family, names.subfamily, names.fullname - local preffamilyname, prefmodifiers, weight = names.preffamilyname, names.prefmodifiers, names.weight - if preffamilyname then - if subfamily then - local n = cleanname(preffamilyname .. " " .. subfamily) - if not mapping[n] and not fallback_mapping[n] then - fallback_mapping[n], nofok = { lower(suffix), fontname, filename, is_sub }, nofok + 1 - end - end - -- okay? - local n = cleanname(preffamilyname) - if not mapping[n] and not fallback_mapping[n] then - fallback_mapping[n], nofok = { lower(suffix), fontname, filename, is_sub }, nofok + 1 + local family = families[familyname] + if not family then + families[familyname] = { index } + else + family[#family+1] = index + end +end + +local function cleanupkeywords() + local data = names.data + local specifications = names.data.specifications + if specifications then + local weights, styles, widths, variants = { }, { }, { }, { } + for i=1,#specifications do + local s = specifications[i] + -- fix (sofar styles are taken from the name, and widths from the specification) + local b_variant, b_weight, b_style, b_width = analysespec(s.weight) + local c_variant, c_weight, c_style, c_width = analysespec(s.style) + local d_variant, d_weight, d_style, d_width = analysespec(s.width) + local e_variant, e_weight, e_style, e_width = analysespec(s.fullname or "") + local weight = b_weight or c_weight or d_weight or e_weight or "normal" + local style = b_style or c_style or d_style or e_style or "normal" + local width = b_width or c_width or d_width or e_width or "normal" + local variant = b_variant or c_variant or d_variant or e_variant or "normal" + 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 + if weight ~= s.weight then + s.fontweight = s.weight + end + s.weight, s.style, s.width, s.variant = weight, style, width, variant + end + local stats = data.statistics + stats.used_weights, stats.used_styles, stats.used_widths, stats.used_variants = weights, styles, widths, variants + end +end + +local function collectstatistics() + local data = names.data + local specifications = data.specifications + if specifications then + local weights, styles, widths = { }, { }, { } + for i=1,#specifications do + local s = specifications[i] + local weight, style, width = s.weight, s.style, s.width + 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 + end + local stats = data.statistics + stats.weights, stats.styles, stats.widths, stats.fonts = weights, styles, widths, #specifications + end +end + +local function collecthashes() + local data = names.data + local mappings = data.mappings + local fallbacks = data.fallbacks + local specifications = data.specifications + local nofmappings, noffallbacks = 0, 0 + if specifications then + for index=1,#specifications do + local s = specifications[index] + local format, fullname, fontname, familyname, weight, subfamily = s.format, s.fullname, s.fontname, s.familyname, s.weight, s.subfamily + local mf, ff = mappings[format], fallbacks[format] + if fullname and not mf[fullname] then + mf[fullname], nofmappings = index, nofmappings + 1 + end + if fontname and not mf[fontname] then + mf[fontname], nofmappings = index, nofmappings + 1 + end + if familyname and weight 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 + local extraname = familyname .. subfamily + if not mf[extraname] and not ff[extraname] then + ff[extraname], noffallbacks = index, noffallbacks + 1 + end + end + if familyname and subfamily then + if not mf[familyname] and not ff[familyname] then + ff[familyname], noffallbacks = index, noffallbacks + 1 + end + end + end + end + return nofmappings, noffallbacks +end + +local function checkduplicate(mapping) -- fails on "Romantik" but that's a border case anyway + local data = names.data + local mapping = data[mapping] + local specifications, loaded = data.specifications, { } + 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.familyname,s.weight or "*",s.style or "*",s.width or "*") + local h = loaded[hash] + if h then + local ok = true + local fn = s.filename + for i=1,#h do + local hn = s.filename + if h[i] == fn then + ok = false + break end end + if ok then + h[#h+1] = fn + end + else + loaded[hash] = { s.filename } end end end end - local trace = verbose or trace_names - local skip_paths = filters.paths - local skip_names = filters.names + for k, v in table.sortedpairs(loaded) do + if #v > 1 then + logs.report("fontnames", "double lookup: %s => %s",k,concat(v," | ")) + end + end +end + +local function checkduplicates() + checkduplicate("mappings") + checkduplicate("fallbacks") +end + +local sorter = function(a,b) + return #a < #b and 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 + 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) + sort(sorted_fallbacks[l],sorter) + end + data.sorted_families = table.keys(data.families) + sort(data.sorted_families,sorter) +end + +local function unpackreferences() + local data = names.data + local specifications = data.specifications + if specifications then + for k, v in next, data.families do + for i=1,#v do + v[i] = specifications[v[i]] + end + end + end + local mappings = data.mappings + if mappings then + for _, m in next, mappings do + for k, v in next, m do + m[k] = specifications[v] + end + end + end + local fallbacks = data.fallbacks + if fallbacks then + for _, f in next, fallbacks do + for k, v in next, f do + f[k] = specifications[v] + end + end + end +end + +local function analysefiles() + local data = names.data + local done, totalnofread, totalnofskipped = { }, 0, 0 + local skip_paths, skip_names = filters.paths, filters.names local function identify(completename,name,suffix,storedname) - if not done[name] and io.exists(completename) then + local basename = file.basename(completename) + local basepath = file.dirname(completename) + if done[name] then + -- already done (avoid otf afm clash) + elseif not io.exists(completename) then + -- weird error + elseif not file.is_qualified_path(completename) and resolvers.find_file(completename,suffix) == "" then + -- not locateble by backend anyway + else nofread = nofread + 1 if #skip_paths > 0 then - local path = file.dirname(completename) for i=1,#skip_paths do - if find(path,skip_paths[i]) then - if trace then + if find(basepath,skip_paths[i]) then + if trace_names then logs.report("fontnames","rejecting path of %s font %s",suffix,completename) logs.push() end @@ -264,11 +564,10 @@ function names.identify(verbose) -- lsr is for kpse end end if #skip_names > 0 then - local base = file.basename(completename) for i=1,#skip_paths do - if find(base,skip_names[i]) then + if find(basename,skip_names[i]) then done[name] = true - if trace then + if trace_names then logs.report("fontnames","rejecting name of %s font %s",suffix,completename) logs.push() end @@ -281,15 +580,21 @@ function names.identify(verbose) -- lsr is for kpse logs.push() end local result, message = filters[lower(suffix)](completename) - if trace then + if trace_names then logs.pop() end if result then if not result[1] then - check(result,storedname,suffix,false) -- was name + local ok = check_name(data,result,storedname,suffix) + if not ok then + nofskipped = nofskipped + 1 + end else for r=1,#result do - check(result[r],storedname,suffix,true) -- was name + local ok = check_name(data,result[r],storedname,suffix,r-1) -- subfonts start at zero + if not ok then + nofskipped = nofskipped + 1 + end end end if message and message ~= "" then @@ -301,33 +606,19 @@ function names.identify(verbose) -- lsr is for kpse done[name] = true end end - local totalread, totalok = 0, 0 local function traverse(what, method) for n, suffix in ipairs(filters.list) do - nofread, nofok = 0, 0 local t = os.gettimeofday() -- use elapser + nofread, nofskipped = 0, 0 suffix = lower(suffix) logs.report("fontnames", "identifying %s font files with suffix %s",what,suffix) method(suffix) suffix = upper(suffix) logs.report("fontnames", "identifying %s font files with suffix %s",what,suffix) method(suffix) - logs.report("fontnames", "%s %s files identified, %s hash entries added, runtime %0.3f seconds",nofread,what,nofok,os.gettimeofday()-t) - totalread, totalok = totalread + nofread, totalok + nofok - end - end - local function walk_tree(pathlist,suffix) - if pathlist then - for _, path in ipairs(pathlist) do - path = resolvers.clean_path(path .. "/") - path = gsub(path,"/+","/") - local pattern = path .. "**." .. suffix -- ** forces recurse - logs.report("fontnames", "globbing path %s",pattern) - local t = dir.glob(pattern) - for _, completename in pairs(t) do -- ipairs - identify(completename,file.basename(completename),suffix,completename) - end - end + totalnofread, totalnofskipped = totalnofread + nofread, totalnofskipped + nofskipped + local elapsed = os.gettimeofday() - t + logs.report("fontnames", "%s %s files identified, %s hash entries added, runtime %0.3f seconds",nofread,what,nofread-nofskipped,elapsed) end end traverse("tree", function(suffix) -- TEXTREE only @@ -343,43 +634,42 @@ function names.identify(verbose) -- lsr is for kpse -- using the vars is to clumsy so we just stick to a full scan instead traverse("lsr", function(suffix) -- all trees local pathlist = resolvers.split_path(resolvers.show_path("ls-R") or "") - walk_tree(pathlist,suffix) + walk_tree(pathlist,suffix,identify) end) else traverse("system", function(suffix) -- OSFONTDIR cum suis - walk_tree(names.getpaths(trace),suffix) + walk_tree(names.getpaths(trace),suffix,identify) end) end - local t = { } - for _, f in ipairs(filters.fixes) do - local expression, replacement = f[1], f[2] - for k,v in next, mapping do - local fix, pos = gsub(k,expression,replacement) - if pos > 0 and not mapping[fix] then - t[fix] = v - end - end - end - local n = 0 - for k,v in next, t do - mapping[k] = v - n = n + 1 - end - local rejected = 0 - for k, v in next, mapping do - local kind, filename = v[1], v[3] - if not file.is_qualified_path(filename) and resolvers.find_file(filename,kind) == "" then - mapping[k] = nil - rejected = rejected + 1 - end - end - if n > 0 then - logs.report("fontnames", "%s files read, %s normal and %s extra entries added, %s rejected, %s valid",totalread,totalok,n,rejected,totalok+n-rejected) + data.statistics.readfiles, data.statistics.skippedfiles = totalnofread, totalnofskipped +end + +local function resetdata() + local mappings, fallbacks = { }, { } + for _, k in next, filters.list do + mappings[k], fallbacks[k] = { }, { } end - names.analyse(mapping) - names.analyse(fallback_mapping) - names.checkduplicates(mapping) - names.checkduplicates(fallback_mapping) + names.data = { + version = names.version, + mappings = mappings, + fallbacks = fallbacks, + specifications = { }, + families = { }, + statistics = { }, + data_state = resolvers.data_state(), + } +end + +function names.identify() + resetdata() + analysefiles() + collectstatistics() + cleanupkeywords() + collecthashes() + checkduplicates() + -- sorthashes() -- will be resorted when saved + + --~ logs.report("fontnames", "%s files read, %s normal and %s extra entries added, %s rejected, %s valid",totalread,totalok,added,rejected,totalok+added-rejected) end function names.is_permitted(name) @@ -392,120 +682,6 @@ function names.read_data(name) return containers.read(names.cache(),name) end -local sorter = function(a,b) return #a < #b and a < b end - -function names.sorted(t) - local s = table.keys(t or { }) or { } - sort(s,sorted) - return s -end - ---~ local P, C, Cc = lpeg.P, lpeg.C, lpeg.Cc ---~ ---~ local weight = C(P("demibold") + P("semibold") + P("mediumbold") + P("ultrabold") + P("bold") + P("demi") + P("semi") + P("light") + P("medium") + P("heavy") + P("ultra") + P("black")) ---~ local style = C(P("regular") + P("italic") + P("oblique") + P("slanted") + P("roman") + P("ital")) ---~ local width = C(P("condensed") + P("normal") + P("expanded") + P("cond")) ---~ local special = P("roman") ---~ local reserved = style + weight + width ---~ local any = (1-reserved) ---~ local name = C((special + any)^1) ---~ local crap = any^0 ---~ local dummy = Cc(false) ---~ local normal = Cc("normal") ---~ local analyser = name * (weight + normal) * crap * (style + normal) * crap * (width + normal) * crap ---~ ---~ function names.analyse(mapping) ---~ for k, v in next, mapping do ---~ -- fails on "Romantik" but that's a border case anyway ---~ local name, weight, style, width = analyser:match(k) ---~ v[5], v[6], v[7], v[8] = name or k, weight or "normal", style or "normal", width or "normal" ---~ end ---~ end - -local P, C, Cc, Cs, Carg = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Carg - -local weight = C(P("demibold") + P("semibold") + P("mediumbold") + P("ultrabold") + P("bold") + P("demi") + P("semi") + P("light") + P("medium") + P("heavy") + P("ultra") + P("black")) -local style = C(P("regular") + P("italic") + P("oblique") + P("slanted") + P("roman") + P("ital")) -local width = C(P("condensed") + P("normal") + P("expanded") + P("cond")) -local strip = P("book") + P("roman") -local any = P(1) - -local t - -local analyser = Cs ( - ( - strip / "" + - weight / function(s) t[6] = s return "" end + - style / function(s) t[7] = s return "" end + - width / function(s) t[8] = s return "" end + - any - )^0 -) - -local stripper = Cs ( - ( - strip / "" + - any - )^0 -) - -function names.analyse(mapping) -- fails on "Romantik" but that's a border case anyway - for k, v in next, mapping do - t = v - t[5] = analyser:match(k) -- somehow Carg fails - v[5], v[6], v[7], v[8] = t[5] or k, t[6] or "normal", t[7] or "normal", t[8] or "normal" - end -end - -local splitter = lpeg.splitat("-") - -function names.splitspec(askedname) - local name, weight, style, width = splitter:match(stripper:match(askedname) or askedname) - if trace_names then - logs.report("fonts","requested name '%s' split in name '%s', weight '%s', style '%s' and width '%s'",askedname,name or '',weight or '',style or '',width or '') - end - if not weight or not weight or not width then - weight, style, width = weight or "normal", style or "normal", width or "normal" - if trace_names then - logs.report("fonts","request '%s' normalized to '%s-%s-%s-%s'",askedname,name,weight,style,width) - end - end - return name or askedname, weight, style, width -end - -function names.checkduplicates(mapping) -- fails on "Romantik" but that's a border case anyway - local loaded = { } - for k, v in next, mapping do - local hash = format("%s-%s-%s-%s",v[5],v[6],v[7],v[8]) - local h = loaded[hash] - if h then - local ok = true - local fn = v[3] - for i=1,#h do - local hn = mapping[h[i]][3] - if hn == fn then - ok = false - break - end - end - if ok then - h[#h+1] = k - end - else - loaded[hash] = { h } - end - end - for k, v in table.sortedpairs(loaded) do - if #v > 1 then - for i=1,#v do - local vi = v[i] - v[i] = format("%s = %s",vi,mapping[vi][3]) - end - logs.report("fonts", "double lookup: %s => %s",k,concat(v," | ")) - end - end -end - function names.load(reload,verbose) if not names.loaded then if reload then @@ -516,51 +692,85 @@ function names.load(reload,verbose) logs.report("font table", "unable to access database cache") end names.saved = true - else - names.data = names.read_data(names.basename) - if not names.saved then - if table.is_empty(names.data) or table.is_empty(names.data.mapping) then - names.load(true) - end - names.saved = true + end + local data = names.read_data(names.basename) + names.data = data + if not names.saved then + if not next(data) or not next(data.specifications) then + names.load(true) end + names.saved = true end - local data = names.data - -- names.analyse(data.mapping) - -- names.analyse(data.fallback_mapping) - if data then - data.sorted = names.sorted(data.mapping) - data.fallback_sorted = names.sorted(data.fallback_mapping) - else + if not data then logs.report("font table", "accessing the data table failed") + else + unpackreferences() + sorthashes() end names.loaded = true end end -function names.list(pattern,reload) +local function list_them(mapping,sorted,pattern,t,all) + if mapping[pattern] then + t[pattern] = mapping[pattern] + else + for k=1,#sorted do + local v = sorted[k] + if find(v,pattern) then + t[v] = mapping[v] + if not all then + return + end + end + end + end +end + +function names.list(pattern,reload,all) -- here? names.load(reload) if names.loaded then local t = { } - local function list_them(mapping,sorted) - if mapping[pattern] then - t[pattern] = mapping[pattern] - else - for k,v in ipairs(sorted) do - if find(v,pattern) then - t[v] = mapping[v] - end + 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 + for i=1,#list do + local format = list[i] + list_them(mappings[format],sorted_mappings[format],pattern,t,all) + if next(t) and not all then + return t + end + list_them(fallbacks[format],sorted_fallbacks[format],pattern,t,all) + if next(t) and not all then + return t end end end + return t + end +end + +local reloaded = false + +local function is_reloaded() + if not reloaded then local data = names.data - if data then - list_them(data.mapping,data.sorted) - list_them(data.fallback_mapping,data.fallback_sorted) + if names.autoreload then + local c_status = table.serialize(resolvers.data_state()) + local f_status = table.serialize(data.data_state) + if c_status == f_status then + logs.report("fonts","font database matches configuration and file hashes") + return + else + logs.report("fonts","font database does not match configuration and file hashes") + end end - return t - else - return nil + names.loaded = false + reloaded = true + io.flush() + names.load(true) end end @@ -570,231 +780,326 @@ here is for testing purposes only (it deals with names prefixed by an encoding name). --ldx]]-- -local function found_indeed(mapping,sorted,name) - local mn = mapping[name] - if mn then - return mn[2], mn[3], mn[4] +-- if names.be_clever then -- this will become obsolete +-- local encoding, tag = match(name,"^(.-)[%-%:](.+)$") +-- local mt = mapping[tag] +-- if tag and fonts.enc.is_known(encoding) and mt then +-- return mt[1], encoding .. "-" .. mt[3], mt[4] +-- end +-- end + +-- simple search + +local function found(mapping,sorted,name,sub) + local found = mapping[name] + -- obsolete: old encoding test + if not found then + for k,v in next, mapping do + if find(k,name) then + found = v + break + end + end + if not found then + local condensed = gsub(name,"[^%a%d]","") + found = mapping[condensed] + if not found then + for k=1,#sorted do + local v = sorted[k] + if find(v,condensed) then + found = mapping[v] + break + end + end + end + end + end + return found +end + +local function foundname(name,sub) + 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 + for i=1,#list do + local l = list[i] + local okay = found(mappings[l],sorted_mappings[l],name,sub) or found(fallbacks[l],sorted_fallbacks[l],name,sub) + if okay then + return okay + end + end +end + +function names.resolve(askedname,sub) + if askedname and askedname ~= "" and names.enabled then + askedname = cleanname(askedname) + names.load() + local found = foundname(askedname,sub) + if not found and is_reloaded() then + found = foundname(askedname,sub) + end + if found then + return found.filename, found.subfont and found.rawname + end + end +end + +-- specified search + +local function s_collect_weight_style_width(found,done,all,weight,style,width,family) + if family then + for i=1,#family do + local f = family[i] + if f and weight == f.weight and style == f.style and width == f.width then + found[#found+1], done[f] = f, true + if not all then return end + end + end end - if names.be_clever then -- this will become obsolete - local encoding, tag = match(name,"^(.-)[%-%:](.+)$") - local mt = mapping[tag] - if tag and fonts.enc.is_known(encoding) and mt then - return mt[1], encoding .. "-" .. mt[3], mt[4] +end +local function m_collect_weight_style_width(found,done,all,weight,style,width,families,sorted,strictname) + for i=1,#sorted do + local k = sorted[i] + local family = families[k] + for i=1,#family do + local f = family[i] + if not done[f] and weight == f.weight and style == f.style and width == f.width and find(f.fontname,strictname) then + found[#found+1], done[f] = f, true + if not all then return end + end + end + end +end + +local function s_collect_weight_style(found,done,all,weight,style,family) + if family then + for i=1,#family do local f = family[i] + if f and weight == f.weight and style == f.style then + found[#found+1], done[f] = f, true + if not all then return end + end end end - -- name, type, file - for k,v in next, mapping do - if find(k,name) then - return v[2], v[3], v[4] +end +local function m_collect_weight_style(found,done,all,weight,style,families,sorted,strictname) + for i=1,#sorted do + local k = sorted[i] + local family = families[k] + for i=1,#family do + local f = family[i] + if not done[f] and weight == f.weight and style == f.style and find(f.fontname,strictname) then + found[#found+1], done[f] = f, true + if not all then return end + end end end - local condensed = gsub(name,"[^%a%d]","") - local mc = mapping[condensed] - if mc then - return mc[2], mc[3], mc[4] +end + +local function s_collect_style_width(found,done,all,style,width,family) + if family then + for i=1,#family do local f = family[i] + if f and style == f.style and width == f.width then + found[#found+1], done[f] = f, true + if not all then return end + end + end end - for k=1,#sorted do - local v = sorted[k] - if find(v,condensed) then - v = mapping[v] - return v[2], v[3], v[4] +end +local function m_collect_style_width(found,done,all,style,width,families,sorted,strictname) + for i=1,#sorted do + local k = sorted[i] + local family = families[k] + for i=1,#family do + local f = family[i] + if not done[f] and style == f.style and width == f.width and find(f.fontname,strictname) then + found[#found+1], done[f] = f, true + if not all then return end + end end end - return nil, nil, nil end -local function found(name) - if name and name ~= "" and names.data then - name = names.cleanname(name) - local data = names.data - local fontname, filename, is_sub = found_indeed(data.mapping, data.sorted, name) - if not fontname or not filename then - fontname, filename, is_sub = found_indeed(data.fallback_mapping, data.fallback_sorted, name) +local function s_collect_weight(found,done,all,weight,family) + if family then + for i=1,#family do local f = family[i] + if f and weight == f.weight then + found[#found+1], done[f] = f, true + if not all then return end + end + end + end +end +local function m_collect_weight(found,done,all,weight,families,sorted,strictname) + for i=1,#sorted do + local k = sorted[i] + local family = families[k] + for i=1,#family do + local f = family[i] + if not done[f] and weight == f.weight and find(f.fontname,strictname) then + found[#found+1], done[f] = f, true + if not all then return end + end end - return fontname, filename, is_sub - else - return nil, nil, nil end end -local function collect(stage,mapping,sorted,found,done,name,weight,style,width,all) - if not mapping or not sorted then - return +local function s_collect_style(found,done,all,style,family) + if family then + for i=1,#family do local f = family[i] + if f and style == f.style then + found[#found+1], done[f] = f, true + if not all then return end + end + end + end +end +local function m_collect_style(found,done,all,style,families,sorted,strictname) + for i=1,#sorted do + local k = sorted[i] + local family = families[k] + for i=1,#family do + local f = family[i] + if not done[f] and style == f.style and find(f.fontname,strictname) then + found[#found+1], done[f] = f, true + if not all then return end + end + end end -strictname = "^".. name - local f = mapping[name] - if weight ~= "" then - if style ~= "" then - if width ~= "" then +end + +local function s_collect_width(found,done,all,width,family) + if family then + for i=1,#family do local f = family[i] + if f and width == f.width then + found[#found+1], done[f] = f, true + if not all then return end + end + end + end +end +local function m_collect_width(found,done,all,width,families,sorted,strictname) + for i=1,#sorted do + local k = sorted[i] + local family = families[k] + for i=1,#family do + local f = family[i] + if not done[f] and width == f.width and find(f.fontname,strictname) then + found[#found+1], done[f] = f, true + if not all then return end + end + end + end +end + +local function s_collect(found,done,all,family) + if family then + for i=1,#family do local f = family[i] + if f then + found[#found+1], done[f] = f, true + if not all then return end + end + end + end +end +local function m_collect(found,done,all,families,sorted,strictname) + for i=1,#sorted do + local k = sorted[i] + local family = families[k] + for i=1,#family do + local f = family[i] + if not done[f] and find(f.fontname,strictname) then + found[#found+1], done[f] = f, true + if not all then return end + end + end + end +end + +local function collect(stage,found,done,name,weight,style,width,all) + local data = names.data + local families, sorted = data.families, data.sorted_families + strictname = "^".. name -- to be checked + local family = families[name] + if trace_names then + logs.report("fonts","resolving name '%s', weight '%s', style '%s', width '%s'",name or "?",tostring(weight),tostring(style),tostring(width)) + end + if weight and weight ~= "" then + if style and style ~= "" then + if width and width ~= "" then if trace_names then logs.report("fonts","resolving stage %s, name '%s', weight '%s', style '%s', width '%s'",stage,name,weight,style,width) end - if f and width ~= f[8] and style == f[7] and weight == f[6] then - found[#found+1], done[name] = f, true - if not all then return end - end - for i=1,#sorted do - local k = sorted[i] - if not done[k] then - local v = mapping[k] - if v[6] == weight and v[7] == style and v[8] == width and find(v[5],strictname) then - found[#found+1], done[k] = v, true - if not all then return end - end - end - 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) else if trace_names then logs.report("fonts","resolving stage %s, name '%s', weight '%s', style '%s'",stage,name,weight,style) end - if f and style == f[7] and weight == f[6] then - found[#found+1], done[name] = f, true - if not all then return end - end - for i=1,#sorted do - local k = sorted[i] - if not done[k] then - local v = mapping[k] - if v[6] == weight and v[7] == style and find(v[5],strictname) then - found[#found+1], done[k] = v, true - if not all then return end - end - end - 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 logs.report("fonts","resolving stage %s, name '%s', weight '%s'",stage,name,weight) end - if f and weight == f[6] then - found[#found+1], done[name] = f, true - if not all then return end - end - for i=1,#sorted do - local k = sorted[i] - if not done[k] then - local v = mapping[k] - if v[6] == weight and find(v[5],strictname) then - found[#found+1], done[k] = v, true - if not all then return end - end - end - end + s_collect_weight(found,done,all,weight,family) + m_collect_weight(found,done,all,weight,families,sorted,strictname) end - elseif style ~= "" then - if width ~= "" then + elseif style and style ~= "" then + if width and width ~= "" then if trace_names then logs.report("fonts","resolving stage %s, name '%s', style '%s', width '%s'",stage,name,style,width) end - if f and style == f[7] and width == f[8] then - found[#found+1], done[name] = f, true - if not all then return end - end - for i=1,#sorted do - local k = sorted[i] - if not done[k] then - local v = mapping[k] - if v[7] == style and v[8] == width and find(v[5],strictname) then - found[#found+1], done[k] = v, true - if not all then return end - end - end - 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 logs.report("fonts","resolving stage %s, name '%s', style '%s'",stage,name,style) end - if f and style == f[7] then - found[#found+1], done[name] = f, true - if not all then return end - end - for i=1,#sorted do - local k = sorted[i] - if not done[k] then - local v = mapping[k] - if v[7] == style and find(v[5],strictname) then - found[#found+1], done[k] = v, true - if not all then return end - end - end - end + s_collect_style(found,done,all,style,family) + m_collect_style(found,done,all,style,families,sorted,strictname) end - elseif width ~= "" then + elseif width and width ~= "" then if trace_names then logs.report("fonts","resolving stage %s, name '%s', width '%s'",stage,name,width) end - if f and width == f[8] then - found[#found+1], done[name] = f, true - if not all then return end - end - for i=1,#sorted do - local k = sorted[i] - if not done[k] then - local v = mapping[k] - if v[8] == width and find(v[5],strictname) then - found[#found+1], done[k] = v, true - if not all then return end - end - end - end + s_collect_width(found,done,all,width,family) + m_collect_width(found,done,all,width,families,sorted,strictname) else if trace_names then logs.report("fonts","resolving stage %s, name '%s'",stage,name) end - if f then - found[#found+1], done[name] = f, true - if not all then return end - end - for i=1,#sorted do - local k = sorted[i] - if not done[k] then - local v = mapping[k] - if find(v[5],strictname) then - found[#found+1], done[k] = v, true - if not all then return end - end - end - end + s_collect(found,done,all,family) + m_collect(found,done,all,families,sorted,strictname) end end function heuristic(name,weight,style,width,all) -- todo: fallbacks local found, done = { }, { } - local data = names.data - local mapping, sorted, fbmapping, fbsorted = data.mapping, data.sorted, data.fallback_mapping, data.fallback_sorted weight, style = weight or "", style or "" - name = names.cleanname(name) - collect(1,mapping,sorted,found,done,name,weight,style,width,all) - if #found == 0 then - collect(2,fbmapping,fbsorted,found,done,name,weight,style,width,all) - end + name = cleanname(name) + collect(1,found,done,name,weight,style,width,all) + -- still needed ? if #found == 0 and width ~= "" then - width = "normal" - collect(3,mapping,sorted,found,done,name,weight,style,width,all) - if #found == 0 then - collect(4,fbmapping,fbsorted,found,done,name,weight,style,width,all) - end + width = "" + collect(2,found,done,name,weight,style,width,all) end if #found == 0 and weight ~= "" then -- not style - weight = "normal" - collect(5,mapping,sorted,found,done,name,weight,style,width,all) - if #found == 0 then - collect(6,fbmapping,fbsorted,found,done,name,weight,style,width,all) - end + weight = "" + collect(3,found,done,name,weight,style,width,all) end if #found == 0 and style ~= "" then -- not weight - style = "normal" - collect(7,mapping,sorted,found,done,name,weight,style,width,all) - if #found == 0 then - collect(8,fbmapping,fbsorted,found,done,name,weight,style,width,all) - end + style = "" + collect(4,found,done,name,weight,style,width,all) end + -- local nf = #found if trace_names then if nf then local t = { } for i=1,nf do - t[#t+1] = format("'%s'",found[i][2]) + t[#t+1] = format("'%s'",found[i].fontname) end logs.report("fonts","name '%s' resolved to %s instances: %s",name,nf,concat(t," ")) else @@ -803,63 +1108,48 @@ function heuristic(name,weight,style,width,all) -- todo: fallbacks end if all then return nf > 0 and found - elseif nf > 0 then - local f = found[1] - return f[2], f[3], f[4] else - return nil, nil, nil + return found[1] end end -local reloaded = false - -function names.specification(askedname,weight,style,width) +function names.specification(askedname,weight,style,width,reload,all) if askedname and askedname ~= "" and names.enabled then askedname = lower(askedname) -- or cleanname - names.load() - local name, filename, is_sub = heuristic(askedname,weight,style,width) - if not filename and not reloaded and names.autoreload then - names.loaded = false - reloaded = true - io.flush() - names.load(true) - name, filename, is_sub = heuristic(askedname,weight,style,width) + names.load(reload) + local found = heuristic(askedname,weight,style,width,all) + if not found and is_reloaded() then + found = heuristic(askedname,weight,style,width,all) if not filename then - name, filename, is_sub = found(askedname) -- old method + found = foundname(askedname) -- old method end end - return name, filename, is_sub + return found end end -function names.collect(askedname,weight,style,width) +function names.collect(askedname,weight,style,width,reload,all) if askedname and askedname ~= "" and names.enabled then askedname = lower(askedname) -- or cleanname - names.load() + names.load(reload) local list = heuristic(askedname,weight,style,width,true) - if not list or #list == 0 and not reloaded and names.autoreload then - names.loaded = false - reloaded = true - io.flush() - names.load(true) + if not list or #list == 0 and is_reloaded() then list = heuristic(askedname,weight,style,width,true) end return list end end -function names.resolve(askedname, sub) - local name, filename, is_sub = names.specification(askedname) - return filename, (is_sub and name) or sub -end - -function names.collectspec(askedname) - return names.collect(names.splitspec(askedname)) +function names.collectspec(askedname,reload,all) + local name, weight, style, width = names.splitspec(askedname) + return names.collect(name,weight,style,width,reload,all) end function names.resolvespec(askedname,sub) - local name, filename, is_sub = names.specification(names.splitspec(askedname)) - return filename, (is_sub and name) or sub + local found = names.specification(names.splitspec(askedname)) + if found then + return found.filename, found.subfont and found.rawname + end end --[[ldx-- @@ -924,3 +1214,89 @@ function names.exists(name) names.autoreload = fna return found 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 + if lastpattern ~= pattern then + names.load(reload) + local specifications = names.data.specifications + local families = names.data.families + local lookups = specifications + if name then + lookups = families[name] + elseif not find(pattern,"=") then + lookups = families[pattern] + end + if trace_names then + logs.report("fonts","starting with %s lookups for '%s'",#lookups,pattern) + end + if lookups then + for key, value in gmatch(pattern,"([^=,]+)=([^=,]+)") do + local t = { } + for i=1,#lookups do + local s = lookups[i] + if s[key] == value then + t[#t+1] = lookups[i] + end + end + if trace_names then + logs.report("fonts","%s matches for key '%s' with value '%s'",#t,key,value) + end + lookups = t + end + end + lastpattern = pattern + lastlookups = lookups or { } + end + return #lastlookups +end + +function names.getlookupkey(key,n) + local l = lastlookups[n or 1] + return (l and l[key]) or "" +end + +function names.noflookups() + return #lastlookups +end + +function names.getlookups(pattern,name,reload) + if pattern then + names.lookup(pattern,name,reload) + end + return lastlookups +end + +function table.formatcolumns(result) + if result and #result > 0 then + local widths = { } + local first = result[1] + local n = #first + for i=1,n do + widths[i] = 0 + end + for i=1,#result do + local r = result[i] + for j=1,n do + local w = #r[j] + if w > widths[j] then + widths[j] = w + end + end + end + for i=1,n do + widths[i] = "%-" .. widths[i] .. "s" + end + local template = concat(widths," ") + for i=1,#result do + local str = format(template,unpack(result[i])) + result[i] = string.strip(str) + end + end + return result +end diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua index 576829369..2794a947a 100644 --- a/tex/context/base/font-tfm.lua +++ b/tex/context/base/font-tfm.lua @@ -533,15 +533,15 @@ local private = fonts.private end -- needed for \high cum suis local tpx = tp.x_height -if hasmath then - if not tp[13] then tp[13] = .86*tpx end -- mathsupdisplay - if not tp[14] then tp[14] = .86*tpx end -- mathsupnormal - if not tp[15] then tp[15] = .86*tpx end -- mathsupcramped - if not tp[16] then tp[16] = .48*tpx end -- mathsubnormal - if not tp[17] then tp[17] = .48*tpx end -- mathsubcombined - if not tp[22] then tp[22] = 0 end -- mathaxisheight - if t.MathConstants then t.MathConstants.AccentBaseHeight = nil end -- safeguard -end + if hasmath then + if not tp[13] then tp[13] = .86*tpx end -- mathsupdisplay + if not tp[14] then tp[14] = .86*tpx end -- mathsupnormal + if not tp[15] then tp[15] = .86*tpx end -- mathsupcramped + if not tp[16] then tp[16] = .48*tpx end -- mathsubnormal + if not tp[17] then tp[17] = .48*tpx end -- mathsubcombined + if not tp[22] then tp[22] = 0 end -- mathaxisheight + if t.MathConstants then t.MathConstants.AccentBaseHeight = nil end -- safeguard + end t.tounicode = 1 t.cidinfo = tfmtable.cidinfo -- we have t.name=metricfile and t.fullname=RealName and t.filename=diskfilename @@ -549,20 +549,21 @@ end -- can have multiple subfonts if hasmath then if trace_defining then - logs.report("define font","math enabled for: %s %s %s",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") + logs.report("define font","math enabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") end else if trace_defining then - logs.report("define font","math disabled for: %s %s %s",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") + logs.report("define font","math disabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") end t.nomath, t.MathConstants = true, nil end - -- fullname is used in the subsetting if not t.psname then - t.psname = t.fullname -- else bad luck + -- name used in pdf file as well as for selecting subfont in ttc/dfont + t.psname = t.fontname or (t.fullname and fonts.names.cleanname(t.fullname)) end if trace_defining then - logs.report("define font","used for subsetting: %s ",t.fullname or "nofullname") + logs.report("define font","used for accesing subfont: '%s'",t.psname or "nopsname") + logs.report("define font","used for subsetting: '%s'",t.fontname or "nofontname") end return t, delta end diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua index 0fc40b38b..44447a7ad 100644 --- a/tex/context/base/grph-inc.lua +++ b/tex/context/base/grph-inc.lua @@ -667,7 +667,12 @@ function figures.includers.generic(data) end if figure then local n = figures.boxnumber - tex.box[n] = img.node(figure) -- img.write(figure) + tex.box[n] = node.hpack(img.node(figure)) + -- tex.box[n] = img.node(figure) -- img.write(figure) -- assigning img.node directly no longer valid +--~ local inode = img.node(figure) +--~ print(table.serialize(nodes.totable(inode))) +--~ tex.box[n] = inode +--~ print(table.serialize(nodes.totable(tex.box[n]))) tex.wd[n], tex.ht[n], tex.dp[n] = figure.width, figure.height, 0 -- new, hm, tricky, we need to do that in tex (yet) ds.objectnumber = figure.objnum texsprint(ctxcatcodes,"\\relocateexternalfigure") diff --git a/tex/context/base/lang-ini.lua b/tex/context/base/lang-ini.lua index b7b908144..c251ab1a6 100644 --- a/tex/context/base/lang-ini.lua +++ b/tex/context/base/lang-ini.lua @@ -280,7 +280,7 @@ end languages.words = languages.words or {} languages.words.data = languages.words.data or {} -languages.words.enable = false +languages.words.enables = false languages.words.threshold = 4 languages.words.colors = { @@ -426,7 +426,7 @@ do local color = attributes.private('color') function languages.words.check(head) - if lw.enable and head.next then + if lw.enabled and head.next then local colors = lw.colors local alc = attributes.list[color] return lw.methods[lw.method](head, color, alc[colors.known], alc[colors.unknown]) @@ -435,6 +435,15 @@ do end end + function languages.words.enable() + tasks.enableaction("processors","languages.words.check") + languages.words.enabled = true + end + + function languages.words.disable() + languages.words.enabled = false + end + end -- for the moment we hook it into the attribute handler diff --git a/tex/context/base/lang-ini.mkiv b/tex/context/base/lang-ini.mkiv index f88281a60..86870d635 100644 --- a/tex/context/base/lang-ini.mkiv +++ b/tex/context/base/lang-ini.mkiv @@ -567,8 +567,8 @@ \def\setupspellchecking[#1]% todo colors {\getparameters[\??wl][#1]% \doifelse\@@wlstate\v!start - {\ctxlua{languages.words.enable=true }} - {\ctxlua{languages.words.enable=false}}} + {\ctxlua{languages.words.enable()}} + {\ctxlua{languages.words.disable()}}} \setupspellchecking [\c!state=\v!stop] diff --git a/tex/context/base/m-pstric.tex b/tex/context/base/m-pstric.tex index ac018fe07..f4be08dbd 100644 --- a/tex/context/base/m-pstric.tex +++ b/tex/context/base/m-pstric.tex @@ -13,6 +13,9 @@ %M \usemodule[pstric] +\letvalue{@unused}\plussixteen +\letvalue{alloc@}\gobblefivearguments + \chardef\oldbarcode\the\catcode`\| \catcode`\|=12 \def\loadpstrickscolors#1% diff --git a/tex/context/base/math-vfu.lua b/tex/context/base/math-vfu.lua index 0300bb07f..1a8979160 100644 --- a/tex/context/base/math-vfu.lua +++ b/tex/context/base/math-vfu.lua @@ -371,7 +371,7 @@ function fonts.vf.math.define(specification,set) if trace_virtual then logs.report("math virtual", "unicode point U+%05X has no index %04X in vector %s for font %s",unicode,index,vectorname,fontname) elseif not already_reported then - logs.report("math virtual", "the mapping is incomplete for '%s' at %s",name,size) + logs.report("math virtual", "the mapping is incomplete for '%s' at %s",name,number.topoints(size)) already_reported = true end rv[unicode] = true @@ -747,6 +747,23 @@ fonts.enc.math["tex-mi"] = { [0x0003E] = 0x3E, -- > [0x022C6] = 0x3F, -- star [0x02202] = 0x40, -- partial +-- + [0x0266D] = 0x5B, -- flat + [0x0266E] = 0x5C, -- natural + [0x0266F] = 0x5D, -- sharp + [0x02323] = 0x5E, -- smile + [0x02322] = 0x5F, -- frown + [0x02113] = 0x60, -- ell +-- + [0x1D6A4] = 0x7B, -- imath (TODO: also 0131) + [0x1D6A5] = 0x7C, -- jmath (TODO: also 0237) + [0x02118] = 0x7D, -- wp + [0x020D7] = 0x7E, -- vec (TODO: not sure) +-- 0x7F, -- (no idea what that could be) +} + + +fonts.enc.math["tex-it"] = { -- [0x00041] = 0x41, -- A [0x1D6E2] = 0x41, -- Alpha -- [0x00042] = 0x42, -- B @@ -786,12 +803,6 @@ fonts.enc.math["tex-mi"] = { -- [0x00059] = 0x59, -- Y -- [0x0005A] = 0x5A, -- Z [0x1D6E7] = 0x5A, -- Zeta - [0x0266D] = 0x5B, -- flat - [0x0266E] = 0x5C, -- natural - [0x0266F] = 0x5D, -- sharp - [0x02323] = 0x5E, -- smile - [0x02322] = 0x5F, -- frown - [0x02113] = 0x60, -- ell -- [0x00061] = 0x61, -- a -- [0x00062] = 0x62, -- b -- [0x00063] = 0x63, -- c @@ -800,7 +811,7 @@ fonts.enc.math["tex-mi"] = { -- [0x00066] = 0x66, -- f -- [0x00067] = 0x67, -- g -- [0x00068] = 0x68, -- h - [0x0210E] = 0x68, -- plant constant + [0x0210E] = 0x68, -- plank constant -- [0x00069] = 0x69, -- i -- [0x0006A] = 0x6A, -- j -- [0x0006B] = 0x6B, -- k @@ -820,11 +831,6 @@ fonts.enc.math["tex-mi"] = { -- [0x00078] = 0x78, -- x -- [0x00079] = 0x79, -- y -- [0x0007A] = 0x7A, -- z - [0x1D6A4] = 0x7B, -- imath (TODO: also 0131) - [0x1D6A5] = 0x7C, -- jmath (TODO: also 0237) - [0x02118] = 0x7D, -- wp - [0x020D7] = 0x7E, -- vec (TODO: not sure) --- 0x7F, -- (no idea what that could be) } fonts.enc.math["tex-ss"] = { } @@ -1314,7 +1320,7 @@ fonts.enc.math["tex-fraktur"] = { -- now that all other vectors are defined ... -fonts.vf.math.set_letters(fonts.enc.math, "tex-mi", 0x1D434, 0x1D44E) +fonts.vf.math.set_letters(fonts.enc.math, "tex-it", 0x1D434, 0x1D44E) fonts.vf.math.set_letters(fonts.enc.math, "tex-ss", 0x1D5A0, 0x1D5BA) fonts.vf.math.set_letters(fonts.enc.math, "tex-tt", 0x1D670, 0x1D68A) fonts.vf.math.set_letters(fonts.enc.math, "tex-bf", 0x1D400, 0x1D41A) @@ -1342,6 +1348,7 @@ mathematics.make_font ( "lmroman5-math", { { name = "lmroman5-regular.otf", features = "virtualmath", main = true }, { name = "rm-lmr5.tfm", vector = "tex-mr-missing" } , { name = "lmmi5.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "lmmi5.tfm", vector = "tex-it", skewchar=0x7F }, { name = "lmsy5.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "lmex10.tfm", vector = "tex-ex", extension = true } , { name = "msam5.tfm", vector = "tex-ma" }, @@ -1363,6 +1370,7 @@ mathematics.make_font ( "lmroman6-math", { { name = "lmroman6-regular.otf", features = "virtualmath", main = true }, { name = "rm-lmr6.tfm", vector = "tex-mr-missing" } , { name = "lmmi6.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "lmmi6.tfm", vector = "tex-it", skewchar=0x7F }, { name = "lmsy6.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "lmex10.tfm", vector = "tex-ex", extension = true } , { name = "msam5.tfm", vector = "tex-ma" }, @@ -1387,6 +1395,7 @@ mathematics.make_font ( "lmroman7-math", { { name = "lmroman7-regular.otf", features = "virtualmath", main = true }, { name = "rm-lmr7.tfm", vector = "tex-mr-missing" } , { name = "lmmi7.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "lmmi7.tfm", vector = "tex-it", skewchar=0x7F }, { name = "lmsy7.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "lmex10.tfm", vector = "tex-ex", extension = true } , { name = "msam7.tfm", vector = "tex-ma" }, @@ -1409,6 +1418,7 @@ mathematics.make_font ( "lmroman8-math", { { name = "lmroman8-regular.otf", features = "virtualmath", main = true }, { name = "rm-lmr8.tfm", vector = "tex-mr-missing" } , { name = "lmmi8.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "lmmi8.tfm", vector = "tex-it", skewchar=0x7F }, { name = "lmsy8.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "lmex10.tfm", vector = "tex-ex", extension = true } , { name = "msam7.tfm", vector = "tex-ma" }, @@ -1431,6 +1441,7 @@ mathematics.make_font ( "lmroman9-math", { { name = "lmroman9-regular.otf", features = "virtualmath", main = true }, { name = "rm-lmr9.tfm", vector = "tex-mr-missing" } , { name = "lmmi9.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "lmmi9.tfm", vector = "tex-it", skewchar=0x7F }, { name = "lmsy9.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "lmex10.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1456,6 +1467,7 @@ mathematics.make_font ( "lmroman10-math", { { name = "lmroman10-regular.otf", features = "virtualmath", main = true }, { name = "rm-lmr10.tfm", vector = "tex-mr-missing" } , { name = "lmmi10.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "lmmi10.tfm", vector = "tex-it", skewchar=0x7F }, { name = "lmsy10.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "lmex10.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1473,6 +1485,7 @@ mathematics.make_font ( "lmroman10-boldmath", { { name = "lmroman10-bold.otf", features = "virtualmath", main = true }, { name = "rm-lmr10.tfm", vector = "tex-mr-missing" } , { name = "lmmib10.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "lmmib10.tfm", vector = "tex-it", skewchar=0x7F }, { name = "lmbsy10.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "lmex10.tfm", vector = "tex-ex", extension = true } , -- copied from roman: @@ -1495,6 +1508,7 @@ mathematics.make_font ( "lmroman12-math", { { name = "lmroman12-regular.otf", features = "virtualmath", main = true }, { name = "rm-lmr12.tfm", vector = "tex-mr-missing" } , { name = "lmmi12.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "lmmi12.tfm", vector = "tex-it", skewchar=0x7F }, { name = "lmsy10.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "lmex10.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1514,6 +1528,7 @@ mathematics.make_font ( "lmroman17-math", { { name = "lmroman17-regular.otf", features = "virtualmath", main = true }, { name = "rm-lmr12.tfm", vector = "tex-mr-missing" } , { name = "lmmi12.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "lmmi12.tfm", vector = "tex-it", skewchar=0x7F }, { name = "lmsy10.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "lmex10.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1533,6 +1548,7 @@ mathematics.make_font ( "px-math", { { name = "texgyrepagella-regular.otf", features = "virtualmath", main = true }, { name = "rpxr.tfm", vector = "tex-mr" } , { name = "rpxmi.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "pxmi1.tfm", vector = "tex-it", skewchar=0x7F }, { name = "pxsy.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "pxex.tfm", vector = "tex-ex", extension = true } , { name = "pxsya.tfm", vector = "tex-ma" }, @@ -1542,6 +1558,7 @@ mathematics.make_font ( "px-math", { mathematics.make_font ( "tx-math", { { name = "texgyretermes-regular.otf", features = "virtualmath", main = true }, { name = "rtxr.tfm", vector = "tex-mr" } , + { name = "rtxptmri.tfm", vector = "tex-it", skewchar=0x7F }, { name = "rtxmi.tfm", vector = "tex-mi", skewchar=0x7F }, { name = "txsy.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "txex.tfm", vector = "tex-ex", extension = true } , @@ -1552,6 +1569,7 @@ mathematics.make_font ( "tx-math", { mathematics.make_font ( "antykwa-math", { { name = "file:AntykwaTorunska-Regular", features = "virtualmath", main = true }, { name = "mi-anttri.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "mi-anttri.tfm", vector = "tex-it", skewchar=0x7F }, { name = "sy-anttrz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "ex-anttr.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1561,6 +1579,7 @@ mathematics.make_font ( "antykwa-math", { mathematics.make_font ( "antykwa-light-math", { { name = "file:AntykwaTorunskaLight-Regular", features = "virtualmath", main = true }, { name = "mi-anttli.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "mi-anttli.tfm", vector = "tex-it", skewchar=0x7F }, { name = "sy-anttlz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "ex-anttl.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1570,6 +1589,7 @@ mathematics.make_font ( "antykwa-light-math", { mathematics.make_font ( "antykwa-cond-math", { { name = "file:AntykwaTorunskaCond-Regular", features = "virtualmath", main = true }, { name = "mi-anttcri.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "mi-anttcri.tfm", vector = "tex-it", skewchar=0x7F }, { name = "sy-anttcrz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "ex-anttcr.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1579,6 +1599,7 @@ mathematics.make_font ( "antykwa-cond-math", { mathematics.make_font ( "antykwa-lightcond-math", { { name = "file:AntykwaTorunskaCondLight-Regular", features = "virtualmath", main = true }, { name = "mi-anttcli.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "mi-anttcli.tfm", vector = "tex-it", skewchar=0x7F }, { name = "sy-anttclz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "ex-anttcl.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1588,6 +1609,7 @@ mathematics.make_font ( "antykwa-lightcond-math", { mathematics.make_font ( "iwona-math", { { name = "file:Iwona-Regular", features = "virtualmath", main = true }, { name = "mi-iwonari.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "mi-iwonari.tfm", vector = "tex-it", skewchar=0x7F }, { name = "sy-iwonarz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "ex-iwonar.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1597,6 +1619,7 @@ mathematics.make_font ( "iwona-math", { mathematics.make_font ( "iwona-light-math", { { name = "file:IwonaLight-Regular", features = "virtualmath", main = true }, { name = "mi-iwonali.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "mi-iwonali.tfm", vector = "tex-it", skewchar=0x7F }, { name = "sy-iwonalz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "ex-iwonal.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1606,6 +1629,7 @@ mathematics.make_font ( "iwona-light-math", { mathematics.make_font ( "iwona-medium-math", { { name = "file:IwonaMedium-Regular", features = "virtualmath", main = true }, { name = "mi-iwonami.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "mi-iwonami.tfm", vector = "tex-it", skewchar=0x7F }, { name = "sy-iwonamz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "ex-iwonam.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1615,6 +1639,7 @@ mathematics.make_font ( "iwona-medium-math", { mathematics.make_font ( "iwona-heavy-math", { { name = "file:IwonaHeavy-Regular", features = "virtualmath", main = true }, { name = "mi-iwonahi.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "mi-iwonahi.tfm", vector = "tex-it", skewchar=0x7F }, { name = "sy-iwonahz.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } , { name = "ex-iwonah.tfm", vector = "tex-ex", extension = true } , { name = "msam10.tfm", vector = "tex-ma" }, @@ -1626,6 +1651,7 @@ mathematics.make_font ( "iwona-heavy-math", { mathematics.make_font ( "mathtimes-math", { { name = "file:texgyretermes-regular.otf", features = "virtualmath", main = true }, { name = "mtmiz.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "mtmiz.tfm", vector = "tex-it", skewchar=0x7F }, { name = "mtsyn.tfm", vector = "tex-sy", skewchar=0x30, parameters = true }, { name = "mtex.tfm", vector = "tex-ex", extension = true }, { name = "msam10.tfm", vector = "tex-ma" }, @@ -1635,6 +1661,7 @@ mathematics.make_font ( "mathtimes-math", { mathematics.make_font ( "lucida-math", { { name = "lbr.afm", features = "virtualmath", main = true }, { name = "hlcrim.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "hlcrim.tfm", vector = "tex-it", skewchar=0x7F }, { name = "hlcry.tfm", vector = "tex-sy", skewchar=0x30, parameters = true }, { name = "hlcrv.tfm", vector = "tex-ex", extension = true }, { name = "hlcra.tfm", vector = "tex-ma" }, @@ -1645,6 +1672,7 @@ mathematics.make_font ( "charter-math", { { name = "file:bchr8a", features = "virtualmath", main = true }, -- { name = "md-chr7m.tfm", vector = "tex-mr" }, { name = "md-chri7m.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "md-chri7m.tfm", vector = "tex-it", skewchar=0x7F }, { name = "md-chr7y.tfm", vector = "tex-sy", skewchar=0x30, parameters = true }, { name = "md-chr7v.tfm", vector = "tex-ex", extension = true }, { name = "msam10.tfm", vector = "tex-ma" }, @@ -1655,6 +1683,7 @@ mathematics.make_font ( "garamond-math", { { name = "file:ugmr8y", features = "virtualmath", main = true }, -- { name = "md-gmr7m.tfm", vector = "tex-mr" }, { name = "md-gmri7m.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "md-gmri7m.tfm", vector = "tex-it", skewchar=0x7F }, { name = "md-gmr7y.tfm", vector = "tex-sy", skewchar=0x30, parameters = true }, { name = "md-gmr7v.tfm", vector = "tex-ex", extension = true }, { name = "msam10.tfm", vector = "tex-ma" }, @@ -1665,6 +1694,7 @@ mathematics.make_font ( "utopia-math", { { name = "file:putr8y", features = "virtualmath", main = true }, -- { name = "md-utr7m.tfm", vector = "tex-mr" }, { name = "md-utri7m.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "md-utri7m.tfm", vector = "tex-it", skewchar=0x7F }, { name = "md-utr7y.tfm", vector = "tex-sy", skewchar=0x30, parameters = true }, { name = "md-utr7v.tfm", vector = "tex-ex", extension = true }, { name = "msam10.tfm", vector = "tex-ma" }, @@ -1675,6 +1705,7 @@ mathematics.make_font ( "hvmath-math", { { name = "file:texgyreheros-regular.otf", features = "virtualmath", main = true }, { name = "hvrm108r.tfm", vector="tex-mr" }, { name = "hvmi10.tfm", vector = "tex-mi", skewchar=0x7F }, + { name = "hvmi10.tfm", vector = "tex-it", skewchar=0x7F }, { name = "hvsy10.tfm", vector = "tex-sy", skewchar=0x30, parameters = true }, { name = "hvex10.tfm", vector = "tex-ex", extension = true }, { name = "hvam10.tfm", vector = "tex-ma" }, diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua index 253243500..f0ee1ec29 100644 --- a/tex/context/base/mlib-pps.lua +++ b/tex/context/base/mlib-pps.lua @@ -424,7 +424,7 @@ metapost.last_box = metapost.last_box or 1100 metapost.textext_current = metapost.first_box metapost.multipass = false -function metapost.free_boxes() +function metapost.free_boxes() -- todo: mp direct list ipv box local tb = tex.box for i = metapost.first_box,metapost.last_box do local b = tb[i] diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua index 02f6ca82d..008e44b6b 100644 --- a/tex/context/base/node-ref.lua +++ b/tex/context/base/node-ref.lua @@ -67,6 +67,8 @@ local function dimensions(parent,start,stop) end end +-- is pardir important at all? + local function inject_range(head,first,last,reference,make,stack,parent,pardir,txtdir) local width, height, depth = dimensions(parent,first,last) if pardir == "TRT" or txtdir == "+TRT" then diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua index f147981ed..49a1297eb 100644 --- a/tex/context/base/node-res.lua +++ b/tex/context/base/node-res.lua @@ -60,8 +60,10 @@ local glyph = nodes.register(new_node("glyph",0)) local textdir = nodes.register(new_node("whatsit",7)) local rule = nodes.register(new_node("rule")) local latelua = nodes.register(new_node("whatsit",35)) ---~ local user = nodes.register(new_node("user_defined")) -local user = nodes.register(new_node(44)) +local user_n = nodes.register(new_node("whatsit",44)) user_n.type = 100 +local user_l = nodes.register(new_node("whatsit",44)) user_l.type = 110 +local user_s = nodes.register(new_node("whatsit",44)) user_s.type = 115 +local user_t = nodes.register(new_node("whatsit",44)) user_t.type = 116 function nodes.glyph(fnt,chr) local n = copy_node(glyph) @@ -111,27 +113,41 @@ function nodes.latelua(code) return n end +local cache = { } + function nodes.usernumber(num) - local n = copy_node(user) - n.type = 100 - if num then n.value = num end - return n -end -function nodes.userstring(str) - local n = copy_node(user) - n.type = 115 - if str then n.value = str end - return n + local n = cache[num] + if n then + return copy_node(n) + else + local n = copy_node(user_n) + if num then n.value = num end + return n + end end + function nodes.userlist(list) - local n = copy_node(user) - n.type = 110 + local n = copy_node(user_l) if list then n.value = list end return n end + +local cache = { } -- we could use the same cache + +function nodes.userstring(str) + local n = cache[str] + if n then + return copy_node(n) + else + local n = copy_node(user_s) + n.type = 115 + if str then n.value = str end + return n + end +end + function nodes.usertokens(tokens) - local n = copy_node(user) - n.type = 116 + local n = copy_node(user_t) if tokens then n.value = tokens end return n end diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua index 60c6e77f3..3f1d572b7 100644 --- a/tex/context/base/node-rul.lua +++ b/tex/context/base/node-rul.lua @@ -11,7 +11,6 @@ if not modules then modules = { } end modules ['node-rul'] = { local trace_ruled = false trackers.register("nodes.ruled", function(v) trace_ruled = v end) local floor = math.floor -local topoints = number.topoints local n_tostring, n_tosequence = nodes.ids_tostring, nodes.tosequence local a_ruled = attributes.private('ruled') @@ -19,12 +18,14 @@ local a_color = attributes.private('color') local a_transparency = attributes.private('transparency') local a_colorspace = attributes.private('colormodel') -local glyph = node.id("glyph") -local disc = node.id("disc") -local glue = node.id("glue") -local kern = node.id("kern") -local hlist = node.id("hlist") -local vlist = node.id("vlist") +local glyph = node.id("glyph") +local disc = node.id("disc") +local glue = node.id("glue") +local kern = node.id("kern") +local hlist = node.id("hlist") +local vlist = node.id("vlist") +local rule = node.id("rule") +local whatsit = node.id("whatsit") local new_rule = nodes.rule local new_kern = nodes.kern @@ -44,6 +45,11 @@ local variables = interfaces.variables -- -- glyph rule unset whatsit glue margin_kern kern math disc +local checkdir = true + +-- we assume {glyphruns} and no funny extra kerning, ok, maybe we need +-- a dummy character as start and end; anyway we only collect glyphs + local function process_words(attribute,data,flush,head,parent) local n = head if n then @@ -55,7 +61,7 @@ local function process_words(attribute,data,flush,head,parent) local aa = has_attribute(n,attribute) if aa then if aa == a then - if not f then + if not f then -- ? f = n end l = n @@ -77,6 +83,8 @@ local function process_words(attribute,data,flush,head,parent) end elseif f and id == disc then l = n + elseif f and id == rule then + l = n elseif f and id == kern and n.subtype == 0 then l = n elseif id == hlist or id == vlist then @@ -88,6 +96,10 @@ local function process_words(attribute,data,flush,head,parent) if list then n.list = process_words(attribute,data,flush,list,n) end + elseif checkdir and id == whatsit and n.subtype == 7 then -- only changes in dir, we assume proper boundaries + if f and a then + l = n + end elseif f and not continue then head, done = flush(head,f,l,d,level,parent), true f, l, a = nil, nil, nil @@ -160,7 +172,7 @@ local function flush_ruled(head,f,l,d,level,parent) -- not that fast but accepta insert_after(head,r,k) end if trace_ruled then - logs.report("ruled", "level: %s, width: %s, nodes: %s, text: %s",level,topoints(w),n_tostring(f,l),n_tosequence(f,l,true)) + logs.report("ruled", "level: %s, width: %s, nodes: %s, text: %s",level,w,n_tostring(f,l),n_tosequence(f,l,true)) end end return head @@ -179,6 +191,8 @@ end -- tasks.appendaction ("shipouts", "normalizers", "nodes.rules.process") -- tasks.disableaction("shipouts", "nodes.rules.process") -- only kick in when used +local trace_shifted = false trackers.register("nodes.shifted", function(v) trace_shifted = v end) + local a_shifted = attributes.private('shifted') nodes.shifts = nodes.shifts or { } @@ -209,6 +223,9 @@ local function flush_shifted(head,first,last,data,level,parent) -- not that fast end local raise = data.dy * dimenfactor(data.unit,fontdata[first.font]) list.shift, list.height, list.depth = raise, height, depth + if trace_shifted then + logs.report("shifted", "width: %s, nodes: %s, text: %s",width,n_tostring(first,last),n_tosequence(first,last,true)) + end return head end diff --git a/tex/context/base/node-rul.mkiv b/tex/context/base/node-rul.mkiv index 40d0014dc..ba2f0aed3 100644 --- a/tex/context/base/node-rul.mkiv +++ b/tex/context/base/node-rul.mkiv @@ -11,6 +11,8 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +% todo: ex and and em traveling with attribute + \writestatus{loading}{ConTeXt Core Macros / Bars} %D The name of this file might change. @@ -255,13 +257,39 @@ \glet\dodoshifted\dodoshiftedindeed \dodoshifted} +% \def\dodoshiftedindeed#1% +% {\def\currentshift{#1}% +% \advance\csname\??ra:#1:c\endcsname\plusone +% \scratchcounter\csname\??ra:#1:c\endcsname +% \dosetattribute{shifted}{\numexpr1000*\scratchcounter +% +\csname\??ra#1\ifcsname\??ra#1:\number\scratchcounter\s!parent\endcsname:\number\scratchcounter\fi:a\endcsname}% +% \setupalign[\shiftparameter\c!align]% +% \dosetshiftattributes\c!style\c!color} + +\def\dostartisolation{\char0 } +\def\dostopisolation {\char0 } +\def\doisolator {\char0 } + +\def\doisolatedgroupedalign#1#2% + {\groupedcommand + {\begingroup\dostartisolation\begingroup#1} + {#2\endgroup\dostopisolation\endgroup}} + +\def\dosetupisolatedalign#1% + {\doisolator + \setupalign[#1]\relax} + \def\dodoshiftedindeed#1% {\def\currentshift{#1}% \advance\csname\??ra:#1:c\endcsname\plusone \scratchcounter\csname\??ra:#1:c\endcsname \dosetattribute{shifted}{\numexpr1000*\scratchcounter +\csname\??ra#1\ifcsname\??ra#1:\number\scratchcounter\s!parent\endcsname:\number\scratchcounter\fi:a\endcsname}% - \dosetshiftattributes\c!style\c!color} + \dosetshiftattributes\c!style\c!color + \dosetupisolatedalign{\shiftparameter\c!align}} + +\def\doshifted#1% + {\doisolatedgroupedalign{\dodoshifted{#1}}{}} \unexpanded\def\startshift[#1]% {\begingroup @@ -287,6 +315,7 @@ \c!continue=\v!no, \c!dy=0, \c!unit=ex, + \c!align=, \c!style=, \c!color=] diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua index 004aa34fa..f243c9cd0 100644 --- a/tex/context/base/node-tra.lua +++ b/tex/context/base/node-tra.lua @@ -310,7 +310,7 @@ function nodes.show_list(head, message) if message then texio.write_nl(message) end - for n in traverse(head) do + for n in traverse_nodes(head) do texio.write_nl(tostring(n)) end end diff --git a/tex/context/base/pack-rul.mkiv b/tex/context/base/pack-rul.mkiv index 8bae7e754..bd3a127e3 100644 --- a/tex/context/base/pack-rul.mkiv +++ b/tex/context/base/pack-rul.mkiv @@ -2286,7 +2286,7 @@ \egroup} \def\complexvl[#1]% - {\dovlwdhtdp\linewidth{#1}{#1}} + {\dovlwdhtdp{1}{#1}{#1}} \def\complexhl[#1]% {\hbox diff --git a/tex/context/base/spec-fdf.mkii b/tex/context/base/spec-fdf.mkii index 6f5a83bcb..509ea0596 100644 --- a/tex/context/base/spec-fdf.mkii +++ b/tex/context/base/spec-fdf.mkii @@ -191,6 +191,26 @@ \def\appendtoPDFdocumentextgstates#1% {\xdef\docuPDFextgstates{\docuPDFextgstates\space#1}} +%D Patterns (for tikz) + +\let\docuPDFpatterns\empty + +\def\checkPDFpatterns + {\ifx\docuPDFpatterns\empty \else + \ifnum\realpageno=\lastpage\relax + \doPDFdictionaryobject{FDF}{docupatterns}{\docuPDFpatterns}% + \fi + \doPDFgetobjectreference{FDF}{docupatterns}\PDFobjectreference + \doPDFpageresource{/Pattern \PDFobjectreference}% + \fi} + +\appendtoksonce + \checkPDFpatterns +\to \everyshipout + +\def\appendtoPDFdocumentpatterns#1% + {\xdef\docuPDFpatterns{\docuPDFpatterns\space#1}} + %D Another special mechanism (needed for color separation): \let\docuPDFcolorspaces\empty diff --git a/tex/context/base/strc-not.mkiv b/tex/context/base/strc-not.mkiv index 0d45ee59e..0246767b9 100644 --- a/tex/context/base/strc-not.mkiv +++ b/tex/context/base/strc-not.mkiv @@ -251,7 +251,6 @@ % \dochecknote % \to \everysetupnote - \def\setupnote {\dodoubleempty\dosetupnote} diff --git a/tex/context/base/tabl-tbl.mkiv b/tex/context/base/tabl-tbl.mkiv index bfff978ab..6942327fe 100644 --- a/tex/context/base/tabl-tbl.mkiv +++ b/tex/context/base/tabl-tbl.mkiv @@ -410,8 +410,8 @@ \def\gettabulatepreskip#1% {\doifnumberelse{#1} - {\edef\pretabskip{\the\dimenexpr#1\tabulateunit}\let\next\empty} - {\edef\pretabskip{\the\dimenexpr.5\tabulateunit}\def\next{#1}}% + {\edef\pretabskip{\the\dimexpr#1\tabulateunit}\let\next\empty} + {\edef\pretabskip{\the\dimexpr.5\tabulateunit}\def\next{#1}}% \@EA\settabulatepreamble\next} \def\gettabulateposskip#1% @@ -423,8 +423,8 @@ \def\gettabulatepreposskip#1% {\doifnumberelse{#1} - {\edef\pretabskip{\the\dimenexpr#1\tabulateunit}\let\next\empty} - {\edef\pretabskip{\the\dimenexpr.5\tabulateunit}\def\next{#1}}% + {\edef\pretabskip{\the\dimexpr#1\tabulateunit}\let\next\empty} + {\edef\pretabskip{\the\dimexpr.5\tabulateunit}\def\next{#1}}% \let\postabskip\pretabskip \let\gettabulateexit\settabulatepreamble \@EA\settabulatepreamble\next} diff --git a/tex/context/base/task-ini.lua b/tex/context/base/task-ini.lua index dba099451..01bcaec0f 100644 --- a/tex/context/base/task-ini.lua +++ b/tex/context/base/task-ini.lua @@ -20,7 +20,8 @@ tasks.appendaction("processors", "characters", "chars.handle_breakpoints") tasks.appendaction("processors", "characters", "scripts.preprocess") tasks.appendaction("processors", "words", "kernel.hyphenation") -tasks.appendaction("processors", "words", "languages.words.check") +tasks.appendaction("processors", "words", "languages.words.check") -- * disabled + tasks.appendaction("processors", "fonts", "nodes.process_characters") tasks.appendaction("processors", "fonts", "nodes.inject_kerns") @@ -28,21 +29,18 @@ tasks.appendaction("processors", "fonts", "nodes.protect_glyphs", nil, "no tasks.appendaction("processors", "fonts", "kernel.ligaturing") tasks.appendaction("processors", "fonts", "kernel.kerning") -tasks.appendaction("processors", "lists", "lists.handle_spacing") -- * -tasks.appendaction("processors", "lists", "lists.handle_kerning") -- * +tasks.appendaction("processors", "lists", "lists.handle_spacing") -- * disabled +tasks.appendaction("processors", "lists", "lists.handle_kerning") -- * disabled tasks.appendaction("shipouts", "normalizers", "nodes.cleanup_page") tasks.appendaction("shipouts", "normalizers", "nodes.add_references") -- * tasks.appendaction("shipouts", "normalizers", "nodes.add_destinations") -- * -tasks.appendaction("shipouts", "normalizers", "nodes.rules.process") -- * -tasks.appendaction("shipouts", "normalizers", "nodes.shifts.process") -- * - -tasks.disableaction("shipouts", "nodes.rules.process") -- * only kick in when used -tasks.disableaction("shipouts", "nodes.shifts.process") -- * only kick in when used +tasks.appendaction("shipouts", "normalizers", "nodes.rules.process") -- * disabled +tasks.appendaction("shipouts", "normalizers", "nodes.shifts.process") -- * disabled tasks.appendaction("shipouts", "finishers", "shipouts.handle_color") tasks.appendaction("shipouts", "finishers", "shipouts.handle_transparency") -tasks.appendaction("shipouts", "finishers", "shipouts.handle_colorintent") +tasks.appendaction("shipouts", "finishers", "shipouts.handle_colorintent") -- * tasks.appendaction("shipouts", "finishers", "shipouts.handle_negative") -- * tasks.appendaction("shipouts", "finishers", "shipouts.handle_effect") -- * tasks.appendaction("shipouts", "finishers", "shipouts.handle_viewerlayer") -- * @@ -56,3 +54,11 @@ tasks.appendaction("math", "builders", "noads.mlist_to_hlist") -- quite experimental tasks.appendaction("finalizers", "lists", "nodes.repackage_graphicvadjust") -- * + +-- speedup: see * -- only kick in when used + +tasks.disableaction("processors", "languages.words.check") +tasks.disableaction("processors", "lists.handle_spacing") +tasks.disableaction("processors", "lists.handle_kerning") +tasks.disableaction("shipouts", "nodes.rules.process") +tasks.disableaction("shipouts", "nodes.shifts.process") diff --git a/tex/context/base/type-otf.mkiv b/tex/context/base/type-otf.mkiv index 983e197de..e7844fb0b 100644 --- a/tex/context/base/type-otf.mkiv +++ b/tex/context/base/type-otf.mkiv @@ -525,6 +525,24 @@ \loadmapfile[mdput.map] \stoptypescript +% asana math + +\starttypescript [math] [asana] + \definefontsynonym [AsanaMath] [name:asanamath] +\stoptypescript + +\starttypescript [math] [asana] [name] + \definefontsynonym [MathRoman] [AsanaMath] [features=math\mathsizesuffix] +\stoptypescript + +\starttypescript[asana] + \definetypeface [\typescriptone] [rm] [serif] [palatino] [default] + \definetypeface [\typescriptone] [ss] [sans] [modern] [default] [rscale=1.075] + \definetypeface [\typescriptone] [tt] [mono] [modern] [default] [rscale=1.075] + \definetypeface [\typescriptone] [mm] [math] [\typescriptone] [default] + \quittypescriptscanning +\stoptypescript + \stoptypescriptcollection \endinput diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua index 5ab0b07ed..87e066531 100644 --- a/tex/context/base/typo-krn.lua +++ b/tex/context/base/typo-krn.lua @@ -217,3 +217,8 @@ lists.handle_kerning = nodes.install_attribute_handler { namespace = kerns, processor = kerns.process, } + +function kerns.enable() + tasks.enableaction("processors","lists.handle_kerning") + kerns.enabled = true -- will go +end diff --git a/tex/context/base/typo-spa.lua b/tex/context/base/typo-spa.lua index b6a1fbb5b..56ce36a05 100644 --- a/tex/context/base/typo-spa.lua +++ b/tex/context/base/typo-spa.lua @@ -25,7 +25,7 @@ local fontdata = fonts.ids spacings = spacings or { } spacings.mapping = spacings.mapping or { } -spacings.enabled = false +spacings.enabled = false -- will go spacings.attribute = attributes.private("spacing") storage.register("spacings/mapping", spacings.mapping, "spacings.mapping") @@ -148,3 +148,18 @@ lists.handle_spacing = nodes.install_attribute_handler { namespace = spacings, processor = spacings.process, } + +function spacings.enable() + tasks.enableaction("processors","lists.handle_spacing") + spacings.enabled = true -- will go +end + +--~ local data = { +--~ name = "spacing", +--~ namespace = spacings, +--~ processor = spacings.process, +--~ } +--~ nodes.process_attribute = process_attribute +--~ function lists.handle_spacing(head) +--~ return process_attribute(head,data) +--~ end diff --git a/tex/context/base/typo-spa.mkiv b/tex/context/base/typo-spa.mkiv index d1b855edd..9ff614be9 100644 --- a/tex/context/base/typo-spa.mkiv +++ b/tex/context/base/typo-spa.mkiv @@ -43,7 +43,8 @@ \fi} \def\setcharacterspacing - {\ctxlua{spacings.enabled=true}% +% {\ctxlua{spacings.enabled=true}% + {\ctxlua{spacings.enable()}% \gdef\setcharacterspacing[##1]{\dosetattribute{spacing}{\csname\??ch:##1\endcsname}}% \setcharacterspacing} diff --git a/tex/generic/context/luatex-fonts-merged.lua b/tex/generic/context/luatex-fonts-merged.lua index 70368ebd9..82fe96610 100644 --- a/tex/generic/context/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/texmf/tex/generic/context/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/texmf/tex/generic/context/luatex-fonts.lua --- merge date : 11/13/09 12:51:09 +-- merge date : 11/18/09 21:55:28 do -- begin closure to overcome local limits and interference @@ -2345,8 +2345,10 @@ local glyph = nodes.register(new_node("glyph",0)) local textdir = nodes.register(new_node("whatsit",7)) local rule = nodes.register(new_node("rule")) local latelua = nodes.register(new_node("whatsit",35)) ---~ local user = nodes.register(new_node("user_defined")) -local user = nodes.register(new_node(44)) +local user_n = nodes.register(new_node("whatsit",44)) user_n.type = 100 +local user_l = nodes.register(new_node("whatsit",44)) user_l.type = 110 +local user_s = nodes.register(new_node("whatsit",44)) user_s.type = 115 +local user_t = nodes.register(new_node("whatsit",44)) user_t.type = 116 function nodes.glyph(fnt,chr) local n = copy_node(glyph) @@ -2396,27 +2398,41 @@ function nodes.latelua(code) return n end +local cache = { } + function nodes.usernumber(num) - local n = copy_node(user) - n.type = 100 - if num then n.value = num end - return n -end -function nodes.userstring(str) - local n = copy_node(user) - n.type = 115 - if str then n.value = str end - return n + local n = cache[num] + if n then + return copy_node(n) + else + local n = copy_node(user_n) + if num then n.value = num end + return n + end end + function nodes.userlist(list) - local n = copy_node(user) - n.type = 110 + local n = copy_node(user_l) if list then n.value = list end return n end + +local cache = { } -- we could use the same cache + +function nodes.userstring(str) + local n = cache[str] + if n then + return copy_node(n) + else + local n = copy_node(user_s) + n.type = 115 + if str then n.value = str end + return n + end +end + function nodes.usertokens(tokens) - local n = copy_node(user) - n.type = 116 + local n = copy_node(user_t) if tokens then n.value = tokens end return n end @@ -3794,15 +3810,15 @@ local private = fonts.private end -- needed for \high cum suis local tpx = tp.x_height -if hasmath then - if not tp[13] then tp[13] = .86*tpx end -- mathsupdisplay - if not tp[14] then tp[14] = .86*tpx end -- mathsupnormal - if not tp[15] then tp[15] = .86*tpx end -- mathsupcramped - if not tp[16] then tp[16] = .48*tpx end -- mathsubnormal - if not tp[17] then tp[17] = .48*tpx end -- mathsubcombined - if not tp[22] then tp[22] = 0 end -- mathaxisheight - if t.MathConstants then t.MathConstants.AccentBaseHeight = nil end -- safeguard -end + if hasmath then + if not tp[13] then tp[13] = .86*tpx end -- mathsupdisplay + if not tp[14] then tp[14] = .86*tpx end -- mathsupnormal + if not tp[15] then tp[15] = .86*tpx end -- mathsupcramped + if not tp[16] then tp[16] = .48*tpx end -- mathsubnormal + if not tp[17] then tp[17] = .48*tpx end -- mathsubcombined + if not tp[22] then tp[22] = 0 end -- mathaxisheight + if t.MathConstants then t.MathConstants.AccentBaseHeight = nil end -- safeguard + end t.tounicode = 1 t.cidinfo = tfmtable.cidinfo -- we have t.name=metricfile and t.fullname=RealName and t.filename=diskfilename @@ -3810,20 +3826,21 @@ end -- can have multiple subfonts if hasmath then if trace_defining then - logs.report("define font","math enabled for: %s %s %s",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") + logs.report("define font","math enabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") end else if trace_defining then - logs.report("define font","math disabled for: %s %s %s",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") + logs.report("define font","math disabled for: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") end t.nomath, t.MathConstants = true, nil end - -- fullname is used in the subsetting if not t.psname then - t.psname = t.fullname -- else bad luck + -- name used in pdf file as well as for selecting subfont in ttc/dfont + t.psname = t.fontname or (t.fullname and fonts.names.cleanname(t.fullname)) end if trace_defining then - logs.report("define font","used for subsetting: %s ",t.fullname or "nofullname") + logs.report("define font","used for accesing subfont: '%s'",t.psname or "nopsname") + logs.report("define font","used for subsetting: '%s'",t.fontname or "nofontname") end return t, delta end @@ -6705,8 +6722,9 @@ function otf.copy_to_tfm(data,cache_id) -- we can save a copy when we reorder th tfm.units = metadata.units_per_em or 1000 -- we need a runtime lookup because of running from cdrom or zip, brrr tfm.filename = resolvers.findbinfile(luatex.filename,"") or luatex.filename - tfm.fullname = metadata.fontname or metadata.fullname - tfm.psname = tfm.fullname + tfm.fullname = metadata.fullname + tfm.fontname = metadata.fontname + tfm.psname = tfm.fontname or tfm.fullname tfm.encodingbytes = 2 tfm.cidinfo = data.cidinfo tfm.cidinfo.registry = tfm.cidinfo.registry or "" @@ -6830,7 +6848,8 @@ function tfm.read_from_open_type(specification) if filename then tfmtable.encodingbytes = 2 tfmtable.filename = resolvers.findbinfile(filename,"") or filename - tfmtable.fullname = tfmtable.fullname or otfdata.metadata.fontname or otfdata.metadata.fullname + tfmtable.fontname = tfmtable.fontname or otfdata.metadata.fontname + tfmtable.fullname = tfmtable.fullname or otfdata.metadata.fullname or tfmtable.fontname local order = otfdata and otfdata.metadata.order2 if order == 0 then tfmtable.format = 'opentype' @@ -6839,7 +6858,7 @@ function tfm.read_from_open_type(specification) else tfmtable.format = specification.format end - tfmtable.name = tfmtable.filename or tfmtable.fullname + tfmtable.name = tfmtable.filename or tfmtable.fullname or tfmtable.fontname end fonts.logger.save(tfmtable,file.extname(specification.filename),specification) end @@ -7491,7 +7510,7 @@ results in different tables. -- remark: the 'not implemented yet' variants will be done when we have fonts that use them -- remark: we need to check what to do with discretionaries -local concat = table.concat +local concat, insert, remove = table.concat, table.insert, table.remove local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip local type, next, tonumber, tostring = type, next, tonumber, tostring @@ -7513,6 +7532,7 @@ local trace_details = false trackers.register("otf.details", function local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end) local trace_steps = false trackers.register("otf.steps", function(v) trace_steps = v end) local trace_skips = false trackers.register("otf.skips", function(v) trace_skips = v end) +local trace_directions = false trackers.register("otf.directions", function(v) trace_directions = v end) trackers.register("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end) trackers.register("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end) @@ -8117,7 +8137,7 @@ function handlers.gpos_cursive(start,kind,lookupname,exitanchors,sequence) -- to if exit then local dx, dy, bound = set_cursive(start,nxt,tfmdata.factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) if trace_cursive then - logprocess("%s: moving %s to %s cursive (%s,%s) using anchor %s and bound %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound) + logprocess("%s: moving %s to %s cursive (%s,%s) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode) end done = true break @@ -8769,7 +8789,7 @@ function chainprocs.gpos_cursive(start,stop,kind,chainname,currentcontext,cache, if exit then local dx, dy, bound = set_cursive(start,nxt,tfmdata.factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) if trace_cursive then - logprocess("%s: moving %s to %s cursive (%s,%s) using anchor %s and bound %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound) + logprocess("%s: moving %s to %s cursive (%s,%s) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode) end done = true break @@ -9206,6 +9226,9 @@ local resolved = { } -- we only resolve a font,script,language pair once -- todo: pass all these 'locals' in a table +-- maybe some day i'll make an alternative that works on 'sub direction runs' which might be +-- more efficient for arabic but it has quite some consequences + function fonts.methods.node.otf.features(head,font,attr) if trace_steps then checkstep(head) @@ -9249,6 +9272,7 @@ function fonts.methods.node.otf.features(head,font,attr) local ra = rl [attr] if ra == nil then ra = { } rl [attr] = ra end -- attr can be false -- sequences always > 1 so no need for optimization for s=1,#sequences do + local pardir, txtdir = 0, { } local success = false local sequence = sequences[s] local r = ra[s] -- cache @@ -9348,7 +9372,7 @@ function fonts.methods.node.otf.features(head,font,attr) local ns = #subtables local thecache = featuredata[typ] or { } start = head -- local ? - rlmode = 0 + rlmode = 0 -- to be checked ? if ns == 1 then local lookupname = subtables[1] local lookupcache = thecache[lookupname] @@ -9390,24 +9414,57 @@ function fonts.methods.node.otf.features(head,font,attr) -- start = start.next -- end elseif id == whatsit then +--~ if subtype == 7 then +--~ local dir = start.dir +--~ if dir == "+TRT" then +--~ rlmode = -1 +--~ elseif dir == "+TLT" then +--~ rlmode = 1 +--~ else +--~ rlmode = 0 +--~ end +--~ elseif subtype == 6 then +--~ local dir = start.dir +--~ if dir == "TRT" then +--~ rlmode = -1 +--~ elseif dir == "TLT" then +--~ rlmode = 1 +--~ else +--~ rlmode = 0 +--~ end +--~ end local subtype = start.subtype if subtype == 7 then local dir = start.dir - if dir == "+TRT" then + if dir == "+TRT" or dir == "+TLT" then + insert(txtdir,dir) + elseif dir == "-TRT" or dir == "-TLT" then + remove(txtdir) + end + local d = txtdir[#txtdir] + if d == "+TRT" then rlmode = -1 - elseif dir == "+TLT" then + elseif d == "+TLT" then rlmode = 1 else - rlmode = 0 + rlmode = pardir + end + if trace_directions then + logs.report("fonts","directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode) end elseif subtype == 6 then local dir = start.dir if dir == "TRT" then - rlmode = -1 + pardir = -1 elseif dir == "TLT" then - rlmode = 1 + pardir = 1 else - rlmode = 0 + pardir = 0 + end + rlmode = pardir + --~ txtdir = { } + if trace_directions then + logs.report("fonts","directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode) end end start = start.next @@ -9415,7 +9472,6 @@ function fonts.methods.node.otf.features(head,font,attr) start = start.next end end - end else while start do @@ -9462,25 +9518,59 @@ function fonts.methods.node.otf.features(head,font,attr) -- end elseif id == whatsit then local subtype = start.subtype - if subtype == 7 then - local dir = start.dir - if dir == "+TRT" then - rlmode = -1 - elseif dir == "+TLT" then - rlmode = 1 - else - rlmode = 0 +--~ if subtype == 7 then +--~ local dir = start.dir +--~ if dir == "+TRT" then +--~ rlmode = -1 +--~ elseif dir == "+TLT" then +--~ rlmode = 1 +--~ else +--~ rlmode = 0 +--~ end +--~ elseif subtype == 6 then +--~ local dir = start.dir +--~ if dir == "TRT" then +--~ rlmode = -1 +--~ elseif dir == "TLT" then +--~ rlmode = 1 +--~ else +--~ rlmode = 0 +--~ end +--~ end + local subtype = start.subtype + if subtype == 7 then + local dir = start.dir + if dir == "+TRT" or dir == "+TLT" then + insert(txtdir,dir) + elseif dir == "-TRT" or dir == "-TLT" then + remove(txtdir) + end + local d = txtdir[#txtdir] + if d == "+TRT" then + rlmode = -1 + elseif d == "+TLT" then + rlmode = 1 + else + rlmode = pardir + end + if trace_directions then + logs.report("fonts","directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode) + end + elseif subtype == 6 then + local dir = start.dir + if dir == "TRT" then + pardir = -1 + elseif dir == "TLT" then + pardir = 1 + else + pardir = 0 + end + rlmode = pardir + --~ txtdir = { } + if trace_directions then + logs.report("fonts","directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode) end - elseif subtype == 6 then - local dir = start.dir - if dir == "TRT" then - rlmode = -1 - elseif dir == "TLT" then - rlmode = 1 - else - rlmode = 0 end - end start = start.next else start = start.next @@ -11521,10 +11611,15 @@ function fonts.logger.save() end -- names +-- +-- Watch out, the version number is the same as the one used in +-- the mtx-fonts.lua function scripts.fonts.names as we use a +-- simplified font database in the plain solution and by using +-- a different number we're less dependent on context. fonts.names = fonts.names or { } -fonts.names.version = 1.014 +fonts.names.version = 1.001 -- not the same as in context fonts.names.basename = "luatex-fonts-names.lua" fonts.names.new_to_old = { } fonts.names.old_to_new = { } @@ -11539,16 +11634,6 @@ function fonts.names.resolve(name,sub) local foundname = resolvers.find_file(basename,format) or "" if foundname ~= "" then data = dofile(foundname) - if data then - local d = { } - for k, v in pairs(data.mapping) do - local t = v[1] - if t == "ttf" or t == "otf" or t == "ttc" or t == "dfont" then - d[k] = v - end - end - data.mapping = d - end break end end @@ -11559,9 +11644,12 @@ function fonts.names.resolve(name,sub) local condensed = string.gsub(string.lower(name),"[^%a%d]","") local found = data.mapping and data.mapping[condensed] if found then - local filename, is_sub = found[3], found[4] - if is_sub then is_sub = found[2] end - return filename, is_sub + local fontname, filename, subfont = found[1], found[2], found[3] + if subfont then + return filename, fontname + else + return filename, false + end else return name, false -- fallback to filename end -- cgit v1.2.3