diff options
author | Hans Hagen <pragma@wxs.nl> | 2009-11-13 12:45:00 +0100 |
---|---|---|
committer | Hans Hagen <pragma@wxs.nl> | 2009-11-13 12:45:00 +0100 |
commit | 9cf4a9e0a6642da57b94730bf7104335735a7ace (patch) | |
tree | 54c569dc3afe03413ce4ff8e22e2f80a70188e64 /tex | |
parent | e1359274233291895621d41406cf38756e2e04b1 (diff) | |
download | context-9cf4a9e0a6642da57b94730bf7104335735a7ace.tar.gz |
beta 2009.11.13 12:45
Diffstat (limited to 'tex')
29 files changed, 924 insertions, 209 deletions
diff --git a/tex/context/base/anch-pos.lua b/tex/context/base/anch-pos.lua index 61ed73933..8b64ead8d 100644 --- a/tex/context/base/anch-pos.lua +++ b/tex/context/base/anch-pos.lua @@ -91,6 +91,7 @@ function jobpositions.MPxy(id) texprint(ctxcatcodes,'(0,0)') end end + function jobpositions.MPll(id) local jpi = pcol[id] or ptbs[id] if jpi then @@ -100,6 +101,7 @@ function jobpositions.MPll(id) texprint(ctxcatcodes,'(0,0)') end end + function jobpositions.MPlr(id) local jpi = pcol[id] or ptbs[id] if jpi then @@ -109,6 +111,7 @@ function jobpositions.MPlr(id) texprint(ctxcatcodes,'(0,0)') end end + function jobpositions.MPur(id) local jpi = pcol[id] or ptbs[id] if jpi then @@ -118,6 +121,7 @@ function jobpositions.MPur(id) texprint(ctxcatcodes,'(0,0)') end end + function jobpositions.MPul(id) local jpi = pcol[id] or ptbs[id] if jpi then @@ -127,6 +131,7 @@ function jobpositions.MPul(id) texprint(ctxcatcodes,'(0,0)') end end + function jobpositions.MPpos(id) local jpi = pcol[id] or ptbs[id] if jpi then @@ -135,11 +140,25 @@ function jobpositions.MPpos(id) texprint(ctxcatcodes,'0,0,0,0,0,0') end end + +local splitter = lpeg.splitat(",") + function jobpositions.MPplus(id,n,default) local jpi = pcol[id] or ptbs[id] - texprint(ctxcatcodes,(jpi and jpi[6+n]) or default) + if not jpi then + texprint(ctxcatcodes,default) + else + local split = jpi[0] + if not split then + split = splitter:match(jpi[7]) + jpi[0] = split + end + texprint(ctxcatcodes,split[n] or default) + end end + function jobpositions.MPrest(id,default) local jpi = pcol[id] or ptbs[id] - texprint(ctxcatcodes,(jpi and jpi[7] and concat(jpi,",",7,#jpi)) or default) + -- texprint(ctxcatcodes,(jpi and jpi[7] and concat(jpi,",",7,#jpi)) or default) + texprint(ctxcatcodes,(jpi and jpi[7]) or default) end diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex index 64a039a69..1eecb06fe 100644 --- a/tex/context/base/cont-new.tex +++ b/tex/context/base/cont-new.tex @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2009.11.10 13:30} +\newcontextversion{2009.11.13 12:45} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex index 8693887c9..95b945f26 100644 --- a/tex/context/base/context.tex +++ b/tex/context/base/context.tex @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2009.11.10 13:30} +\edef\contextversion{2009.11.13 12:45} %D For those who want to use this: diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua index 304920b57..a055d8c7e 100644 --- a/tex/context/base/core-uti.lua +++ b/tex/context/base/core-uti.lua @@ -19,6 +19,7 @@ saves much runtime but at the cost of more memory usage.</p> local sort, concat, format = table.sort, table.concat, string.format local next, type, tostring = next, type, tostring +local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes if not jobs then jobs = { } end if not job then jobs['main'] = { } end job = jobs['main'] @@ -72,7 +73,7 @@ local function initializer() math.setrandomseedi(r) jobvariables.tobesaved.randomseed = r for cs, value in next, jobvariables.collected do - tex.sprint(format("\\xdef\\%s{%s}",cs,value)) + texsprint(ctxcatcodes,format("\\xdef\\%s{%s}",cs,value)) end end diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua index 9738cfaff..7181f5a17 100644 --- a/tex/context/base/data-res.lua +++ b/tex/context/base/data-res.lua @@ -37,6 +37,8 @@ local format, gsub, find, lower, upper, match, gmatch = string.format, string.gs local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys local next, type = next, type +local collapse_path = file.collapse_path + local trace_locating, trace_detail, trace_verbose = false, false, false trackers.register("resolvers.verbose", function(v) trace_verbose = v end) @@ -425,7 +427,7 @@ local function expanded_path_from_list(pathlist) -- maybe not a list, just a pat end if ok then local function validate(s) - s = file.collapse_path(s) + s = collapse_path(s) return s ~= "" and not find(s,dummy_path_expr) and s end for k=1,#pathlist do @@ -434,7 +436,7 @@ local function expanded_path_from_list(pathlist) -- maybe not a list, just a pat else for k=1,#pathlist do for p in gmatch(pathlist[k],"([^,]+)") do - p = file.collapse_path(p) + p = collapse_path(p) if p ~= "" then newlist[#newlist+1] = p end end end @@ -499,9 +501,9 @@ local function identify_own() local ownpath = resolvers.getownpath() or lfs.currentdir() local ie = instance.environment if ownpath then - if resolvers.env('SELFAUTOLOC') == "" then os.env['SELFAUTOLOC'] = file.collapse_path(ownpath) end - if resolvers.env('SELFAUTODIR') == "" then os.env['SELFAUTODIR'] = file.collapse_path(ownpath .. "/..") end - if resolvers.env('SELFAUTOPARENT') == "" then os.env['SELFAUTOPARENT'] = file.collapse_path(ownpath .. "/../..") end + if resolvers.env('SELFAUTOLOC') == "" then os.env['SELFAUTOLOC'] = collapse_path(ownpath) end + if resolvers.env('SELFAUTODIR') == "" then os.env['SELFAUTODIR'] = collapse_path(ownpath .. "/..") end + if resolvers.env('SELFAUTOPARENT') == "" then os.env['SELFAUTOPARENT'] = collapse_path(ownpath .. "/../..") end else logs.report("fileio","error: unable to locate ownpath") os.exit() @@ -530,7 +532,7 @@ function resolvers.identify_cnf() local function locate(filename,list) for i=1,#t do local ti = t[i] - local texmfcnf = file.collapse_path(file.join(ti,filename)) + local texmfcnf = collapse_path(file.join(ti,filename)) if lfs.isfile(texmfcnf) then list[#list+1] = texmfcnf end @@ -625,12 +627,12 @@ function resolvers.load_cnf() else instance.rootpath = instance.cnffiles[1] for k,fname in ipairs(instance.cnffiles) do - instance.cnffiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.cnffiles[k] = collapse_path(gsub(fname,"\\",'/')) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) end - instance.rootpath = file.collapse_path(instance.rootpath) + instance.rootpath = collapse_path(instance.rootpath) if instance.diskcache and not instance.renewcache then resolvers.loadoldconfig(instance.cnffiles) if instance.loaderror then @@ -654,12 +656,12 @@ function resolvers.load_lua() else instance.rootpath = instance.luafiles[1] for k,fname in ipairs(instance.luafiles) do - instance.luafiles[k] = file.collapse_path(gsub(fname,"\\",'/')) + instance.luafiles[k] = collapse_path(gsub(fname,"\\",'/')) end for i=1,3 do instance.rootpath = file.dirname(instance.rootpath) end - instance.rootpath = file.collapse_path(instance.rootpath) + instance.rootpath = collapse_path(instance.rootpath) resolvers.loadnewconfig() collapse_cnf_data() end @@ -721,7 +723,7 @@ function resolvers.locatelists() if trace_verbose then logs.report("fileio","locating list of %s",path) end - resolvers.locatedatabase(file.collapse_path(path)) + resolvers.locatedatabase(collapse_path(path)) end end @@ -1263,7 +1265,7 @@ function resolvers.clean_path_list(str) local t = resolvers.expanded_path_list(str) if t then for i=1,#t do - t[i] = file.collapse_path(resolvers.clean_path(t[i])) + t[i] = collapse_path(resolvers.clean_path(t[i])) end end return t @@ -1460,8 +1462,8 @@ end local function collect_instance_files(filename,collected) -- todo : plugin (scanners, checkers etc) local result = collected or { } local stamp = nil - filename = file.collapse_path(filename) -- elsewhere - filename = file.collapse_path(gsub(filename,"\\","/")) -- elsewhere + filename = collapse_path(filename) -- elsewhere + filename = collapse_path(gsub(filename,"\\","/")) -- elsewhere -- speed up / beware: format problem if instance.remember then stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format @@ -1692,7 +1694,7 @@ local function collect_instance_files(filename,collected) -- todo : plugin (scan end end for k=1,#result do - result[k] = file.collapse_path(result[k]) + result[k] = collapse_path(result[k]) end if instance.remember then instance.found[stamp] = result diff --git a/tex/context/base/font-def.lua b/tex/context/base/font-def.lua index c362e3867..65c74d48f 100644 --- a/tex/context/base/font-def.lua +++ b/tex/context/base/font-def.lua @@ -85,17 +85,28 @@ local right = P(")") local colon = P(":") local space = P(" ") +define.defaultlookup = "file" + +local prefixpattern = P(false) + function define.add_specifier(symbol) specifiers = specifiers .. symbol local method = S(specifiers) - local lookup = C(P("file")+P("name")) * colon -- hard test, else problems with : method + local lookup = C(prefixpattern) * colon local sub = left * C(P(1-left-right-method)^1) * right ---~ local specification = C(method) * C(P(1-method)^1) local specification = C(method) * C(P(1)^1) local name = C((1-sub-specification)^1) splitter = P((lookup + Cc("")) * name * (sub + Cc("")) * (specification + Cc(""))) end +function define.add_lookup(str,default) + prefixpattern = prefixpattern + P(str) +end + +define.add_lookup("file") +define.add_lookup("name") +define.add_lookup("spec") + function define.get_specification(str) return splitter:match(str) end @@ -116,8 +127,8 @@ function define.makespecification(specification, lookup, name, sub, method, deta --~ lookup = specification.lookup -- can come from xetex [] syntax --~ specification.lookup = nil --~ end - if lookup ~= 'name' then -- for the moment only two lookups, maybe some day also system: - lookup = 'file' + if not lookup or lookup == "" then + lookup = define.defaultlookup end local t = { lookup = lookup, -- forced type @@ -219,17 +230,44 @@ end <p>We can resolve the filename using the next function:</p> --ldx]]-- +define.resolvers = resolvers + +function define.resolvers.file(specification) + specification.forced = file.extname(specification.name) + specification.name = file.removesuffix(specification.name) +end + +function define.resolvers.name(specification) + local resolve = fonts.names.resolve + if resolve then + specification.resolved, specification.sub = fonts.names.resolve(specification.name,specification.sub) + if specification.resolved then + specification.forced = file.extname(specification.resolved) + specification.name = file.removesuffix(specification.resolved) + end + else + define.resolvers.file(specification) + end +end + +function define.resolvers.spec(specification) + local resolvespec = fonts.names.resolvespec + if resolvespec then + specification.resolved, specification.sub = fonts.names.resolvespec(specification.name,specification.sub) + if specification.resolved then + specification.forced = file.extname(specification.resolved) + specification.name = file.removesuffix(specification.resolved) + end + else + define.resolvers.name(specification) + end +end + function define.resolve(specification) if not specification.resolved or specification.resolved == "" then -- resolved itself not per se in mapping hash - if specification.lookup == 'name' then - specification.resolved, specification.sub = fonts.names.resolve(specification.name,specification.sub) - if specification.resolved then - specification.forced = file.extname(specification.resolved) - specification.name = file.removesuffix(specification.resolved) - end - elseif specification.lookup == 'file' then - specification.forced = file.extname(specification.name) - specification.name = file.removesuffix(specification.name) + local r = define.resolvers[specification.lookup] + if r then + r(specification) end end if specification.forced == "" then @@ -237,7 +275,6 @@ function define.resolve(specification) else specification.forced = specification.forced end ---~ specification.hash = specification.name .. ' @ ' .. tfm.hash_features(specification) specification.hash = lower(specification.name .. ' @ ' .. tfm.hash_features(specification)) if specification.sub and specification.sub ~= "" then specification.hash = specification.sub .. ' @ ' .. specification.hash diff --git a/tex/context/base/font-dum.lua b/tex/context/base/font-dum.lua index ef267a42c..c585c18b5 100644 --- a/tex/context/base/font-dum.lua +++ b/tex/context/base/font-dum.lua @@ -42,6 +42,7 @@ end fonts.names = fonts.names or { } +fonts.names.version = 1.014 fonts.names.basename = "luatex-fonts-names.lua" fonts.names.new_to_old = { } fonts.names.old_to_new = { } @@ -72,7 +73,7 @@ function fonts.names.resolve(name,sub) end loaded = true end - if type(data) == "table" and data.version == 1.08 then + if type(data) == "table" and data.version == fonts.names.version then local condensed = string.gsub(string.lower(name),"[^%a%d]","") local found = data.mapping and data.mapping[condensed] if found then @@ -85,6 +86,8 @@ function fonts.names.resolve(name,sub) end end +fonts.names.resolvespec = fonts.names.resolve -- only supported in mkiv + -- For the moment we put this (adapted) pseudo feature here. table.insert(fonts.triggers,"itlc") diff --git a/tex/context/base/font-otb.lua b/tex/context/base/font-otb.lua index b80c88b39..127d4c218 100644 --- a/tex/context/base/font-otb.lua +++ b/tex/context/base/font-otb.lua @@ -309,7 +309,7 @@ local supported_gsub = { 'zero', 'smcp','cpsp','c2sc','ornm','aalt', 'hwid','fwid', - 'ssty', -- math + 'ssty', 'rtlm', -- math } local supported_gpos = { diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua index 47c2e0e9f..55cb734d6 100644 --- a/tex/context/base/font-ott.lua +++ b/tex/context/base/font-ott.lua @@ -87,7 +87,7 @@ otf.tables.scripts = { ['ugar'] = 'Ugaritic Cuneiform', ['xpeo'] = 'Old Persian Cuneiform', ['xsux'] = 'Sumero-Akkadian Cuneiform', - ['yi' ] = 'Yi' + ['yi' ] = 'Yi', } otf.tables.languages = { @@ -569,6 +569,7 @@ otf.tables.features = { ['rphf'] = 'Reph Form', ['rtbd'] = 'Right Bounds', ['rtla'] = 'Right-To-Left Alternates', + ['rtlm'] = 'Right To Left Math', -- math ['ruby'] = 'Ruby Notation Forms', ['salt'] = 'Stylistic Alternates', ['sinf'] = 'Scientific Inferiors', diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua index bd6413f41..f184fe2e5 100644 --- a/tex/context/base/font-syn.lua +++ b/tex/context/base/font-syn.lua @@ -8,6 +8,7 @@ if not modules then modules = { } end modules ['font-syn'] = { local next = next local gsub, lower, match, find, lower, upper = string.gsub, string.lower, string.match, string.find, string.lower, string.upper +local concat, sort, format = table.concat, table.sort, string.format local trace_names = false trackers.register("fonts.names", function(v) trace_names = v end) @@ -29,7 +30,7 @@ fonts.names.data = fonts.names.data or { } local names = fonts.names local filters = fonts.names.filters -names.version = 1.08 -- when adapting this, also changed font-dum.lua +names.version = 1.014 -- when adapting this, also changed font-dum.lua names.basename = "names" names.saved = false names.loaded = false @@ -103,12 +104,14 @@ filters.list = { "otf", "ttf", "ttc", "dfont", "afm", } -filters.fixes = { - { "reg$", "regular", }, - { "ita$", "italic", }, +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 @@ -196,7 +199,7 @@ function names.identify(verbose) -- lsr is for kpse } 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) + local function check(result, filename, suffix, is_sub) -- unlocal this one local fontname = result.fullname if fontname then local n = cleanname(result.fullname) @@ -373,6 +376,10 @@ function names.identify(verbose) -- lsr is for kpse 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) end + names.analyse(mapping) + names.analyse(fallback_mapping) + names.checkduplicates(mapping) + names.checkduplicates(fallback_mapping) end function names.is_permitted(name) @@ -385,6 +392,120 @@ 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 @@ -405,9 +526,11 @@ function names.load(reload,verbose) end end local data = names.data + -- names.analyse(data.mapping) + -- names.analyse(data.fallback_mapping) if data then - data.sorted = table.sortedkeys(data.mapping or { }) or { } - data.fallback_sorted = table.sortedkeys(data.fallback_mapping or { }) or { } + data.sorted = names.sorted(data.mapping) + data.fallback_sorted = names.sorted(data.fallback_mapping) else logs.report("font table", "accessing the data table failed") end @@ -494,26 +617,248 @@ local function found(name) end end +local function collect(stage,mapping,sorted,found,done,name,weight,style,width,all) + if not mapping or not sorted then + return + end +strictname = "^".. name + local f = mapping[name] + if weight ~= "" then + if style ~= "" then + if 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 + 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 + 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 + end + elseif style ~= "" then + if 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 + 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 + end + elseif 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 + 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 + 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 + 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 + 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 + 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 + 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]) + end + logs.report("fonts","name '%s' resolved to %s instances: %s",name,nf,concat(t," ")) + else + logs.report("fonts","name '%s' unresolved",name) + end + 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 + end +end + local reloaded = false -function names.specification(askedname, sub) +function names.specification(askedname,weight,style,width) if askedname and askedname ~= "" and names.enabled then - askedname = lower(askedname) + askedname = lower(askedname) -- or cleanname names.load() - local name, filename, is_sub = found(askedname) + 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 = found(askedname) + name, filename, is_sub = heuristic(askedname,weight,style,width) + if not filename then + name, filename, is_sub = found(askedname) -- old method + end end return name, filename, is_sub end end +function names.collect(askedname,weight,style,width) + if askedname and askedname ~= "" and names.enabled then + askedname = lower(askedname) -- or cleanname + names.load() + 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) + 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, 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)) +end + +function names.resolvespec(askedname,sub) + local name, filename, is_sub = names.specification(names.splitspec(askedname)) return filename, (is_sub and name) or sub end diff --git a/tex/context/base/l-dimen.lua b/tex/context/base/l-dimen.lua index ba22ab5a8..00e96586f 100644 --- a/tex/context/base/l-dimen.lua +++ b/tex/context/base/l-dimen.lua @@ -15,14 +15,19 @@ done by using the conversion factors collected in the following table.</p> --ldx]]-- -local format, type = string.format, type +local format, match, gsub, type, setmetatable = string.format, string.match, string.gsub, type, setmetatable + +number = number or { } + +number.tonumberf = function(n) return match(format("%.20f",n),"(.-0?)0*$") end -- one zero too much but alas +number.tonumberg = function(n) return format("%.20g",n) end local dimenfactors = { ["pt"] = 1/65536, ["in"] = ( 100/ 7227)/65536, ["cm"] = ( 254/ 7227)/65536, - ["mm"] = ( 254/72270)/65536, - ["sp"] = 1, + ["mm"] = ( 2540/ 7227)/65536, + ["sp"] = 1, -- 65536 sp in 1pt ["bp"] = ( 7200/ 7227)/65536, ["pc"] = ( 1/ 12)/65536, ["dd"] = ( 1157/ 1238)/65536, @@ -31,17 +36,62 @@ local dimenfactors = { ["nc"] = ( 5080/65043)/65536 } +--~ print(table.serialize(dimenfactors)) +--~ +--~ %.99g: +--~ +--~ t={ +--~ ["bp"]=1.5201782378580324e-005, +--~ ["cc"]=1.1883696112892098e-006, +--~ ["cm"]=5.3628510057769479e-007, +--~ ["dd"]=1.4260435335470516e-005, +--~ ["em"]=0.000152587890625, +--~ ["ex"]=6.103515625e-005, +--~ ["in"]=2.1113586636917117e-007, +--~ ["mm"]=5.3628510057769473e-008, +--~ ["nc"]=1.1917446679504327e-006, +--~ ["nd"]=1.4300936015405194e-005, +--~ ["pc"]=1.2715657552083333e-006, +--~ ["pt"]=1.52587890625e-005, +--~ ["sp"]=1, +--~ } +--~ +--~ patched %s and tonumber +--~ +--~ t={ +--~ ["bp"]=0.00001520178238, +--~ ["cc"]=0.00000118836961, +--~ ["cm"]=0.0000005362851, +--~ ["dd"]=0.00001426043534, +--~ ["em"]=0.00015258789063, +--~ ["ex"]=0.00006103515625, +--~ ["in"]=0.00000021113587, +--~ ["mm"]=0.00000005362851, +--~ ["nc"]=0.00000119174467, +--~ ["nd"]=0.00001430093602, +--~ ["pc"]=0.00000127156576, +--~ ["pt"]=0.00001525878906, +--~ ["sp"]=1, +--~ } + --[[ldx-- <p>A conversion function that takes a number, unit (string) and optional format (string) is implemented using this table.</p> --ldx]]-- +-- was: + local function todimen(n,unit,fmt) if type(n) == 'string' then return n else unit = unit or 'pt' - return format(fmt or "%.5f%s",n*dimenfactors[unit],unit) + return format(fmt or "%s%s",n*dimenfactors[unit],unit) + -- if fmt then + -- return format(fmt,n*dimenfactors[unit],unit) + -- else + -- return match(format("%.20f",n*dimenfactors[unit]),"(.-0?)0*$") .. unit + -- end end end @@ -49,8 +99,6 @@ end <p>We collect a bunch of converters in the <type>number</type> namespace.</p> --ldx]]-- -number = number or { } - number.todimen = todimen number.dimenfactors = dimenfactors @@ -89,8 +137,8 @@ alternative index function.</p> local mt = { } setmetatable(dimenfactors,mt) mt.__index = function(t,s) - error("wrong dimension: " .. (s or "?")) - return 1 + -- error("wrong dimension: " .. (s or "?")) -- better a message + return false end function string:todimen() @@ -262,7 +310,7 @@ is loaded, the relevant tables that hold the functions needed may not yet be available.</p> --ldx]]-- -function dimensions.texify() +function dimensions.texify() -- todo: % local fti, fc = fonts and fonts.ids and fonts.ids, font and font.current if fti and fc then dimenfactors["ex"] = function() return fti[fc()].ex_height end diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua index a5c490fbf..955b6cc36 100644 --- a/tex/context/base/l-file.lua +++ b/tex/context/base/l-file.lua @@ -33,8 +33,12 @@ function file.dirname(name,default) return match(name,"^(.+)[/\\].-$") or (default or "") end +--~ function file.basename(name) +--~ return match(name,"^.+[/\\](.-)$") or name +--~ end + function file.basename(name) - return match(name,"^.+[/\\](.-)$") or name + return match(name,"^.*[/\\](.-)$") or name end function file.nameonly(name) diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua index 87e694c0a..70a901e9d 100644 --- a/tex/context/base/l-table.lua +++ b/tex/context/base/l-table.lua @@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['l-table'] = { table.join = table.concat local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove -local format, find, gsub, lower, dump = string.format, string.find, string.gsub, string.lower, string.dump +local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match local getmetatable, setmetatable = getmetatable, setmetatable local type, next, tostring, tonumber, ipairs, pairs = type, next, tostring, tonumber, ipairs, pairs @@ -299,6 +299,8 @@ end -- -- local propername = lpeg.P(lpeg.R("AZ","az","__") * lpeg.R("09","AZ","az", "__")^0 * lpeg.P(-1) ) +-- problem: there no good number_to_string converter with the best resolution + local function do_serialize(root,name,depth,level,indexed) if level > 0 then depth = depth .. " " @@ -321,6 +323,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s{",depth)) end end + -- we could check for k (index) being number (cardinal) if root and next(root) then local first, last = nil, 0 -- #root cannot be trusted here if compact then @@ -343,7 +346,7 @@ local function do_serialize(root,name,depth,level,indexed) if hexify then handle(format("%s 0x%04X,",depth,v)) else - handle(format("%s %s,",depth,v)) + handle(format("%s %s,",depth,v)) -- %.99g end elseif t == "string" then if reduce and tonumber(v) then @@ -383,25 +386,25 @@ local function do_serialize(root,name,depth,level,indexed) --~ if hexify then --~ handle(format("%s %s=0x%04X,",depth,key(k),v)) --~ else - --~ handle(format("%s %s=%s,",depth,key(k),v)) + --~ handle(format("%s %s=%s,",depth,key(k),v)) -- %.99g --~ end if type(k) == "number" then -- or find(k,"^%d+$") then if hexify then handle(format("%s [0x%04X]=0x%04X,",depth,k,v)) else - handle(format("%s [%s]=%s,",depth,k,v)) + handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g end elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then if hexify then handle(format("%s %s=0x%04X,",depth,k,v)) else - handle(format("%s %s=%s,",depth,k,v)) + handle(format("%s %s=%s,",depth,k,v)) -- %.99g end else if hexify then handle(format("%s [%q]=0x%04X,",depth,k,v)) else - handle(format("%s [%q]=%s,",depth,k,v)) + handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g end end elseif t == "string" then diff --git a/tex/context/base/lxml-aux.lua b/tex/context/base/lxml-aux.lua index e52b3f629..79b0653a0 100644 --- a/tex/context/base/lxml-aux.lua +++ b/tex/context/base/lxml-aux.lua @@ -358,7 +358,7 @@ local function include(xmldata,pattern,attribute,recursive,loaddata) --~ local settings = xmldata.settings --~ settings.parent_root = xmldata -- to be tested --~ local xi = xmlconvert(data,settings) - local xi = xml.inheritedconvert(element,xmldata) + local xi = xml.inheritedconvert(data,xmldata) if not xi then epdt[ek.ni] = "" -- xml.empty(d,k) else diff --git a/tex/context/base/lxml-ini.mkiv b/tex/context/base/lxml-ini.mkiv index f1af79797..e0a217a2b 100644 --- a/tex/context/base/lxml-ini.mkiv +++ b/tex/context/base/lxml-ini.mkiv @@ -331,8 +331,10 @@ % % mkii: [\processXMLbuffer]\quad mkiv: [\xmlprocessbuffer{main}{}{}] -\def\xmlmapvalue#1#2#3{\setvalue{\??xm:v:#1:#2}{#3}} % keep #3 to grab spaces -\def\xmlvalue #1#2#3{\executeifdefined{\??xm:v:#1:#2}{#3}} +\def\xmlmapvalue #1#2#3{\setvalue{\??xm:v:#1:#2}{#3}} % keep #3 to grab spaces +\def\xmlvalue #1#2#3{\executeifdefined{\??xm:v:#1:#2}{#3}} +%def\xmlvalue #1#2{\ifcsname\??xm:v:#1:#2\endcsname\csname\??xm:v:#1:#2\expandafter\expandafter\gobbleoneargument\expandafter\endcsname\else\expandafter\firstofoneargument\fi} +\def\xmldoifelsevalue #1#2{\ifcsname\??xm:v:#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} \let\xmlmapval\xmlmapvalue \let\xmlval \xmlvalue diff --git a/tex/context/base/lxml-lpt.lua b/tex/context/base/lxml-lpt.lua index 254076349..b417e49d5 100644 --- a/tex/context/base/lxml-lpt.lua +++ b/tex/context/base/lxml-lpt.lua @@ -420,7 +420,7 @@ local noparent = 1 - (lparent+rparent) local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent} local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"} -local lp_child = Cc("expr.child(e,'") * R("az","AZ","--","__")^1 * Cc("')") +local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')") local lp_string = Cc("'") * R("az","AZ","--","__")^1 * Cc("'") local lp_content = (P("'") * (1-P("'"))^0 * P("'") + P('"') * (1-P('"'))^0 * P('"')) @@ -430,9 +430,9 @@ local lp_special = (C(P("name")+P("text")+P("tag")+P("count")+P("child"))) * val if expressions[t] then s = s and s ~= "" and cleaner:match(s) if s and s ~= "" then - return "expr." .. t .. "(e," .. s ..")" + return "expr." .. t .. "(ll," .. s ..")" else - return "expr." .. t .. "(e)" + return "expr." .. t .. "(ll)" end else return "expr.error(" .. t .. ")" @@ -982,38 +982,42 @@ expressions.name = function(e,n) -- ns + tg end expressions.tag = function(e,n) -- only tg - local found = false - n = tonumber(n) or 0 - if n == 0 then - found = (type(e) == "table") and e -- seems to fail - elseif n < 0 then - local d, k = e.__p__.dt, e.ni - for i=k-1,1,-1 do - local di = d[i] - if type(di) == "table" then - if n == -1 then - found = di - break - else - n = n + 1 + if not e then + return "" + else + local found = false + n = tonumber(n) or 0 + if n == 0 then + found = (type(e) == "table") and e -- seems to fail + elseif n < 0 then + local d, k = e.__p__.dt, e.ni + for i=k-1,1,-1 do + local di = d[i] + if type(di) == "table" then + if n == -1 then + found = di + break + else + n = n + 1 + end end end - end - else - local d, k = e.__p__.dt, e.ni - for i=k+1,#d,1 do - local di = d[i] - if type(di) == "table" then - if n == 1 then - found = di - break - else - n = n - 1 + else + local d, k = e.__p__.dt, e.ni + for i=k+1,#d,1 do + local di = d[i] + if type(di) == "table" then + if n == 1 then + found = di + break + else + n = n - 1 + end end end end + return (found and found.tg) or "" end - return (found and found.tg) or "" end --[[ldx-- diff --git a/tex/context/base/lxml-tex.lua b/tex/context/base/lxml-tex.lua index 92783d499..12f44b68e 100644 --- a/tex/context/base/lxml-tex.lua +++ b/tex/context/base/lxml-tex.lua @@ -376,13 +376,15 @@ function lxml.include(id,pattern,attribute,recurse) if filename then filename = commands.preparedfile(filename) if file.dirname(filename) == "" and root.filename then - filename = file.join(file.dirname(root.filename),filename) + local dn = file.dirname(root.filename) + if dn ~= "" then + filename = file.join(dn,filename) + end end if trace_loading then commands.writestatus("lxml","including file: %s",filename) end - noffiles = noffiles + 1 - nofconverted = nofconverted + 1 + noffiles, nofconverted = noffiles + 1, nofconverted + 1 return resolvers.loadtexfile(filename) or "" else return "" diff --git a/tex/context/base/mtx-context-arrange.tex b/tex/context/base/mtx-context-arrange.tex index 9d0bb901b..21a06b3a8 100644 --- a/tex/context/base/mtx-context-arrange.tex +++ b/tex/context/base/mtx-context-arrange.tex @@ -103,3 +103,5 @@ \stoptext + + diff --git a/tex/context/base/mult-sys.tex b/tex/context/base/mult-sys.tex index 88f7132e4..8600fd8f3 100644 --- a/tex/context/base/mult-sys.tex +++ b/tex/context/base/mult-sys.tex @@ -554,6 +554,7 @@ \definesystemvariable {pt} % PageshifT \definesystemvariable {py} % PropertYs \definesystemvariable {pv} % PublicationVariable +\definesystemvariable {ra} % RAise \definesystemvariable {rd} % RenDering \definesystemvariable {rf} % ReFereren \definesystemvariable {rg} % ReGel diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua index 242ea7ace..60c6e77f3 100644 --- a/tex/context/base/node-rul.lua +++ b/tex/context/base/node-rul.lua @@ -38,6 +38,75 @@ local texwrite = tex.write local fontdata = fonts.ids local variables = interfaces.variables +-- we can use this one elsewhere too +-- +-- todo: functions: word, sentence +-- +-- glyph rule unset whatsit glue margin_kern kern math disc + +local function process_words(attribute,data,flush,head,parent) + local n = head + if n then + local f, l, a, d, i, level + local continue, done = false, false + while n do + local id = n.id + if id == glyph then + local aa = has_attribute(n,attribute) + if aa then + if aa == a then + if not f then + f = n + end + l = n + else + -- possible extensions: when in same class then keep spanning + if f then + head, done = flush(head,f,l,d,level,parent), true + end + f, l, a = n, n, aa + level, i = floor(a/1000), a%1000 + d = data[i] + continue = d.continue == variables.yes + end + else + if f then + head, done = flush(head,f,l,d,level,parent), true + end + f, l, a = nil, nil, nil + end + elseif f and id == disc then + l = n + elseif f and id == kern and n.subtype == 0 then + l = n + elseif id == hlist or id == vlist then + if f then + head, done = flush(head,f,l,d,level,parent), true + f, l, a = nil, nil, nil + end + local list = n.list + if list then + n.list = process_words(attribute,data,flush,list,n) + end + elseif f and not continue then + head, done = flush(head,f,l,d,level,parent), true + f, l, a = nil, nil, nil + end + n = n.next + end + if f then + head, done = flush(head,f,l,d,level,parent), true + end + return head, true -- todo: done + else + return head, false + end +end + +nodes.process_words = process_words + +-- + nodes.rules = nodes.rules or { } nodes.rules.data = nodes.rules.data or { } @@ -50,7 +119,7 @@ function nodes.rules.define(settings) texwrite(#data) end -local function flush(head,f,l,d,level,parent) -- not that fast but acceptable for this purpose +local function flush_ruled(head,f,l,d,level,parent) -- not that fast but acceptable for this purpose local r, m local w = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,f,l.next) local method, offset, continue, dy, rulethickness, unit, order, max, ma, ca, ta = @@ -97,67 +166,56 @@ local function flush(head,f,l,d,level,parent) -- not that fast but acceptable fo return head end --- todo: functions: word, sentence +local process = nodes.process_words --- glyph rule unset whatsit glue margin_kern kern math disc +nodes.rules.process = function(head) return process(a_ruled,data,flush_ruled,head) end -local function process(head,parent) - local n = head - local f, l, a, d, i, level - local continue = false - while n do - local id = n.id - if id == glyph then - local aa = has_attribute(n,a_ruled) - if aa then - if aa == a then - if not f then - f = n - end - l = n - else - -- possible extensions: when in same class then keep spanning - if f then - head = flush(head,f,l,d,level,parent) - end - f, l, a = n, n, aa - level, i = floor(a/1000), a%1000 - d = data[i] - continue = d.continue == variables.yes - end - else - if f then - head = flush(head,f,l,d,level,parent) - end - f, l, a = nil, nil, nil - end - elseif f and id == disc then - l = n - elseif f and id == kern and n.subtype == 0 then - l = n - elseif id == hlist or id == vlist then - if f then - head = flush(head,f,l,d,level,parent) - f, l, a = nil, nil, nil - end - n.list = process(n.list,n) - elseif f and not continue then - head = flush(head,f,l,d,level,parent) - f, l, a = nil, nil, nil - end - n = n.next +function nodes.rules.enable() + tasks.enableaction("shipouts","nodes.rules.process") +end + +-- elsewhere: +-- +-- tasks.appendaction ("shipouts", "normalizers", "nodes.rules.process") +-- tasks.disableaction("shipouts", "nodes.rules.process") -- only kick in when used + +local a_shifted = attributes.private('shifted') + +nodes.shifts = nodes.shifts or { } +nodes.shifts.data = nodes.shifts.data or { } + +storage.register("nodes/shifts/data", nodes.shifts.data, "nodes.shifts.data") + +local data = nodes.shifts.data + +function nodes.shifts.define(settings) + data[#data+1] = settings + texwrite(#data) +end + +local function flush_shifted(head,first,last,data,level,parent) -- not that fast but acceptable for this purpose + local prev, next = first.prev, last.next + first.prev, last.next = nil, nil + local width, height, depth = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,first,next) + local list = node.hpack(first,width,"exactly") + if first == head then + head = list + end + if prev then + prev.next, list.prev = list, prev end - if f then - head = flush(head,f,l,d,level,parent) + if next then + next.prev, list.next = list, next end - return head, true -- todo: done + local raise = data.dy * dimenfactor(data.unit,fontdata[first.font]) + list.shift, list.height, list.depth = raise, height, depth + return head end -nodes.rules.process = function(head) return process(head) end +local process = nodes.process_words -function nodes.rules.enable() - tasks.enableaction("shipouts","nodes.rules.process") -end +nodes.shifts.process = function(head) return process(a_shifted,data,flush_shifted,head) end ---~ tasks.appendaction ("shipouts", "normalizers", "nodes.rules.process") ---~ tasks.disableaction("shipouts", "nodes.rules.process") -- only kick in when used +function nodes.shifts.enable() + tasks.enableaction("shipouts","nodes.shifts.process") +end diff --git a/tex/context/base/node-rul.mkiv b/tex/context/base/node-rul.mkiv index ea9f5364b..40d0014dc 100644 --- a/tex/context/base/node-rul.mkiv +++ b/tex/context/base/node-rul.mkiv @@ -56,6 +56,7 @@ \unprotect \definesystemattribute[ruled] +\definesystemattribute[shifted] \registerctxluafile{node-rul}{1.001} @@ -191,6 +192,115 @@ \def\setupunderbar[#1]% too incompatible for the moment {} +%D This will move: (a bit duplicated) + +\newtoks\checkalldefinedshifts + +\def\shiftparameter #1{\csname\doshiftparameter\currentshift#1\endcsname} +\def\shiftparameterhash#1{\doshiftparameterhash{\??ra\currentshift}#1} + +\def\doshiftparameter #1#2{\ifcsname\??ra#1#2\endcsname\??ra#1#2\else\expandafter\doshiftparentparameter\csname\??ra#1\s!parent\endcsname#2\fi} +\def\doshiftparameterhash#1#2{\ifcsname#1#2\endcsname#1\else\expandafter\doshiftparentparameterhash\csname#1\s!parent\endcsname#2\fi} + +\def\doshiftparentparameter #1#2{\ifx#1\relax\s!empty\else\doshiftparameter #1#2\fi} +\def\doshiftparentparameterhash#1#2{\ifx#1\relax \else\doshiftparameterhash#1#2\fi} + +\def\dosetshiftattributes#1#2% style color + {\edef\fontattributehash {\shiftparameterhash#1}% + \edef\colorattributehash{\shiftparameterhash#2}% + \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi + \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi} + +\def\defineshift + {\dotripleempty\dodefineshift} + +\def\dodefineshift[#1][#2][#3]% + {\ifthirdargument + \getparameters[\??ra#1][\s!parent=#2,#3]% + \else + \getparameters[\??ra#1][\s!parent=,#2]% + \fi + % + %\setvalue{\??ra:#1}{0}% + % + \ifcsname\??ra:#1:c\endcsname + \csname\??ra:#1:c\endcsname\zerocount + \else + \expandafter\newcount\csname\??ra:#1:c\endcsname + \fi + \normalexpanded{\checkalldefinedshifts{\noexpand\doredefineshift{#1}\the\checkalldefinedshifts}}% + \dodefineshiftindeed{#1}% + \unexpanded\setvalue{#1}{\doshifted{#1}}} + +\def\dodefineshiftindeed#1% + {\bgroup + \def\currentshift{#1}% + \normalexpanded + {\egroup + \scratchcounter\ctxlua{nodes.shifts.define { + method = \shiftparameter\c!method, + continue = "\shiftparameter\c!continue", + dy = \shiftparameter\c!dy, + unit = "\shiftparameter\c!unit", + }}}% + \setevalue{\??ra#1:a}{\the\scratchcounter}} + +\let\doredefineshift\dodefineshiftindeed + +\def\doshifted#1% + {\groupedcommand{\dodoshifted{#1}}\relax} + +\def\dodoshifted + {\ctxlua{nodes.shifts.enable()}% + \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}% + \dosetshiftattributes\c!style\c!color} + +\unexpanded\def\startshift[#1]% + {\begingroup + \dodoshifted{#1}} + +\unexpanded\def\stopshift + {\endgroup} + +\def\setupshifts + {\dodoubleempty\dosetupshifts} + +\def\dosetupshifts[#1][#2]% not that efficient + {\ifsecondargument + \getparameters[\??ra#1][#2]% + \dodefineshiftindeed{#1}% + \else + \getparameters[\??ra][#1]% + \the\checkalldefinedshifts + \fi} + +\setupshifts + [\c!method=0, + \c!continue=\v!no, + \c!dy=0, + \c!unit=ex, + \c!style=, + \c!color=] + +\def\v!shiftup {shiftup} +\def\v!shiftdown{shiftdown} + +\defineshift [\v!shiftup] [\c!method=0,\c!dy=-1,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=] +\defineshift [\v!shiftdown] [\c!method=1,\c!dy=.3,\c!unit=ex,\c!continue=\v!yes,\c!style=\txx,\c!color=] + +% we want these always so ... + +\expandafter\let\expandafter\shiftup \csname\v!shiftup \endcsname +\expandafter\let\expandafter\shiftdown \csname\v!shiftdown \endcsname + \protect \endinput % obsolete: diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua index c5f901e05..facec7911 100644 --- a/tex/context/base/page-lin.lua +++ b/tex/context/base/page-lin.lua @@ -12,6 +12,7 @@ local format = string.format local texsprint, texwrite, texbox = tex.sprint, tex.write, tex.box local ctxcatcodes = tex.ctxcatcodes +local variables = interfaces.variables nodes = nodes or { } nodes.lines = nodes.lines or { } @@ -119,12 +120,12 @@ end local leftskip = nodes.leftskip -local function check_number(n,a) -- move inline +local function check_number(n,a,skip) -- move inline local d = data[a] if d then local s = d.start current_list[#current_list+1] = { n, s } - if d.start % d.step == 0 then + if not skip and s % d.step == 0 then texsprint(ctxcatcodes, format("\\makenumber{%s}{%s}{%s}{%s}{%s}\\endgraf", d.tag or "", s, n.shift, n.width, leftskip(n.list))) else texsprint(ctxcatcodes, "\\skipnumber\\endgraf") @@ -141,21 +142,29 @@ function nodes.lines.boxed.stage_one(n) --~ while list.id == vlist and not list.next do --~ list = list.list --~ end + local last_a, skip = nil, false for n in traverse_id(hlist,list) do -- attr test here and quit as soon as zero found if n.height == 0 and n.depth == 0 then -- skip funny hlists else local a = has_attribute(n.list,line_number) if a and a > 0 then + if last_a ~= a then + if data[a].method == variables.next then + skip = true + end + last_a = a + end if has_attribute(n,display_math) then if nodes.is_display_math(n) then - check_number(n,a) + check_number(n,a,skip) end else if node.first_character(n.list) then - check_number(n,a) + check_number(n,a,skip) end end + skip = false end end end diff --git a/tex/context/base/page-lin.mkiv b/tex/context/base/page-lin.mkiv index 0a5c44554..e17cdea50 100644 --- a/tex/context/base/page-lin.mkiv +++ b/tex/context/base/page-lin.mkiv @@ -70,28 +70,35 @@ \def\mkdoprocessboxcontents #1{\mkaddtextlinenumbers{#1}\plusone \plusone} \def\mkdoprocesscolumncontents#1{\mkaddtextlinenumbers{#1}\currentcolumn\nofcolumns} -\def\mkcurrentstart{0} -\def\mkcurrentstep {1} - -\def\mkdefinetextlinenumbering#1% - {\begingroup - \scratchcounter\ctxlua{tex.sprint(nodes.lines.boxed.register({start=\mkcurrentstart,step=\mkcurrentstep,tag="#1"}))}% - \setxvalue{ln:c:#1}{\number\scratchcounter}% - \endgroup} +\def\mkdefinetextlinenumbering + {\setxvalue{ln:c:\currentlinenumbering}{\number\ctxlua{tex.sprint(nodes.lines.boxed.register({ + start = \linenumberparameter\c!start, + step = \linenumberparameter\c!step, + method = "\linenumberparameter\c!method", + tag = "\currentlinenumbering", + }))}}} \def\mkstarttextlinenumbering#1#2% {\globallet\mkprocesspagecontents \mkdoprocesspagecontents \globallet\mkprocesscolumncontents\mkdoprocesscolumncontents \global\settrue\boxcontentneedsprocessing % see core-rul.mkiv + \edef\currentlinenumbering{#1}% \ifcase#2\relax % continue \or - \mkdefinetextlinenumbering{#1}% restart + \mkdefinetextlinenumbering % restart \fi - \dosetattribute{line-number}{\getvalue{ln:c:#1}}} - -\def\mksetuptextlinenumbering#1% - {\ctxlua{nodes.lines.boxed.setup(\getvalue{ln:c:#1},{start=\mkcurrentstart,step=\mkcurrentstep,tag="#1"})}} + \dosetattribute{line-number}{\getvalue{ln:c:\currentlinenumbering}}} + +\def\mksetuptextlinenumbering + {\ifcsname ln:c:\currentlinenumbering\endcsname + \expanded{\ctxlua{nodes.lines.boxed.setup(\getvalue{ln:c:\currentlinenumbering},{ + start = \linenumberparameter\c!start, + step = \linenumberparameter\c!step, + method = "\linenumberparameter\c!method", + tag = "\currentlinenumbering" + })}}% + \fi} \def\mkstoptextlinenumbering {\doresetattribute{line-number}} @@ -138,8 +145,8 @@ {\dosingleempty\dodefinelinenumbering} \def\dodefinelinenumbering[#1]% - {\def\currentlinenumbering{#1}% - \mkdefinetextlinenumbering\currentlinenumbering} + {\edef\currentlinenumbering{#1}% + \mkdefinetextlinenumbering} \def\setuplinenumbering {\dodoubleempty\dosetuplinenumbering} @@ -152,7 +159,7 @@ \let\currentlinenumbering\empty \getparameters[\??rn][#1]% \fi - \mksetuptextlinenumbering\currentlinenumbering} + \mksetuptextlinenumbering} \def\linenumberparameter#1% {\csname\??rn\ifcsname\??rn\currentlinenumbering#1\endcsname\currentlinenumbering\fi#1\endcsname} @@ -160,12 +167,11 @@ \def\linenumberattributes {\doattributes{\??rn\ifcsname\??rn\currentlinenumbering\c!style\endcsname\currentlinenumbering\fi}} -\definelinenumbering - \setuplinenumbering [\c!conversion=\v!numbers, \c!start=1, \c!step=1, + \c!method=\v!first, \c!continue=v!no, \c!location=\v!left, \c!style=, @@ -177,15 +183,14 @@ \c!distance=\zeropoint, \c!align=\v!auto] +\definelinenumbering + \def\startlinenumbering {\dodoubleempty\dostartlinenumbering} % no intermediate changes in values, define a class, otherwise each range % would need a number -\def\mkcurrentstart{\linenumberparameter\c!start} -\def\mkcurrentstep {\linenumberparameter\c!step } - % todo: text \expandafter\chardef\csname\??rn:l:\v!middle \endcsname \zerocount diff --git a/tex/context/base/spac-hor.mkiv b/tex/context/base/spac-hor.mkiv index ee88f9656..fb3a9e794 100644 --- a/tex/context/base/spac-hor.mkiv +++ b/tex/context/base/spac-hor.mkiv @@ -343,6 +343,8 @@ \def\removelastspace{\ifhmode\unskip\fi} \def\nospace {\removelastspace\ignorespaces} +\ifdefined\softhyphen \else \let\softhyphen\- \fi + \ctxlua{tex.sprint(tex.ctxcatcodes,"\string\\unexpanded\string\\def\string\\\string\n{\string\\space}")} % \ctxlua{tex.sprint(tex.ctxcatcodes,"\string\\let\string\\\string\n=\string\\space")} diff --git a/tex/context/base/strc-doc.lua b/tex/context/base/strc-doc.lua index 465d10e97..02306f912 100644 --- a/tex/context/base/strc-doc.lua +++ b/tex/context/base/strc-doc.lua @@ -617,7 +617,7 @@ end function sections.fullnumber(depth) local data = data.status[depth or data.depth] if data then - local sectiondata = jobsections.collected[data.references.section] + local sectiondata = jobsections.collected[data.references.section] -- tobesaved? if sectiondata and sectiondata.hidenumber ~= true then -- can be nil sections.typesetnumber(sectiondata,'section',sectiondata) end diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua index 93783b041..42118436e 100644 --- a/tex/context/base/strc-ref.lua +++ b/tex/context/base/strc-ref.lua @@ -196,7 +196,7 @@ local function register_from_lists(collected,derived) if kind and realpage then local d = derived[prefix] if not d then d = { } derived[prefix] = d end local t = { kind, i } - for s in gmatch(reference,"[^, ]+") do + for s in gmatch(reference,"%s*([^,]+)") do if trace_referencing then logs.report("referencing","list entry %s provides %s reference '%s' on realpage %s)",i,kind,s,realpage) end diff --git a/tex/context/base/supp-box.tex b/tex/context/base/supp-box.tex index e314305d7..4c398973e 100644 --- a/tex/context/base/supp-box.tex +++ b/tex/context/base/supp-box.tex @@ -1897,6 +1897,13 @@ \advance\hsize \scratchdimen \divide\hsize #3\relax} +% == +% +% \def\setrigidcolumnhsize#1#2#3% +% {\xdef\savedrigidhsize{\the\hsize}% +% \global\chardef\rigidcolumns#3\relax +% \hsize=\dimexpr(#1-\numexpr#3-1\relax\dimexpr#2\relax)/#3\relax} + \newbox\rigidcolumnbox \let\rigidcolumnlines\!!zerocount diff --git a/tex/context/base/task-ini.lua b/tex/context/base/task-ini.lua index a0d5bc32a..dba099451 100644 --- a/tex/context/base/task-ini.lua +++ b/tex/context/base/task-ini.lua @@ -35,8 +35,10 @@ 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", "finishers", "shipouts.handle_color") tasks.appendaction("shipouts", "finishers", "shipouts.handle_transparency") diff --git a/tex/generic/context/luatex-fonts-merged.lua b/tex/generic/context/luatex-fonts-merged.lua index c64942372..70368ebd9 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/10/09 13:34:42 +-- merge date : 11/13/09 12:51:09 do -- begin closure to overcome local limits and interference @@ -537,7 +537,7 @@ if not modules then modules = { } end modules ['l-table'] = { table.join = table.concat local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove -local format, find, gsub, lower, dump = string.format, string.find, string.gsub, string.lower, string.dump +local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match local getmetatable, setmetatable = getmetatable, setmetatable local type, next, tostring, tonumber, ipairs, pairs = type, next, tostring, tonumber, ipairs, pairs @@ -827,6 +827,8 @@ end -- -- local propername = lpeg.P(lpeg.R("AZ","az","__") * lpeg.R("09","AZ","az", "__")^0 * lpeg.P(-1) ) +-- problem: there no good number_to_string converter with the best resolution + local function do_serialize(root,name,depth,level,indexed) if level > 0 then depth = depth .. " " @@ -849,6 +851,7 @@ local function do_serialize(root,name,depth,level,indexed) handle(format("%s{",depth)) end end + -- we could check for k (index) being number (cardinal) if root and next(root) then local first, last = nil, 0 -- #root cannot be trusted here if compact then @@ -871,7 +874,7 @@ local function do_serialize(root,name,depth,level,indexed) if hexify then handle(format("%s 0x%04X,",depth,v)) else - handle(format("%s %s,",depth,v)) + handle(format("%s %s,",depth,v)) -- %.99g end elseif t == "string" then if reduce and tonumber(v) then @@ -911,25 +914,25 @@ local function do_serialize(root,name,depth,level,indexed) --~ if hexify then --~ handle(format("%s %s=0x%04X,",depth,key(k),v)) --~ else - --~ handle(format("%s %s=%s,",depth,key(k),v)) + --~ handle(format("%s %s=%s,",depth,key(k),v)) -- %.99g --~ end if type(k) == "number" then -- or find(k,"^%d+$") then if hexify then handle(format("%s [0x%04X]=0x%04X,",depth,k,v)) else - handle(format("%s [%s]=%s,",depth,k,v)) + handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g end elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then if hexify then handle(format("%s %s=0x%04X,",depth,k,v)) else - handle(format("%s %s=%s,",depth,k,v)) + handle(format("%s %s=%s,",depth,k,v)) -- %.99g end else if hexify then handle(format("%s [%q]=0x%04X,",depth,k,v)) else - handle(format("%s [%q]=%s,",depth,k,v)) + handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g end end elseif t == "string" then @@ -1421,8 +1424,12 @@ function file.dirname(name,default) return match(name,"^(.+)[/\\].-$") or (default or "") end +--~ function file.basename(name) +--~ return match(name,"^.+[/\\](.-)$") or name +--~ end + function file.basename(name) - return match(name,"^.+[/\\](.-)$") or name + return match(name,"^.*[/\\](.-)$") or name end function file.nameonly(name) @@ -4337,7 +4344,7 @@ otf.tables.scripts = { ['ugar'] = 'Ugaritic Cuneiform', ['xpeo'] = 'Old Persian Cuneiform', ['xsux'] = 'Sumero-Akkadian Cuneiform', - ['yi' ] = 'Yi' + ['yi' ] = 'Yi', } otf.tables.languages = { @@ -4819,6 +4826,7 @@ otf.tables.features = { ['rphf'] = 'Reph Form', ['rtbd'] = 'Right Bounds', ['rtla'] = 'Right-To-Left Alternates', + ['rtlm'] = 'Right To Left Math', -- math ['ruby'] = 'Ruby Notation Forms', ['salt'] = 'Stylistic Alternates', ['sinf'] = 'Scientific Inferiors', @@ -7299,7 +7307,7 @@ local supported_gsub = { 'zero', 'smcp','cpsp','c2sc','ornm','aalt', 'hwid','fwid', - 'ssty', -- math + 'ssty', 'rtlm', -- math } local supported_gpos = { @@ -10559,17 +10567,28 @@ local right = P(")") local colon = P(":") local space = P(" ") +define.defaultlookup = "file" + +local prefixpattern = P(false) + function define.add_specifier(symbol) specifiers = specifiers .. symbol local method = S(specifiers) - local lookup = C(P("file")+P("name")) * colon -- hard test, else problems with : method + local lookup = C(prefixpattern) * colon local sub = left * C(P(1-left-right-method)^1) * right ---~ local specification = C(method) * C(P(1-method)^1) local specification = C(method) * C(P(1)^1) local name = C((1-sub-specification)^1) splitter = P((lookup + Cc("")) * name * (sub + Cc("")) * (specification + Cc(""))) end +function define.add_lookup(str,default) + prefixpattern = prefixpattern + P(str) +end + +define.add_lookup("file") +define.add_lookup("name") +define.add_lookup("spec") + function define.get_specification(str) return splitter:match(str) end @@ -10590,8 +10609,8 @@ function define.makespecification(specification, lookup, name, sub, method, deta --~ lookup = specification.lookup -- can come from xetex [] syntax --~ specification.lookup = nil --~ end - if lookup ~= 'name' then -- for the moment only two lookups, maybe some day also system: - lookup = 'file' + if not lookup or lookup == "" then + lookup = define.defaultlookup end local t = { lookup = lookup, -- forced type @@ -10693,17 +10712,44 @@ end <p>We can resolve the filename using the next function:</p> --ldx]]-- +define.resolvers = resolvers + +function define.resolvers.file(specification) + specification.forced = file.extname(specification.name) + specification.name = file.removesuffix(specification.name) +end + +function define.resolvers.name(specification) + local resolve = fonts.names.resolve + if resolve then + specification.resolved, specification.sub = fonts.names.resolve(specification.name,specification.sub) + if specification.resolved then + specification.forced = file.extname(specification.resolved) + specification.name = file.removesuffix(specification.resolved) + end + else + define.resolvers.file(specification) + end +end + +function define.resolvers.spec(specification) + local resolvespec = fonts.names.resolvespec + if resolvespec then + specification.resolved, specification.sub = fonts.names.resolvespec(specification.name,specification.sub) + if specification.resolved then + specification.forced = file.extname(specification.resolved) + specification.name = file.removesuffix(specification.resolved) + end + else + define.resolvers.name(specification) + end +end + function define.resolve(specification) if not specification.resolved or specification.resolved == "" then -- resolved itself not per se in mapping hash - if specification.lookup == 'name' then - specification.resolved, specification.sub = fonts.names.resolve(specification.name,specification.sub) - if specification.resolved then - specification.forced = file.extname(specification.resolved) - specification.name = file.removesuffix(specification.resolved) - end - elseif specification.lookup == 'file' then - specification.forced = file.extname(specification.name) - specification.name = file.removesuffix(specification.name) + local r = define.resolvers[specification.lookup] + if r then + r(specification) end end if specification.forced == "" then @@ -10711,7 +10757,6 @@ function define.resolve(specification) else specification.forced = specification.forced end ---~ specification.hash = specification.name .. ' @ ' .. tfm.hash_features(specification) specification.hash = lower(specification.name .. ' @ ' .. tfm.hash_features(specification)) if specification.sub and specification.sub ~= "" then specification.hash = specification.sub .. ' @ ' .. specification.hash @@ -11479,6 +11524,7 @@ end fonts.names = fonts.names or { } +fonts.names.version = 1.014 fonts.names.basename = "luatex-fonts-names.lua" fonts.names.new_to_old = { } fonts.names.old_to_new = { } @@ -11509,7 +11555,7 @@ function fonts.names.resolve(name,sub) end loaded = true end - if type(data) == "table" and data.version == 1.08 then + if type(data) == "table" and data.version == fonts.names.version then local condensed = string.gsub(string.lower(name),"[^%a%d]","") local found = data.mapping and data.mapping[condensed] if found then @@ -11522,6 +11568,8 @@ function fonts.names.resolve(name,sub) end end +fonts.names.resolvespec = fonts.names.resolve -- only supported in mkiv + -- For the moment we put this (adapted) pseudo feature here. table.insert(fonts.triggers,"itlc") |