From b0f61c557fa27bddb54ad085c9dc9beefc851a30 Mon Sep 17 00:00:00 2001
From: Marius We start with a registration system for atributes so that we can use the
+symbolic names later on. We can use the attributes in the range 127-255 (outside user space). These
+are only used when no attribute is set at the \TEX\ end which normally
+happens in This table specifies what stub files are needed in order to create
+the format. These files are loaded before the format is made so that we
+bypass kpse. When the format itself is used, another stub is used (with
+suffix lui). The current format builder is to a large part determined by
+the way luatex evolved and the process will probaby change. If you wondered about some of the previous mappings, how about
+the next bunch:
Here we deal with defining fonts. We do so by intercepting the
default loader that only handles
Here we replace start by new glyph. First we delete the rest of the match.
--ldx]]-- -function chainprocs.gsub_alternate(start,stop,kind,lookupname,currentcontext,cache,currentlookup) +function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,cache,currentlookup,chainlookupname) -- todo: marks ? delete_till_stop(start,stop) local current = start @@ -1155,7 +1159,7 @@ function chainprocs.gsub_ligature(start,stop,kind,chainname,currentcontext,cache logprocess("%s: replacing character %s upto %s by ligature %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2)) end end - start = toligature(kind,lookup,start,stop,l2,currentlookup.flags[1],discfound) + start = toligature(kind,lookupname,start,stop,l2,currentlookup.flags[1],discfound) return start, true, nofreplacements elseif trace_bugs then if start == stop then @@ -1490,7 +1494,7 @@ function chainprocs.gpos_pair(start,stop,kind,chainname,currentcontext,cache,cur end end else - logs.report("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname)) + report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname)) local a, b = krn[3], krn[7] if a and a ~= 0 then local k = set_kern(snext,factor,rlmode,a) @@ -1864,12 +1868,11 @@ local function logprocess(...) if trace_steps then registermessage(...) end - logs.report("otf process",...) -end -local function logwarning(...) - logs.report("otf process",...) + report_process(...) end +local logwarning = report_process + local function report_missing_cache(typ,lookup) local f = missing[currentfont] if not f then f = { } missing[currentfont] = f end local t = f[typ] if not t then t = { } f[typ] = t end @@ -1882,6 +1885,9 @@ end local resolved = { } -- we only resolve a font,script,language pair once -- todo: pass all these 'locals' in a table +-- +-- dynamics will be isolated some day ... for the moment we catch attribute zero +-- not being set function fonts.methods.node.otf.features(head,font,attr) if trace_steps then @@ -1926,8 +1932,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 pardir, txtdir, success = 0, { }, false local sequence = sequences[s] local r = ra[s] -- cache if r == nil then @@ -1965,7 +1970,7 @@ function fonts.methods.node.otf.features(head,font,attr) end if trace_applied then local typ, action = match(sequence.type,"(.*)_(.*)") - logs.report("otf node mode", + report_process( "%s font: %03i, dynamic: %03i, kind: %s, lookup: %3i, script: %-4s, language: %-4s (%-4s), type: %s, action: %s, name: %s", (valid and "+") or "-",font,attr or 0,kind,s,script,language,what,typ,action,sequence.name) end @@ -1994,24 +1999,33 @@ function fonts.methods.node.otf.features(head,font,attr) while start do local id = start.id if id == glyph then - if start.subtype<256 and start.font == font and (not attr or has_attribute(start,0,attr)) then ---~ if start.subtype<256 and start.font == font and has_attribute(start,0,attr) then - for i=1,#subtables do - local lookupname = subtables[i] - local lookupcache = thecache[lookupname] - if lookupcache then - local lookupmatch = lookupcache[start.char] - if lookupmatch then - start, success = handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,i) - if success then - break + if start.subtype<256 and start.font == font then + local a = has_attribute(start,0) + if a then + a = a == attr + else + a = true + end + if a then + for i=1,#subtables do + local lookupname = subtables[i] + local lookupcache = thecache[lookupname] + if lookupcache then + local lookupmatch = lookupcache[start.char] + if lookupmatch then + start, success = handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,i) + if success then + break + end end + else + report_missing_cache(typ,lookupname) end - else - report_missing_cache(typ,lookupname) end + if start then start = start.prev end + else + start = start.prev end - if start then start = start.prev end else start = start.prev end @@ -2034,18 +2048,27 @@ function fonts.methods.node.otf.features(head,font,attr) while start do local id = start.id if id == glyph then ---~ if start.font == font and start.subtype<256 and has_attribute(start,0,attr) and (not attribute or has_attribute(start,state,attribute)) then - if start.font == font and start.subtype<256 and (not attr or has_attribute(start,0,attr)) and (not attribute or has_attribute(start,state,attribute)) then - local lookupmatch = lookupcache[start.char] - if lookupmatch then - -- sequence kan weg - local ok - start, ok = handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,1) - if ok then - success = true + if start.subtype<256 and start.font == font then + local a = has_attribute(start,0) + if a then + a = (a == attr) and (not attribute or has_attribute(start,state,attribute)) + else + a = not attribute or has_attribute(start,state,attribute) + end + if a then + local lookupmatch = lookupcache[start.char] + if lookupmatch then + -- sequence kan weg + local ok + start, ok = handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,1) + if ok then + success = true + end end + if start then start = start.next end + else + start = start.next end - if start then start = start.next end else start = start.next end @@ -2082,7 +2105,7 @@ function fonts.methods.node.otf.features(head,font,attr) 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) + report_process("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 @@ -2096,7 +2119,7 @@ function fonts.methods.node.otf.features(head,font,attr) 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) + report_process("directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode) end end start = start.next @@ -2109,27 +2132,36 @@ function fonts.methods.node.otf.features(head,font,attr) while start do local id = start.id if id == glyph then - if start.subtype<256 and start.font == font and (not attr or has_attribute(start,0,attr)) and (not attribute or has_attribute(start,state,attribute)) then ---~ if start.subtype<256 and start.font == font and has_attribute(start,0,attr) and (not attribute or has_attribute(start,state,attribute)) then - for i=1,ns do - local lookupname = subtables[i] - local lookupcache = thecache[lookupname] - if lookupcache then - local lookupmatch = lookupcache[start.char] - if lookupmatch then - -- we could move all code inline but that makes things even more unreadable - local ok - start, ok = handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,i) - if ok then - success = true - break + if start.subtype<256 and start.font == font then + local a = has_attribute(start,0) + if a then + a = (a == attr) and (not attribute or has_attribute(start,state,attribute)) + else + a = not attribute or has_attribute(start,state,attribute) + end + if a then + for i=1,ns do + local lookupname = subtables[i] + local lookupcache = thecache[lookupname] + if lookupcache then + local lookupmatch = lookupcache[start.char] + if lookupmatch then + -- we could move all code inline but that makes things even more unreadable + local ok + start, ok = handler(start,r[4],lookupname,lookupmatch,sequence,featuredata,i) + if ok then + success = true + break + end end + else + report_missing_cache(typ,lookupname) end - else - report_missing_cache(typ,lookupname) end + if start then start = start.next end + else + start = start.next end - if start then start = start.next end else start = start.next end @@ -2149,7 +2181,6 @@ function fonts.methods.node.otf.features(head,font,attr) -- start = start.next -- end elseif id == whatsit then - local subtype = start.subtype local subtype = start.subtype if subtype == 7 then local dir = start.dir @@ -2167,7 +2198,7 @@ function fonts.methods.node.otf.features(head,font,attr) 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) + report_process("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 @@ -2181,7 +2212,7 @@ function fonts.methods.node.otf.features(head,font,attr) 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) + report_process("directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode) end end start = start.next @@ -2280,7 +2311,7 @@ local function prepare_lookups(tfmdata) -- as well (no big deal) -- local action = { - substitution = function(p,lookup,k,glyph,unicode) + substitution = function(p,lookup,glyph,unicode) local old, new = unicode, unicodes[p[2]] if type(new) == "table" then new = new[1] @@ -2289,10 +2320,10 @@ local function prepare_lookups(tfmdata) if not s then s = { } single[lookup] = s end s[old] = new --~ if trace_lookups then - --~ logs.report("define otf","lookup %s: substitution %s => %s",lookup,old,new) + --~ report_prepare("lookup %s: substitution %s => %s",lookup,old,new) --~ end end, - multiple = function (p,lookup,k,glyph,unicode) + multiple = function (p,lookup,glyph,unicode) local old, new = unicode, { } local m = multiple[lookup] if not m then m = { } multiple[lookup] = m end @@ -2306,10 +2337,10 @@ local function prepare_lookups(tfmdata) end end --~ if trace_lookups then - --~ logs.report("define otf","lookup %s: multiple %s => %s",lookup,old,concat(new," ")) + --~ report_prepare("lookup %s: multiple %s => %s",lookup,old,concat(new," ")) --~ end end, - alternate = function(p,lookup,k,glyph,unicode) + alternate = function(p,lookup,glyph,unicode) local old, new = unicode, { } local a = alternate[lookup] if not a then a = { } alternate[lookup] = a end @@ -2323,12 +2354,12 @@ local function prepare_lookups(tfmdata) end end --~ if trace_lookups then - --~ logs.report("define otf","lookup %s: alternate %s => %s",lookup,old,concat(new,"|")) + --~ report_prepare("lookup %s: alternate %s => %s",lookup,old,concat(new,"|")) --~ end end, - ligature = function (p,lookup,k,glyph,unicode) + ligature = function (p,lookup,glyph,unicode) --~ if trace_lookups then - --~ logs.report("define otf","lookup %s: ligature %s => %s",lookup,p[2],glyph.name) + --~ report_prepare("lookup %s: ligature %s => %s",lookup,p[2],glyph.name) --~ end local first = true local t = ligature[lookup] @@ -2337,7 +2368,7 @@ local function prepare_lookups(tfmdata) if first then local u = unicodes[s] if not u then - logs.report("define otf","lookup %s: ligature %s => %s ignored due to invalid unicode",lookup,p[2],glyph.name) + report_prepare("lookup %s: ligature %s => %s ignored due to invalid unicode",lookup,p[2],glyph.name) break elseif type(u) == "number" then if not t[u] then @@ -2374,13 +2405,13 @@ local function prepare_lookups(tfmdata) end t[2] = unicode end, - position = function(p,lookup,k,glyph,unicode) + position = function(p,lookup,glyph,unicode) -- not used local s = position[lookup] if not s then s = { } position[lookup] = s end s[unicode] = p[2] -- direct pointer to kern spec end, - pair = function(p,lookup,k,glyph,unicode) + pair = function(p,lookup,glyph,unicode) local s = pair[lookup] if not s then s = { } pair[lookup] = s end local others = s[unicode] @@ -2407,7 +2438,7 @@ local function prepare_lookups(tfmdata) end end --~ if trace_lookups then - --~ logs.report("define otf","lookup %s: pair for U+%04X",lookup,unicode) + --~ report_prepare("lookup %s: pair for U+%04X",lookup,unicode) --~ end end, } @@ -2416,7 +2447,7 @@ local function prepare_lookups(tfmdata) local lookups = glyph.slookups if lookups then for lookup, p in next, lookups do - action[p[1]](p,lookup,k,glyph,unicode) + action[p[1]](p,lookup,glyph,unicode) end end local lookups = glyph.mlookups @@ -2424,7 +2455,7 @@ local function prepare_lookups(tfmdata) for lookup, whatever in next, lookups do for i=1,#whatever do -- normaly one local p = whatever[i] - action[p[1]](p,lookup,k,glyph,unicode) + action[p[1]](p,lookup,glyph,unicode) end end end @@ -2435,7 +2466,7 @@ local function prepare_lookups(tfmdata) if not k then k = { } kerns[lookup] = k end k[unicode] = krn -- ref to glyph, saves lookup --~ if trace_lookups then - --~ logs.report("define otf","lookup %s: kern for U+%04X",lookup,unicode) + --~ report_prepare("lookup %s: kern for U+%04X",lookup,unicode) --~ end end end @@ -2451,7 +2482,7 @@ local function prepare_lookups(tfmdata) if not f then f = { } mark[lookup] = f end f[unicode] = anchors -- ref to glyph, saves lookup --~ if trace_lookups then - --~ logs.report("define otf","lookup %s: mark anchor %s for U+%04X",lookup,name,unicode) + --~ report_prepare("lookup %s: mark anchor %s for U+%04X",lookup,name,unicode) --~ end end end @@ -2465,7 +2496,7 @@ local function prepare_lookups(tfmdata) if not f then f = { } cursive[lookup] = f end f[unicode] = anchors -- ref to glyph, saves lookup --~ if trace_lookups then - --~ logs.report("define otf","lookup %s: exit anchor %s for U+%04X",lookup,name,unicode) + --~ report_prepare("lookup %s: exit anchor %s for U+%04X",lookup,name,unicode) --~ end end end @@ -2479,7 +2510,7 @@ end -- local cache = { } luatex = luatex or {} -- this has to change ... we need a better one -function prepare_contextchains(tfmdata) +local function prepare_contextchains(tfmdata) local otfdata = tfmdata.shared.otfdata local lookups = otfdata.lookups if lookups then @@ -2498,7 +2529,7 @@ function prepare_contextchains(tfmdata) for lookupname, lookupdata in next, otfdata.lookups do local lookuptype = lookupdata.type if not lookuptype then - logs.report("otf process","missing lookuptype for %s",lookupname) + report_prepare("missing lookuptype for %s",lookupname) else local rules = lookupdata.rules if rules then @@ -2506,7 +2537,7 @@ function prepare_contextchains(tfmdata) -- contextchain[lookupname][unicode] if fmt == "coverage" then if lookuptype ~= "chainsub" and lookuptype ~= "chainpos" then - logs.report("otf process","unsupported coverage %s for %s",lookuptype,lookupname) + report_prepare("unsupported coverage %s for %s",lookuptype,lookupname) else local contexts = contextchain[lookupname] if not contexts then @@ -2542,7 +2573,7 @@ function prepare_contextchains(tfmdata) end elseif fmt == "reversecoverage" then if lookuptype ~= "reversesub" then - logs.report("otf process","unsupported reverse coverage %s for %s",lookuptype,lookupname) + report_prepare("unsupported reverse coverage %s for %s",lookuptype,lookupname) else local contexts = reversecontextchain[lookupname] if not contexts then @@ -2582,7 +2613,7 @@ function prepare_contextchains(tfmdata) end elseif fmt == "glyphs" then if lookuptype ~= "chainsub" and lookuptype ~= "chainpos" then - logs.report("otf process","unsupported coverage %s for %s",lookuptype,lookupname) + report_prepare("unsupported coverage %s for %s",lookuptype,lookupname) else local contexts = contextchain[lookupname] if not contexts then @@ -2653,7 +2684,7 @@ function fonts.initializers.node.otf.features(tfmdata,value) prepare_lookups(tfmdata) otfdata.shared.initialized = true if trace_preparing then - logs.report("otf process","preparation time is %0.3f seconds for %s",os.clock()-t,tfmdata.fullname or "?") + report_prepare("preparation time is %0.3f seconds for %s",os.clock()-t,tfmdata.fullname or "?") end end end diff --git a/tex/context/base/font-otp.lua b/tex/context/base/font-otp.lua index a80c515ad..f01468bf2 100644 --- a/tex/context/base/font-otp.lua +++ b/tex/context/base/font-otp.lua @@ -13,6 +13,8 @@ local sort, concat = table.sort, table.concat local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end) +local report_otf = logs.new("load otf") + fonts = fonts or { } fonts.otf = fonts.otf or { } fonts.otf.enhancers = fonts.otf.enhancers or { } @@ -70,7 +72,7 @@ function fonts.otf.enhancers.pack(data) local function success(stage,pass) if #t == 0 then if trace_loading then - logs.report("load otf","pack quality: nothing to pack") + report_otf("pack quality: nothing to pack") end return false elseif #t >= threshold then @@ -98,12 +100,12 @@ function fonts.otf.enhancers.pack(data) data.tables = tt end if trace_loading then - logs.report("load otf","pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)", stage, pass, one+two+rest, one, two, rest, criterium) + report_otf("pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)", stage, pass, one+two+rest, one, two, rest, criterium) end return true else if trace_loading then - logs.report("load otf","pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)", stage, pass, #t, threshold) + report_otf("pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)", stage, pass, #t, threshold) end return false end diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua index 2be1bf06c..c56e98498 100644 --- a/tex/context/base/font-ott.lua +++ b/tex/context/base/font-ott.lua @@ -696,7 +696,6 @@ function otf.meanings.normalize(features) k = lower(k) if k == "language" or k == "lang" then v = gsub(lower(v),"[^a-z0-9%-]","") - k = language if not languages[v] then h.language = to_languages[v] or "dflt" else diff --git a/tex/context/base/font-pat.lua b/tex/context/base/font-pat.lua index 6aba4d47e..b6531abb9 100644 --- a/tex/context/base/font-pat.lua +++ b/tex/context/base/font-pat.lua @@ -10,6 +10,8 @@ local match, lower, find = string.match, string.lower, string.find local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end) +local report_otf = logs.new("load otf") + -- this will become a per font patch file -- -- older versions of latin modern didn't have the designsize set @@ -22,7 +24,7 @@ local function patch(data,filename) local ds = match(file.basename(lower(filename)),"(%d+)") if ds then if trace_loading then - logs.report("load otf","patching design size (%s)",ds) + report_otf("patching design size (%s)",ds) end data.design_size = tonumber(ds) * 10 end @@ -32,7 +34,7 @@ local function patch(data,filename) -- beware, this is a hack, features for latin often don't apply to greek -- but lm has not much features anyway (and only greek for math) if trace_loading then - logs.report("load otf","adding 13 greek capitals") + report_otf("adding 13 greek capitals") end uni_to_ind[0x391] = uni_to_ind[0x41] uni_to_ind[0x392] = uni_to_ind[0x42] @@ -75,7 +77,7 @@ local function patch(data,filename) local v = gpos[k] if not v.features and v.type == "gpos_mark2mark" then if trace_loading then - logs.report("load otf","patching mkmk feature (name: %s)", v.name or "?") + report_otf("patching mkmk feature (name: %s)", v.name or "?") end v.features = { { @@ -101,7 +103,7 @@ local function patch_domh(data,filename,threshold) local d = m.DisplayOperatorMinHeight or 0 if d < threshold then if trace_loading then - logs.report("load otf","patching DisplayOperatorMinHeight(%s -> %s)",d,threshold) + report_otf("patching DisplayOperatorMinHeight(%s -> %s)",d,threshold) end m.DisplayOperatorMinHeight = threshold end @@ -113,7 +115,7 @@ local function patch_domh(data,filename,threshold) local width, italic = g.width or 0, g.italic_correction or 0 local newwidth = width - italic if trace_loading then - logs.report("load otf","patching width of %s: %s (width) - %s (italic) = %s",name,width,italic,newwidth) + report_otf("patching width of %s: %s (width) - %s (italic) = %s",name,width,italic,newwidth) end g.width = newwidth end diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua index 5ad92e002..b698fe27f 100644 --- a/tex/context/base/font-syn.lua +++ b/tex/context/base/font-syn.lua @@ -20,6 +20,8 @@ local unpack = unpack or table.unpack local trace_names = false trackers.register("fonts.names", function(v) trace_names = v end) local trace_warnings = false trackers.register("fonts.warnings", function(v) trace_warnings = v end) +local report_names = logs.new("fontnames") + --[[ldx--This module implements a name to filename resolver. Names are resolved using a table that has keys filtered from the font related files.
@@ -44,7 +46,7 @@ names.saved = false names.loaded = false names.be_clever = true names.enabled = true -names.autoreload = toboolean(os.env['MTX.FONTS.AUTOLOAD'] or os.env['MTX_FONTS_AUTOLOAD'] or "no") +names.autoreload = toboolean(os.getenv('MTX.FONTS.AUTOLOAD') or os.getenv('MTX_FONTS_AUTOLOAD') or "no") names.cache = containers.define("fonts","data",names.version,true) --[[ldx-- @@ -123,13 +125,13 @@ function names.splitspec(askedname) width = width and lpegmatch(widths, width) or width variant = variant and lpegmatch(variants,variant) or variant if trace_names then - logs.report("fonts","requested name '%s' split in name '%s', weight '%s', style '%s', width '%s' and variant '%s'", + report_names("requested name '%s' split in name '%s', weight '%s', style '%s', width '%s' and variant '%s'", askedname,name or '',weight or '',style or '',width or '',variant or '') end if not weight or not weight or not width or not variant then weight, style, width, variant = weight or "normal", style or "normal", width or "normal", variant or "normal" if trace_names then - logs.report("fonts","request '%s' normalized to '%s-%s-%s-%s-%s'", + report_names("request '%s' normalized to '%s-%s-%s-%s-%s'", askedname,name,weight,style,width,variant) end end @@ -218,11 +220,12 @@ filters.names = { } function names.getpaths(trace) local hash, result = { }, { } - local function collect(t) + local function collect(t,where) for i=1, #t do local v = resolvers.clean_path(t[i]) - v = gsub(v,"/+$","") + v = gsub(v,"/+$","") -- not needed any more local key = lower(v) + report_names("adding path from %s: %s",where,v) if not hash[key] then hash[key], result[#result+1] = true, v end @@ -230,13 +233,16 @@ function names.getpaths(trace) end local path = names.environment_path_variable or "" if path ~= "" then - collect(resolvers.expanded_path_list(path)) + collect(resolvers.expanded_path_list(path),path) end if xml then - local confname = names.xml_configuration_file or "" + local confname = resolvers.getenv("FONTCONFIG_FILE") or "" + if confname == "" then + confname = names.xml_configuration_file or "" + end if confname ~= "" then -- first look in the tex tree - local name = resolvers.find_file(confname,"other") + local name = resolvers.find_file(confname,"fontconfig files") or "" if name == "" then -- after all, fontconfig is a unix thing name = file.join("/etc",confname) @@ -246,7 +252,7 @@ function names.getpaths(trace) end if name ~= "" and lfs.isfile(name) then if trace_names then - logs.report("fontnames","loading fontconfig file: %s",name) + report_names("loading fontconfig file: %s",name) end local xmldata = xml.load(name) -- begin of untested mess @@ -259,19 +265,19 @@ function names.getpaths(trace) end if lfs.isfile(incname) then if trace_names then - logs.report("fontnames","merging included fontconfig file: %s",incname) + report_names("merging included fontconfig file: %s",incname) end return io.loaddata(incname) elseif trace_names then - logs.report("fontnames","ignoring included fontconfig file: %s",incname) + report_names("ignoring included fontconfig file: %s",incname) end end) -- end of untested mess local fontdirs = xml.collect_texts(xmldata,"dir",true) if trace_names then - logs.report("fontnames","%s dirs found in fontconfig",#fontdirs) + report_names("%s dirs found in fontconfig",#fontdirs) end - collect(fontdirs) + collect(fontdirs,"fontconfig file") end end end @@ -308,7 +314,7 @@ local function walk_tree(pathlist,suffix,identify) path = resolvers.clean_path(path .. "/") path = gsub(path,"/+","/") local pattern = path .. "**." .. suffix -- ** forces recurse - logs.report("fontnames", "globbing path %s",pattern) + report_names( "globbing path %s",pattern) local t = dir.glob(pattern) sort(t,sorter) for j=1,#t do @@ -529,12 +535,12 @@ local function checkduplicate(where) -- fails on "Romantik" but that's a border local nv = #v if nv > 1 then if trace_warnings then - logs.report("fontnames", "double lookup: %s => %s",k,concat(v," | ")) + report_names( "double lookup: %s => %s",k,concat(v," | ")) end n = n + nv end end - logs.report("fontnames", "%s double lookups in %s",n,where) + report_names( "%s double lookups in %s",n,where) end local function checkduplicates() @@ -590,26 +596,43 @@ end local function analysefiles() local data = names.data - local done, totalnofread, totalnofskipped = { }, 0, 0 + local done, totalnofread, totalnofskipped, totalnofduplicates, nofread, nofskipped, nofduplicates = { }, 0, 0, 0, 0, 0, 0 local skip_paths, skip_names = filters.paths, filters.names local function identify(completename,name,suffix,storedname) local basename = file.basename(completename) local basepath = file.dirname(completename) + nofread = nofread + 1 if done[name] then -- already done (avoid otf afm clash) + if trace_names then + report_names("%s font %s already done",suffix,completename) + logs.push() + end + nofduplicates = nofduplicates + 1 + nofskipped = nofskipped + 1 elseif not io.exists(completename) then -- weird error + if trace_names then + report_names("%s font %s does not really exist",suffix,completename) + logs.push() + end + nofskipped = nofskipped + 1 elseif not file.is_qualified_path(completename) and resolvers.find_file(completename,suffix) == "" then -- not locateble by backend anyway + if trace_names then + report_names("%s font %s cannot be found by backend",suffix,completename) + logs.push() + end + nofskipped = nofskipped + 1 else - nofread = nofread + 1 if #skip_paths > 0 then for i=1,#skip_paths do if find(basepath,skip_paths[i]) then if trace_names then - logs.report("fontnames","rejecting path of %s font %s",suffix,completename) + report_names("rejecting path of %s font %s",suffix,completename) logs.push() end + nofskipped = nofskipped + 1 return end end @@ -619,15 +642,16 @@ local function analysefiles() if find(basename,skip_names[i]) then done[name] = true if trace_names then - logs.report("fontnames","rejecting name of %s font %s",suffix,completename) + report_names("rejecting name of %s font %s",suffix,completename) logs.push() end + nofskipped = nofskipped + 1 return end end end if trace_names then - logs.report("fontnames","identifying %s font %s",suffix,completename) + report_names("identifying %s font %s",suffix,completename) logs.push() end local result, message = filters[lower(suffix)](completename) @@ -635,24 +659,25 @@ local function analysefiles() logs.pop() end if result then - if not result[1] then - local ok = check_name(data,result,storedname,suffix) - if not ok then - nofskipped = nofskipped + 1 - end - else + if result[1] then for r=1,#result do local ok = check_name(data,result[r],storedname,suffix,r-1) -- subfonts start at zero - if not ok then - nofskipped = nofskipped + 1 - end + -- if not ok then + -- nofskipped = nofskipped + 1 + -- end end + else + local ok = check_name(data,result,storedname,suffix) + -- if not ok then + -- nofskipped = nofskipped + 1 + -- end end if trace_warnings and message and message ~= "" then - logs.report("fontnames","warning when identifying %s font %s: %s",suffix,completename,message) + report_names("warning when identifying %s font %s: %s",suffix,completename,message) end elseif trace_warnings then - logs.report("fontnames","error when identifying %s font %s: %s",suffix,completename,message or "unknown") + nofskipped = nofskipped + 1 + report_names("error when identifying %s font %s: %s",suffix,completename,message or "unknown") end done[name] = true end @@ -662,27 +687,32 @@ local function analysefiles() for n=1,#list do local suffix = list[n] local t = os.gettimeofday() -- use elapser - nofread, nofskipped = 0, 0 + nofread, nofskipped, nofduplicates = 0, 0, 0 suffix = lower(suffix) - logs.report("fontnames", "identifying %s font files with suffix %s",what,suffix) + report_names( "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) + report_names( "identifying %s font files with suffix %s",what,suffix) method(suffix) - totalnofread, totalnofskipped = totalnofread + nofread, totalnofskipped + nofskipped + totalnofread, totalnofskipped, totalnofduplicates = totalnofread + nofread, totalnofskipped + nofskipped, totalnofduplicates + nofduplicates 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) + report_names( "%s %s files identified, %s skipped, %s duplicates, %s hash entries added, runtime %0.3f seconds",nofread,what,nofskipped,nofduplicates,nofread-nofskipped,elapsed) end end if not trace_warnings then - logs.report("fontnames", "warnings are disabled (tracker 'fonts.warnings')") + report_names( "warnings are disabled (tracker 'fonts.warnings')") end traverse("tree", function(suffix) -- TEXTREE only resolvers.with_files(".*%." .. suffix .. "$", function(method,root,path,name) - if method == "file" then + if method == "file" or method == "tree" then local completename = root .."/" .. path .. "/" .. name - identify(completename,name,suffix,name,name) + identify(completename,name,suffix,name) + return true end + end, function(blobtype,blobpath,pattern) + report_names( "scanning %s for %s files",blobpath,suffix) + end, function(blobtype,blobpath,pattern,total,checked,done) + report_names( "%s entries found, %s %s files checked, %s okay",total,checked,suffix,done) end) end) if texconfig.kpse_init then @@ -697,7 +727,7 @@ local function analysefiles() walk_tree(names.getpaths(trace),suffix,identify) end) end - data.statistics.readfiles, data.statistics.skippedfiles = totalnofread, totalnofskipped + data.statistics.readfiles, data.statistics.skippedfiles, data.statistics.duplicatefiles = totalnofread, totalnofskipped, totalnofduplicates end local function rejectclashes() -- just to be sure, so no explicit afm will be found then @@ -709,7 +739,7 @@ local function rejectclashes() -- just to be sure, so no explicit afm will be fo local fnd, fnm = used[f], s.filename if fnd then if trace_warnings then - logs.report("fontnames", "fontname '%s' clashes, rejecting '%s' in favor of '%s'",f,fnm,fnd) + report_names( "fontname '%s' clashes, rejecting '%s' in favor of '%s'",f,fnm,fnd) end else used[f], okay[#okay+1] = fnm, s @@ -720,7 +750,7 @@ local function rejectclashes() -- just to be sure, so no explicit afm will be fo end local d = #specifications - #okay if d > 0 then - logs.report("fontnames", "%s files rejected due to clashes",d) + report_names( "%s files rejected due to clashes",d) end names.data.specifications = okay end @@ -754,13 +784,13 @@ function names.identify() end function names.is_permitted(name) - return containers.is_usable(names.cache(), name) + return containers.is_usable(names.cache, name) end function names.write_data(name,data) - containers.write(names.cache(),name,data) + containers.write(names.cache,name,data) end function names.read_data(name) - return containers.read(names.cache(),name) + return containers.read(names.cache,name) end function names.load(reload,verbose) @@ -770,7 +800,7 @@ function names.load(reload,verbose) names.identify(verbose) names.write_data(names.basename,names.data) else - logs.report("font table", "unable to access database cache") + report_names("unable to access database cache") end names.saved = true end @@ -783,7 +813,7 @@ function names.load(reload,verbose) names.saved = true end if not data then - logs.report("font table", "accessing the data table failed") + report_names("accessing the data table failed") else unpackreferences() sorthashes() @@ -842,10 +872,10 @@ local function is_reloaded() 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") + -- report_names("font database matches configuration and file hashes") return else - logs.report("fonts","font database does not match configuration and file hashes") + report_names("font database does not match configuration and file hashes") end end names.loaded = false @@ -886,7 +916,7 @@ local function foundname(name,sub) -- sub is not used currently local found = mappings[l][name] if found then if trace_names then - logs.report("fonts","resolved via direct name match: '%s'",name) + report_names("resolved via direct name match: '%s'",name) end return found end @@ -896,7 +926,7 @@ local function foundname(name,sub) -- sub is not used currently local found, fname = fuzzy(mappings[l],sorted_mappings[l],name,sub) if found then if trace_names then - logs.report("fonts","resolved via fuzzy name match: '%s' => '%s'",name,fname) + report_names("resolved via fuzzy name match: '%s' => '%s'",name,fname) end return found end @@ -906,7 +936,7 @@ local function foundname(name,sub) -- sub is not used currently local found = fallbacks[l][name] if found then if trace_names then - logs.report("fonts","resolved via direct fallback match: '%s'",name) + report_names("resolved via direct fallback match: '%s'",name) end return found end @@ -916,11 +946,14 @@ local function foundname(name,sub) -- sub is not used currently local found, fname = fuzzy(sorted_mappings[l],sorted_fallbacks[l],name,sub) if found then if trace_names then - logs.report("fonts","resolved via fuzzy fallback match: '%s' => '%s'",name,fname) + report_names("resolved via fuzzy fallback match: '%s' => '%s'",name,fname) end return found end end + if trace_names then + report_names("font with name '%s' cannot be found",name) + end end function names.resolvedspecification(askedname,sub) @@ -1144,7 +1177,7 @@ local function collect(stage,found,done,name,weight,style,width,variant,all) 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', variant '%s'", + report_names("resolving name '%s', weight '%s', style '%s', width '%s', variant '%s'", name or "?",tostring(weight),tostring(style),tostring(width),tostring(variant)) end --~ print(name,table.serialize(family)) @@ -1153,27 +1186,27 @@ local function collect(stage,found,done,name,weight,style,width,variant,all) if width and width ~= "" then if variant and variant ~= "" then if trace_names then - logs.report("fonts","resolving stage %s, name '%s', weight '%s', style '%s', width '%s', variant '%s'",stage,name,weight,style,width,variant) + report_names("resolving stage %s, name '%s', weight '%s', style '%s', width '%s', variant '%s'",stage,name,weight,style,width,variant) end s_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,family) m_collect_weight_style_width_variant(found,done,all,weight,style,width,variant,families,sorted,strictname) else if trace_names then - logs.report("fonts","resolving stage %s, name '%s', weight '%s', style '%s', width '%s'",stage,name,weight,style,width) + report_names("resolving stage %s, name '%s', weight '%s', style '%s', width '%s'",stage,name,weight,style,width) end s_collect_weight_style_width(found,done,all,weight,style,width,family) m_collect_weight_style_width(found,done,all,weight,style,width,families,sorted,strictname) end else if trace_names then - logs.report("fonts","resolving stage %s, name '%s', weight '%s', style '%s'",stage,name,weight,style) + report_names("resolving stage %s, name '%s', weight '%s', style '%s'",stage,name,weight,style) end s_collect_weight_style(found,done,all,weight,style,family) m_collect_weight_style(found,done,all,weight,style,families,sorted,strictname) end else if trace_names then - logs.report("fonts","resolving stage %s, name '%s', weight '%s'",stage,name,weight) + report_names("resolving stage %s, name '%s', weight '%s'",stage,name,weight) end s_collect_weight(found,done,all,weight,family) m_collect_weight(found,done,all,weight,families,sorted,strictname) @@ -1181,33 +1214,33 @@ local function collect(stage,found,done,name,weight,style,width,variant,all) elseif style and style ~= "" then if width and width ~= "" then if trace_names then - logs.report("fonts","resolving stage %s, name '%s', style '%s', width '%s'",stage,name,style,width) + report_names("resolving stage %s, name '%s', style '%s', width '%s'",stage,name,style,width) end s_collect_style_width(found,done,all,style,width,family) m_collect_style_width(found,done,all,style,width,families,sorted,strictname) else if trace_names then - logs.report("fonts","resolving stage %s, name '%s', style '%s'",stage,name,style) + report_names("resolving stage %s, name '%s', style '%s'",stage,name,style) end s_collect_style(found,done,all,style,family) m_collect_style(found,done,all,style,families,sorted,strictname) end elseif width and width ~= "" then if trace_names then - logs.report("fonts","resolving stage %s, name '%s', width '%s'",stage,name,width) + report_names("resolving stage %s, name '%s', width '%s'",stage,name,width) end s_collect_width(found,done,all,width,family) m_collect_width(found,done,all,width,families,sorted,strictname) else if trace_names then - logs.report("fonts","resolving stage %s, name '%s'",stage,name) + report_names("resolving stage %s, name '%s'",stage,name) end s_collect(found,done,all,family) m_collect(found,done,all,families,sorted,strictname) end end -function heuristic(name,weight,style,width,variant,all) -- todo: fallbacks +local function heuristic(name,weight,style,width,variant,all) -- todo: fallbacks local found, done = { }, { } --~ print(name,weight,style,width,variant) weight, style, width, variant = weight or "normal", style or "normal", width or "normal", variant or "normal" @@ -1238,9 +1271,9 @@ function heuristic(name,weight,style,width,variant,all) -- todo: fallbacks for i=1,nf do t[#t+1] = format("'%s'",found[i].fontname) end - logs.report("fonts","name '%s' resolved to %s instances: %s",name,nf,concat(t," ")) + report_names("name '%s' resolved to %s instances: %s",name,nf,concat(t," ")) else - logs.report("fonts","name '%s' unresolved",name) + report_names("name '%s' unresolved",name) end end if all then @@ -1385,19 +1418,29 @@ function names.lookup(pattern,name,reload) -- todo: find lookups = families[pattern] end if trace_names then - logs.report("fonts","starting with %s lookups for '%s'",#lookups,pattern) + report_names("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] + if find(value,"*") then + value = string.topattern(value) + for i=1,#lookups do + local s = lookups[i] + if find(s[key],value) then + t[#t+1] = lookups[i] + end + end + else + for i=1,#lookups do + local s = lookups[i] + if s[key] == value then + t[#t+1] = lookups[i] + end end end if trace_names then - logs.report("fonts","%s matches for key '%s' with value '%s'",#t,key,value) + report_names("%s matches for key '%s' with value '%s'",#t,key,value) end lookups = t end diff --git a/tex/context/base/font-tfm.lua b/tex/context/base/font-tfm.lua index 31ae2cae1..69cd2707e 100644 --- a/tex/context/base/font-tfm.lua +++ b/tex/context/base/font-tfm.lua @@ -14,6 +14,8 @@ local concat, sortedkeys, utfbyte, serialize = table.concat, table.sortedkeys, u local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end) local trace_scaling = false trackers.register("fonts.scaling" , function(v) trace_scaling = v end) +local report_define = logs.new("define fonts") + -- tfmdata has also fast access to indices and unicodes -- to be checked: otf -> tfm -> tfmscaled -- @@ -52,11 +54,13 @@ tfm.fontname_mode = "fullpath" tfm.enhance = tfm.enhance or function() end +fonts.formats.tfm = "type1" -- we need to have at least a value here + function tfm.read_from_tfm(specification) local fname, tfmdata = specification.filename or "", nil if fname ~= "" then if trace_defining then - logs.report("define font","loading tfm file %s at size %s",fname,specification.size) + report_define("loading tfm file %s at size %s",fname,specification.size) end tfmdata = font.read_tfm(fname,specification.size) -- not cached, fast enough if tfmdata then @@ -79,7 +83,7 @@ function tfm.read_from_tfm(specification) tfm.enhance(tfmdata,specification) end elseif trace_defining then - logs.report("define font","loading tfm with name %s fails",specification.name) + report_define("loading tfm with name %s fails",specification.name) end return tfmdata end @@ -247,12 +251,12 @@ function tfm.do_scale(tfmtable, scaledpoints, relativeid) local nodemode = tfmtable.mode == "node" local hasquality = tfmtable.auto_expand or tfmtable.auto_protrude local hasitalic = tfmtable.has_italic + local descriptions = tfmtable.descriptions or { } -- t.parameters = { } t.characters = { } t.MathConstants = { } -- fast access - local descriptions = tfmtable.descriptions or { } t.unicodes = tfmtable.unicodes t.indices = tfmtable.indices t.marks = tfmtable.marks @@ -355,7 +359,7 @@ t.colorscheme = tfmtable.colorscheme end end -- if trace_scaling then - -- logs.report("define font","t=%s, u=%s, i=%s, n=%s c=%s",k,chr.tounicode or k,description.index,description.name or '-',description.class or '-') + -- report_define("t=%s, u=%s, i=%s, n=%s c=%s",k,chr.tounicode or k,description.index,description.name or '-',description.class or '-') -- end if tounicode then local tu = tounicode[index] -- nb: index! @@ -391,6 +395,9 @@ t.colorscheme = tfmtable.colorscheme local vn = v.next if vn then chr.next = vn + --~ if v.vert_variants or v.horiz_variants then + --~ report_define("glyph 0x%05X has combination of next, vert_variants and horiz_variants",index) + --~ end else local vv = v.vert_variants if vv then @@ -560,11 +567,11 @@ t.colorscheme = tfmtable.colorscheme -- can have multiple subfonts if hasmath then if trace_defining then - 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") + report_define("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: name '%s', fullname: '%s', filename: '%s'",t.name or "noname",t.fullname or "nofullname",t.filename or "nofilename") + report_define("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 @@ -573,8 +580,8 @@ t.colorscheme = tfmtable.colorscheme t.psname = t.fontname or (t.fullname and fonts.names.cleanname(t.fullname)) end if trace_defining then - 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") + report_define("used for accesing subfont: '%s'",t.psname or "nopsname") + report_define("used for subsetting: '%s'",t.fontname or "nofontname") end --~ print(t.fontname,table.serialize(t.MathConstants)) return t, delta @@ -713,18 +720,18 @@ function tfm.checked_filename(metadata,whatever) if askedfilename ~= "" then foundfilename = resolvers.findbinfile(askedfilename,"") or "" if foundfilename == "" then - logs.report("fonts","source file '%s' is not found",askedfilename) + report_define("source file '%s' is not found",askedfilename) foundfilename = resolvers.findbinfile(file.basename(askedfilename),"") or "" if foundfilename ~= "" then - logs.report("fonts","using source file '%s' (cache mismatch)",foundfilename) + report_define("using source file '%s' (cache mismatch)",foundfilename) end end elseif whatever then - logs.report("fonts","no source file for '%s'",whatever) + report_define("no source file for '%s'",whatever) foundfilename = "" end metadata.foundfilename = foundfilename - -- logs.report("fonts","using source file '%s'",foundfilename) + -- report_define("using source file '%s'",foundfilename) end return foundfilename end diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua index 508240a3b..c933d6a5f 100644 --- a/tex/context/base/grph-inc.lua +++ b/tex/context/base/grph-inc.lua @@ -50,6 +50,8 @@ local trace_programs = false trackers.register("figures.programs", function local trace_conversion = false trackers.register("figures.conversion", function(v) trace_conversion = v end) local trace_inclusion = false trackers.register("figures.inclusion", function(v) trace_inclusion = v end) +local report_graphics = logs.new("graphics") + --- some extra img functions --- local imgkeys = img.keys() @@ -333,7 +335,7 @@ local function register(askedname,specification) end local converter = (newformat ~= format) and figures.converters[format] if trace_conversion then - logs.report("figures","checking conversion of '%s': old format '%s', new format '%s', conversion '%s'", + report_graphics("checking conversion of '%s': old format '%s', new format '%s', conversion '%s'", askedname,format,newformat,conversion or "default") end if converter then @@ -375,12 +377,12 @@ local function register(askedname,specification) local newtime = lfs.attributes(newname,'modification') or 0 if oldtime > newtime then if trace_conversion then - logs.report("figures","converting '%s' from '%s' to '%s'",askedname,format,newformat) + report_graphics("converting '%s' from '%s' to '%s'",askedname,format,newformat) end converter(oldname,newname) else if trace_conversion then - logs.report("figures","no need to convert '%s' from '%s' to '%s'",askedname,format,newformat) + report_graphics("no need to convert '%s' from '%s' to '%s'",askedname,format,newformat) end end if io.exists(newname) then @@ -430,10 +432,17 @@ local function locate(request) -- name, format, cache end -- protocol check local hashed = url.hashed(askedname) - if hashed and hashed.scheme ~= "file" then - local foundname = resolvers.findbinfile(askedname) - if foundname then - askedname = foundname + if hashed then + if hashed.scheme == "file" then + local path = hashed.path + if path and path ~= "" then + askedname = path + end + else + local foundname = resolvers.findbinfile(askedname) + if foundname then + askedname = foundname + end end end -- we could use the hashed data instead @@ -745,11 +754,11 @@ function figures.checkers.generic(data) figure, data = f or figure, d or data figures.loaded[hash] = figure if trace_conversion then - logs.report("figures","new graphic, hash: %s",hash) + report_graphics("new graphic, hash: %s",hash) end else if trace_conversion then - logs.report("figures","existing graphic, hash: %s",hash) + report_graphics("existing graphic, hash: %s",hash) end end if figure then @@ -820,7 +829,7 @@ function figures.checkers.mov(data) dr.width, dr.height = width, height du.width, du.height, du.foundname = width, height, foundname if trace_inclusion then - logs.report("figures","including movie '%s': width %s, height %s",foundname,width,height) + report_graphics("including movie '%s': width %s, height %s",foundname,width,height) end -- we need to push the node.write in between ... we could make a shared helper for this context.startfoundexternalfigure(width .. "sp",height .. "sp") @@ -903,7 +912,7 @@ end local function runprogram(...) local command = format(...) if trace_conversion or trace_programs then - logs.report("figures","running %s",command) + report_graphics("running %s",command) end os.spawn(command) end @@ -977,7 +986,7 @@ figures.programs.convert = { function gifconverter.pdf(oldname,newname) local convert = figures.programs.convert runprogram ( - "convert %s %s", + "%s %s %s %s", convert.command, makeoptions(convert.options), oldname, newname ) end diff --git a/tex/context/base/grph-u3d.lua b/tex/context/base/grph-u3d.lua index f3bf17631..04ddd1f4e 100644 --- a/tex/context/base/grph-u3d.lua +++ b/tex/context/base/grph-u3d.lua @@ -10,6 +10,8 @@ if not modules then modules = { } end modules ['grph-u3d'] = { local trace_inclusion = false trackers.register("figures.inclusion", function(v) trace_inclusion = v end) +local report_graphics = logs.new("graphics") + local pdfannotation = nodes.pdfannotation local todimen = string.todimen @@ -19,11 +21,11 @@ function figures.checkers.u3d(data) local dr, du, ds = data.request, data.used, data.status local width = todimen(dr.width or figures.defaultwidth) local height = todimen(dr.height or figures.defaultheight) - local foundname = du.fullname + local foundname = du.report_graphics( dr.width, dr.height = width, height du.width, du.height, du.foundname = width, height, foundname if trace_inclusion then - logs.report("figures","including u3d '%s': width %s, height %s",foundname,width,height) + report_graphics("including u3d '%s': width %s, height %s",foundname,width,height) end context.startfoundexternalfigure(width .. "sp",height .. "sp") context(function() diff --git a/tex/context/base/l-aux.lua b/tex/context/base/l-aux.lua index 97063e3bc..aeea79173 100644 --- a/tex/context/base/l-aux.lua +++ b/tex/context/base/l-aux.lua @@ -70,11 +70,7 @@ end function aux.settings_to_hash(str,existing) if str and str ~= "" then hash = existing or { } - if moretolerant then - lpegmatch(pattern_b_s,str) - else - lpegmatch(pattern_a_s,str) - end + lpegmatch(pattern_a_s,str) return hash else return { } diff --git a/tex/context/base/l-boolean.lua b/tex/context/base/l-boolean.lua index be7ec7d57..cf8dc0ac8 100644 --- a/tex/context/base/l-boolean.lua +++ b/tex/context/base/l-boolean.lua @@ -35,7 +35,7 @@ function toboolean(str,tolerant) end end -function string.is_boolean(str) +function string.is_boolean(str,default) if type(str) == "string" then if str == "true" or str == "yes" or str == "on" or str == "t" then return true @@ -43,7 +43,7 @@ function string.is_boolean(str) return false end end - return nil + return default end function boolean.alwaystrue() diff --git a/tex/context/base/l-dir.lua b/tex/context/base/l-dir.lua index 2643f538b..64ebbeafc 100644 --- a/tex/context/base/l-dir.lua +++ b/tex/context/base/l-dir.lua @@ -307,7 +307,7 @@ else local str, pth, t = "", "", { ... } for i=1,#t do local s = t[i] - if s ~= "" then + if s and s ~= "" then -- we catch nil and false if str ~= "" then str = str .. "/" .. s else diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua index 2bfc07090..b528d9a7d 100644 --- a/tex/context/base/l-file.lua +++ b/tex/context/base/l-file.lua @@ -10,45 +10,88 @@ if not modules then modules = { } end modules ['l-file'] = { file = file or { } -local concat = table.concat +local insert, concat = table.insert, table.concat local find, gmatch, match, gsub, sub, char = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char local lpegmatch = lpeg.match +local getcurrentdir = lfs.currentdir -function file.removesuffix(filename) - return (gsub(filename,"%.[%a%d]+$","")) +local function dirname(name,default) + return match(name,"^(.+)[/\\].-$") or (default or "") end -function file.addsuffix(filename, suffix) - if not suffix or suffix == "" then - return filename - elseif not find(filename,"%.[%a%d]+$") then - return filename .. "." .. suffix - else - return filename - end +local function basename(name) + return match(name,"^.+[/\\](.-)$") or name end -function file.replacesuffix(filename, suffix) - return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix +local function nameonly(name) + return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$","")) end -function file.dirname(name,default) - return match(name,"^(.+)[/\\].-$") or (default or "") +local function extname(name,default) + return match(name,"^.+%.([^/\\]-)$") or default or "" end -function file.basename(name) - return match(name,"^.+[/\\](.-)$") or name +local function splitname(name) + local n, s = match(name,"^(.+)%.([^/\\]-)$") + return n or name, s or "" end -function file.nameonly(name) - return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$","")) +file.basename = basename +file.dirname = dirname +file.nameonly = nameonly +file.extname = extname +file.suffix = extname + +function file.removesuffix(filename) + return (gsub(filename,"%.[%a%d]+$","")) end -function file.extname(name,default) - return match(name,"^.+%.([^/\\]-)$") or default or "" +function file.addsuffix(filename, suffix, criterium) + if not suffix or suffix == "" then + return filename + elseif criterium == true then + return filename .. "." .. suffix + elseif not criterium then + local n, s = splitname(filename) + if not s or s == "" then + return filename .. "." .. suffix + else + return filename + end + else + local n, s = splitname(filename) + if s and s ~= "" then + local t = type(criterium) + if t == "table" then + -- keep if in criterium + for i=1,#criterium do + if s == criterium[i] then + return filename + end + end + elseif t == "string" then + -- keep if criterium + if s == criterium then + return filename + end + end + end + return n .. "." .. suffix + end end -file.suffix = file.extname +--~ print("1 " .. file.addsuffix("name","new") .. " -> name.new") +--~ print("2 " .. file.addsuffix("name.old","new") .. " -> name.old") +--~ print("3 " .. file.addsuffix("name.old","new",true) .. " -> name.old.new") +--~ print("4 " .. file.addsuffix("name.old","new","new") .. " -> name.new") +--~ print("5 " .. file.addsuffix("name.old","new","old") .. " -> name.old") +--~ print("6 " .. file.addsuffix("name.old","new","foo") .. " -> name.new") +--~ print("7 " .. file.addsuffix("name.old","new",{"foo","bar"}) .. " -> name.new") +--~ print("8 " .. file.addsuffix("name.old","new",{"old","bar"}) .. " -> name.old") + +function file.replacesuffix(filename, suffix) + return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix +end --~ function file.join(...) --~ local pth = concat({...},"/") @@ -101,7 +144,7 @@ end --~ print(file.join("//nas-1","/y")) function file.iswritable(name) - local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,".")) + local a = lfs.attributes(name) or lfs.attributes(dirname(name,".")) return a and sub(a.permissions,2,2) == "w" end @@ -140,31 +183,94 @@ end -- we can hash them weakly -function file.collapse_path(str) +--~ function file.old_collapse_path(str) -- fails on b.c/.. +--~ str = gsub(str,"\\","/") +--~ if find(str,"/") then +--~ str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified +--~ str = gsub(str,"/%./","/") +--~ local n, m = 1, 1 +--~ while n > 0 or m > 0 do +--~ str, n = gsub(str,"[^/%.]+/%.%.$","") +--~ str, m = gsub(str,"[^/%.]+/%.%./","") +--~ end +--~ str = gsub(str,"([^/])/$","%1") +--~ -- str = gsub(str,"^%./","") -- ./xx in qualified +--~ str = gsub(str,"/%.$","") +--~ end +--~ if str == "" then str = "." end +--~ return str +--~ end +--~ +--~ The previous one fails on "a.b/c" so Taco came up with a split based +--~ variant. After some skyping we got it sort of compatible with the old +--~ one. After that the anchoring to currentdir was added in a better way. +--~ Of course there are some optimizations too. Finally we had to deal with +--~ windows drive prefixes and thinsg like sys://. + +function file.collapse_path(str,anchor) + if anchor and not find(str,"^/") and not find(str,"^%a:") then + str = getcurrentdir() .. "/" .. str + end + if str == "" or str =="." then + return "." + elseif find(str,"^%.%.") then + str = gsub(str,"\\","/") + return str + elseif not find(str,"%.") then + str = gsub(str,"\\","/") + return str + end str = gsub(str,"\\","/") - if find(str,"/") then - str = gsub(str,"^%./",(gsub(lfs.currentdir(),"\\","/")) .. "/") -- ./xx in qualified - str = gsub(str,"/%./","/") - local n, m = 1, 1 - while n > 0 or m > 0 do - str, n = gsub(str,"[^/%.]+/%.%.$","") - str, m = gsub(str,"[^/%.]+/%.%./","") + local starter, rest = match(str,"^(%a+:/*)(.-)$") + if starter then + str = rest + end + local oldelements = checkedsplit(str,"/") + local newelements = { } + local i = #oldelements + while i > 0 do + local element = oldelements[i] + if element == '.' then + -- do nothing + elseif element == '..' then + local n = i -1 + while n > 0 do + local element = oldelements[n] + if element ~= '..' and element ~= '.' then + oldelements[n] = '.' + break + else + n = n - 1 + end + end + if n < 1 then + insert(newelements,1,'..') + end + elseif element ~= "" then + insert(newelements,1,element) end - str = gsub(str,"([^/])/$","%1") - -- str = gsub(str,"^%./","") -- ./xx in qualified - str = gsub(str,"/%.$","") + i = i - 1 + end + if #newelements == 0 then + return starter or "." + elseif starter then + return starter .. concat(newelements, '/') + elseif find(str,"^/") then + return "/" .. concat(newelements,'/') + else + return concat(newelements, '/') end - if str == "" then str = "." end - return str end ---~ print(file.collapse_path("/a")) ---~ print(file.collapse_path("a/./b/..")) ---~ print(file.collapse_path("a/aa/../b/bb")) ---~ print(file.collapse_path("a/../..")) ---~ print(file.collapse_path("a/.././././b/..")) ---~ print(file.collapse_path("a/./././b/..")) ---~ print(file.collapse_path("a/b/c/../..")) +--~ local function test(str) +--~ print(string.format("%-20s %-15s %-15s",str,file.collapse_path(str),file.collapse_path(str,true))) +--~ end +--~ test("a/b.c/d") test("b.c/d") test("b.c/..") +--~ test("/") test("c:/..") test("sys://..") +--~ test("") test("./") test(".") test("..") test("./..") test("../..") +--~ test("a") test("./a") test("/a") test("a/../..") +--~ test("a/./b/..") test("a/aa/../b/bb") test("a/.././././b/..") test("a/./././b/..") +--~ test("a/b/c/../..") test("./a/b/c/../..") test("a/b/c/../..") function file.robustname(str) return (gsub(str,"[^%a%d%/%-%.\\]+","-")) diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua index b107a8e64..05bbebab9 100644 --- a/tex/context/base/l-lpeg.lua +++ b/tex/context/base/l-lpeg.lua @@ -48,6 +48,11 @@ patterns.whitespace = patterns.eol + patterns.spacer patterns.nonwhitespace = 1 - patterns.whitespace patterns.utf8 = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four patterns.utfbom = P('\000\000\254\255') + P('\255\254\000\000') + P('\255\254') + P('\254\255') + P('\239\187\191') +patterns.validutf8 = patterns.utf8^0 * P(-1) * Cc(true) + Cc(false) + +patterns.undouble = P('"')/"" * (1-P('"'))^0 * P('"')/"" +patterns.unsingle = P("'")/"" * (1-P("'"))^0 * P("'")/"" +patterns.unspacer = ((patterns.spacer^1)/"")^0 function lpeg.anywhere(pattern) --slightly adapted from website return P { P(pattern) + 1 * V(1) } -- why so complex? @@ -163,3 +168,61 @@ local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 6 local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end patterns.utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4 + +local cache = { } + +function lpeg.stripper(str) + local s = cache[str] + if not s then + s = Cs(((S(str)^1)/"" + 1)^0) + cache[str] = s + end + return s +end + +function lpeg.replacer(t) + if #t > 0 then + local p + for i=1,#t do + local ti= t[i] + local pp = P(ti[1]) / ti[2] + p = (p and p + pp ) or pp + end + return Cs((p + 1)^0) + end +end + +--~ print(utf.check("")) +--~ print(utf.check("abcde")) +--~ print(utf.check("abcde\255\123")) + +local splitters_f, splitters_s = { }, { } + +function lpeg.firstofsplit(separator) -- always return value + local splitter = splitters_f[separator] + if not splitter then + separator = P(separator) + splitter = C((1 - separator)^0) + splitters_f[separator] = splitter + end + return splitter +end + +function lpeg.secondofsplit(separator) -- nil if not split + local splitter = splitters_s[separator] + if not splitter then + separator = P(separator) + splitter = (1 - separator)^0 * separator * C(P(1)^0) + splitters_s[separator] = splitter + end + return splitter +end + +--~ print(1,match(lpeg.firstofsplit(":"),"bc:de")) +--~ print(2,match(lpeg.firstofsplit(":"),":de")) -- empty +--~ print(3,match(lpeg.firstofsplit(":"),"bc")) +--~ print(4,match(lpeg.secondofsplit(":"),"bc:de")) +--~ print(5,match(lpeg.secondofsplit(":"),"bc:")) -- empty +--~ print(6,match(lpeg.secondofsplit(":",""),"bc")) +--~ print(7,match(lpeg.secondofsplit(":"),"bc")) +--~ print(9,match(lpeg.secondofsplit(":","123"),"bc")) diff --git a/tex/context/base/l-os.lua b/tex/context/base/l-os.lua index fba2cd317..0d06c4673 100644 --- a/tex/context/base/l-os.lua +++ b/tex/context/base/l-os.lua @@ -8,24 +8,95 @@ if not modules then modules = { } end modules ['l-os'] = { -- maybe build io.flush in os.execute -local find, format, gsub = string.find, string.format, string.gsub +local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper local random, ceil = math.random, math.ceil +local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber +local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber -local execute, spawn, exec, ioflush = os.execute, os.spawn or os.execute, os.exec or os.execute, io.flush +-- The following code permits traversing the environment table, at least +-- in luatex. Internally all environment names are uppercase. + +if not os.__getenv__ then + + os.__getenv__ = os.getenv + os.__setenv__ = os.setenv + + if os.env then + + local osgetenv = os.getenv + local ossetenv = os.setenv + local osenv = os.env local _ = osenv.PATH -- initialize the table + + function os.setenv(k,v) + if v == nil then + v = "" + end + local K = upper(k) + osenv[K] = v + ossetenv(K,v) + end + + function os.getenv(k) + local K = upper(k) + local v = osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k) + if v == "" then + return nil + else + return v + end + end + + else + + local ossetenv = os.setenv + local osgetenv = os.getenv + local osenv = { } + + function os.setenv(k,v) + if v == nil then + v = "" + end + local K = upper(k) + osenv[K] = v + end + + function os.getenv(k) + local K = upper(k) + local v = osenv[K] or osgetenv(K) or osgetenv(k) + if v == "" then + return nil + else + return v + end + end + + local function __index(t,k) + return os.getenv(k) + end + local function __newindex(t,k,v) + os.setenv(k,v) + end + + os.env = { } + + setmetatable(os.env, { __index = __index, __newindex = __newindex } ) + + end + +end + +-- end of environment hack + +local execute, spawn, exec, iopopen, ioflush = os.execute, os.spawn or os.execute, os.exec or os.execute, io.popen, io.flush function os.execute(...) ioflush() return execute(...) end function os.spawn (...) ioflush() return spawn (...) end function os.exec (...) ioflush() return exec (...) end +function io.popen (...) ioflush() return iopopen(...) end function os.resultof(command) - ioflush() -- else messed up logging local handle = io.popen(command,"r") - if not handle then - -- print("unknown command '".. command .. "' in os.resultof") - return "" - else - return handle:read("*all") or "" - end + return handle and handle:read("*all") or "" end --~ os.type : windows | unix (new, we already guessed os.platform) @@ -102,24 +173,6 @@ end setmetatable(os,osmt) -if not os.setenv then - - -- we still store them but they won't be seen in - -- child processes although we might pass them some day - -- using command concatination - - local env, getenv = { }, os.getenv - - function os.setenv(k,v) - env[k] = v - end - - function os.getenv(k) - return env[k] or getenv(k) - end - -end - -- we can use HOSTTYPE on some platforms local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or "" @@ -240,7 +293,7 @@ elseif name == "kfreebsd" then -- we sometims have HOSTTYPE set so let's check that first local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" if find(architecture,"x86_64") then - platform = "kfreebsd-64" + platform = "kfreebsd-amd64" else platform = "kfreebsd-i386" end diff --git a/tex/context/base/l-pdfview.lua b/tex/context/base/l-pdfview.lua index 627477ee8..76923e1fc 100644 --- a/tex/context/base/l-pdfview.lua +++ b/tex/context/base/l-pdfview.lua @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['l-pdfview'] = { license = "see context related readme files" } -local format, getenv = string.format, os.getenv +local format, concat = string.format, table.concat pdfview = pdfview or { } @@ -32,15 +32,15 @@ else end pdfview.METHOD = "MTX_PDFVIEW_METHOD" -pdfview.method = getenv(pdfview.METHOD) or 'default' +pdfview.method = resolvers.getenv(pdfview.METHOD) or 'default' pdfview.method = (opencalls[pdfview.method] and pdfview.method) or 'default' function pdfview.methods() - return table.concat(table.sortedkeys(opencalls), " ") + return concat(table.sortedkeys(opencalls), " ") end function pdfview.status() - return format("pdfview methods: %s, current method: %s, MTX_PDFVIEW_METHOD=%s",pdfview.methods(),pdfview.method,getenv(pdfview.METHOD) or "Callbacks are the real asset of
We cannot load anything yet. However what we will do us reserve a fewtables. These can be used for runtime user data or third party modules and will not be @@ -17,9 +22,11 @@ cluttered by macro package code.
userdata = userdata or { } -- might be used thirddata = thirddata or { } -- might be used moduledata = moduledata or { } -- might be used -document = document or { } +documentdata = documentdata or { } -- might be used parametersets = parametersets or { } -- experimental +document = document or { } + --[[ldx--These can be used/set by the caller program;
We've now arrived at an interesting part: accessing the tree using a subset
of
The parser used here is inspired by the variant discussed in the lua book, but handles comment and processing instructions, has a different structure, provides @@ -150,7 +152,7 @@ local dcache, hcache, acache = { }, { }, { } local mt = { } -function initialize_mt(root) +local function initialize_mt(root) mt = { __index = root } -- will be redefined later end @@ -254,7 +256,7 @@ local reported_attribute_errors = { } local function attribute_value_error(str) if not reported_attribute_errors[str] then - logs.report("xml","invalid attribute value: %q",str) + report_xml("invalid attribute value: %q",str) reported_attribute_errors[str] = true at._error_ = str end @@ -262,7 +264,7 @@ local function attribute_value_error(str) end local function attribute_specification_error(str) if not reported_attribute_errors[str] then - logs.report("xml","invalid attribute specification: %q",str) + report_xml("invalid attribute specification: %q",str) reported_attribute_errors[str] = true at._error_ = str end @@ -325,18 +327,18 @@ local function handle_hex_entity(str) h = unify_predefined and predefined_unified[n] if h then if trace_entities then - logs.report("xml","utfize, converting hex entity %s; into %s",str,h) + report_xml("utfize, converting hex entity %s; into %s",str,h) end elseif utfize then h = (n and utfchar(n)) or xml.unknown_hex_entity_format(str) or "" if not n then - logs.report("xml","utfize, ignoring hex entity %s;",str) + report_xml("utfize, ignoring hex entity %s;",str) elseif trace_entities then - logs.report("xml","utfize, converting hex entity %s; into %s",str,h) + report_xml("utfize, converting hex entity %s; into %s",str,h) end else if trace_entities then - logs.report("xml","found entity %s;",str) + report_xml("found entity %s;",str) end h = "" .. str .. ";" end @@ -352,18 +354,18 @@ local function handle_dec_entity(str) d = unify_predefined and predefined_unified[n] if d then if trace_entities then - logs.report("xml","utfize, converting dec entity %s; into %s",str,d) + report_xml("utfize, converting dec entity %s; into %s",str,d) end elseif utfize then d = (n and utfchar(n)) or xml.unknown_dec_entity_format(str) or "" if not n then - logs.report("xml","utfize, ignoring dec entity %s;",str) + report_xml("utfize, ignoring dec entity %s;",str) elseif trace_entities then - logs.report("xml","utfize, converting dec entity %s; into %s",str,h) + report_xml("utfize, converting dec entity %s; into %s",str,h) end else if trace_entities then - logs.report("xml","found entity %s;",str) + report_xml("found entity %s;",str) end d = "" .. str .. ";" end @@ -388,7 +390,7 @@ local function handle_any_entity(str) end if a then if trace_entities then - logs.report("xml","resolved entity &%s; -> %s (internal)",str,a) + report_xml("resolved entity &%s; -> %s (internal)",str,a) end a = lpegmatch(parsedentity,a) or a else @@ -397,11 +399,11 @@ local function handle_any_entity(str) end if a then if trace_entities then - logs.report("xml","resolved entity &%s; -> %s (external)",str,a) + report_xml("resolved entity &%s; -> %s (external)",str,a) end else if trace_entities then - logs.report("xml","keeping entity &%s;",str) + report_xml("keeping entity &%s;",str) end if str == "" then a = "&error;" @@ -413,7 +415,7 @@ local function handle_any_entity(str) acache[str] = a elseif trace_entities then if not acache[str] then - logs.report("xml","converting entity &%s; into %s",str,a) + report_xml("converting entity &%s; into %s",str,a) acache[str] = a end end @@ -422,7 +424,7 @@ local function handle_any_entity(str) local a = acache[str] if not a then if trace_entities then - logs.report("xml","found entity &%s;",str) + report_xml("found entity &%s;",str) end a = resolve_predefined and predefined_simplified[str] if a then @@ -441,7 +443,7 @@ local function handle_any_entity(str) end local function handle_end_entity(chr) - logs.report("xml","error in entity, %q found instead of ';'",chr) + report_xml("error in entity, %q found instead of ';'",chr) end local space = S(' \r\n\t') @@ -576,7 +578,7 @@ local function xmlconvert(data, settings) resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities unify_predefined = settings.unify_predefined_entities -- & -> & cleanup = settings.text_cleanup - stack, top, at, xmlns, errorstr, result, entities = { }, { }, { }, { }, nil, nil, settings.entities or { } + stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { } acache, hcache, dcache = { }, { }, { } -- not stored reported_attribute_errors = { } if settings.parent_root then @@ -604,6 +606,7 @@ local function xmlconvert(data, settings) else errorstr = "invalid xml file - no text at all" end + local result if errorstr and errorstr ~= "" then result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={ }, er = true } } } setmetatable(stack, mt) @@ -784,7 +787,7 @@ local function verbose_element(e,handlers) ats[#ats+1] = format('%s=%q',k,v) end end - if ern and trace_remap and ern ~= ens then + if ern and trace_entities and ern ~= ens then ens = ern end if ens ~= "" then @@ -915,7 +918,7 @@ local function newhandlers(settings) if settings then for k,v in next, settings do if type(v) == "table" then - tk = t[k] if not tk then tk = { } t[k] = tk end + local tk = t[k] if not tk then tk = { } t[k] = tk end for kk,vv in next, v do tk[kk] = vv end @@ -1026,7 +1029,7 @@ local function xmltext(root) -- inline return (root and xmltostring(root)) or "" end -function initialize_mt(root) +initialize_mt = function(root) -- redefinition mt = { __tostring = xmltext, __index = root } end diff --git a/tex/context/base/lxml-tex.lua b/tex/context/base/lxml-tex.lua index aaa90217f..5b116fbf4 100644 --- a/tex/context/base/lxml-tex.lua +++ b/tex/context/base/lxml-tex.lua @@ -15,7 +15,7 @@ local type, next, tonumber, tostring = type, next, tonumber, tostring local lpegmatch = lpeg.match local P, S, C, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc -if not tex and not tex.sprint then +if not tex and not tex.sprint then -- no longer needed tex = { sprint = function(catcodes,...) texio.write(table.concat{...}) end, print = function(catcodes,...) texio.write(table.concat{...}) end, @@ -43,6 +43,8 @@ local trace_loading = false trackers.register("lxml.loading", function(v) tra local trace_access = false trackers.register("lxml.access", function(v) trace_access = v end) local trace_comments = false trackers.register("lxml.comments", function(v) trace_comments = v end) +local report_lxml = logs.new("lxml") + lxml = lxml or { } lxml.loaded = lxml.loaded or { } @@ -211,20 +213,20 @@ local function get_id(id, qualified) return root end elseif trace_access then - logs.report("lxml","'%s' has no index entry '%s'",d,i) + report_lxml("'%s' has no index entry '%s'",d,i) end elseif trace_access then - logs.report("lxml","'%s' has no index",d) + report_lxml("'%s' has no index",d) end elseif trace_access then - logs.report("lxml","'%s' is not loaded",d) + report_lxml("'%s' is not loaded",d) end elseif trace_access then - logs.report("lxml","'%s' is not loaded",i) + report_lxml("'%s' is not loaded",i) end end elseif trace_access then - logs.report("lxml","invalid id (nil)") + report_lxml("invalid id (nil)") end end @@ -270,7 +272,7 @@ local function addindex(name,check_sum,force) root.index = index root.maxindex = maxindex if trace_access then - logs.report("lxml","%s indexed, %s nodes",tostring(name),maxindex) + report_lxml("%s indexed, %s nodes",tostring(name),maxindex) end end end @@ -444,7 +446,7 @@ end local function tex_comment(e,handlers) if trace_comments then - logs.report("lxml","comment: %s",e.dt[1]) + report_lxml("comment: %s",e.dt[1]) end end @@ -470,7 +472,7 @@ local function tex_element(e,handlers) end texsprint(ctxcatcodes,"\\xmlw{",command,"}{",rootname,"::",ix,"}") else - logs.report("lxml", "fatal error: no index for '%s'",command) + report_lxml( "fatal error: no index for '%s'",command) texsprint(ctxcatcodes,"\\xmlw{",command,"}{",ix or 0,"}") end elseif tc == "function" then @@ -522,7 +524,7 @@ local function ctx_text(e) end local function tex_handle(...) --- logs.report("lxml", "error while flushing: %s", concat { ... }) +-- report_lxml( "error while flushing: %s", concat { ... }) texsprint(...) -- notcatcodes is active anyway end @@ -762,19 +764,19 @@ function lxml.setsetup(id,pattern,setup) local ix = e.ix or 0 if setup == "-" then e.command = false - logs.report("lxml","lpath matched (a) %5i: %s = %s -> skipped",c,ix,setup) + report_lxml("lpath matched (a) %5i: %s = %s -> skipped",c,ix,setup) elseif setup == "+" then e.command = true - logs.report("lxml","lpath matched (b) %5i: %s = %s -> text",c,ix,setup) + report_lxml("lpath matched (b) %5i: %s = %s -> text",c,ix,setup) else local tg = e.tg if tg then -- to be sure e.command = tg local ns = e.rn or e.ns if ns == "" then - logs.report("lxml","lpath matched (c) %5i: %s = %s -> %s",c,ix,tg,tg) + report_lxml("lpath matched (c) %5i: %s = %s -> %s",c,ix,tg,tg) else - logs.report("lxml","lpath matched (d) %5i: %s = %s:%s -> %s",c,ix,ns,tg,tg) + report_lxml("lpath matched (d) %5i: %s = %s:%s -> %s",c,ix,ns,tg,tg) end end end @@ -792,7 +794,7 @@ function lxml.setsetup(id,pattern,setup) end end elseif trace_setups then - logs.report("lxml","no lpath matches for %s",pattern) + report_lxml("no lpath matches for %s",pattern) end else local a, b = match(setup,"^(.+:)([%*%-])$") @@ -806,23 +808,23 @@ function lxml.setsetup(id,pattern,setup) if b == "-" then e.command = false if ns == "" then - logs.report("lxml","lpath matched (e) %5i: %s = %s -> skipped",c,ix,tg) + report_lxml("lpath matched (e) %5i: %s = %s -> skipped",c,ix,tg) else - logs.report("lxml","lpath matched (f) %5i: %s = %s:%s -> skipped",c,ix,ns,tg) + report_lxml("lpath matched (f) %5i: %s = %s:%s -> skipped",c,ix,ns,tg) end elseif b == "+" then e.command = true if ns == "" then - logs.report("lxml","lpath matched (g) %5i: %s = %s -> text",c,ix,tg) + report_lxml("lpath matched (g) %5i: %s = %s -> text",c,ix,tg) else - logs.report("lxml","lpath matched (h) %5i: %s = %s:%s -> text",c,ix,ns,tg) + report_lxml("lpath matched (h) %5i: %s = %s:%s -> text",c,ix,ns,tg) end else e.command = a .. tg if ns == "" then - logs.report("lxml","lpath matched (i) %5i: %s = %s -> %s",c,ix,tg,e.command) + report_lxml("lpath matched (i) %5i: %s = %s -> %s",c,ix,tg,e.command) else - logs.report("lxml","lpath matched (j) %5i: %s = %s:%s -> %s",c,ix,ns,tg,e.command) + report_lxml("lpath matched (j) %5i: %s = %s:%s -> %s",c,ix,ns,tg,e.command) end end end @@ -839,7 +841,7 @@ function lxml.setsetup(id,pattern,setup) end end elseif trace_setups then - logs.report("lxml","no lpath matches for %s",pattern) + report_lxml("no lpath matches for %s",pattern) end else local collected = lxmlparseapply(id,pattern) @@ -850,9 +852,9 @@ function lxml.setsetup(id,pattern,setup) e.command = setup local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0 if ns == "" then - logs.report("lxml","lpath matched (k) %5i: %s = %s -> %s",c,ix,tg,setup) + report_lxml("lpath matched (k) %5i: %s = %s -> %s",c,ix,tg,setup) else - logs.report("lxml","lpath matched (l) %5i: %s = %s:%s -> %s",c,ix,ns,tg,setup) + report_lxml("lpath matched (l) %5i: %s = %s:%s -> %s",c,ix,ns,tg,setup) end end else @@ -861,7 +863,7 @@ function lxml.setsetup(id,pattern,setup) end end elseif trace_setups then - logs.report("lxml","no lpath matches for %s",pattern) + report_lxml("no lpath matches for %s",pattern) end end end @@ -932,9 +934,10 @@ local function index(collected,n) end end -local function command(collected,cmd) - if collected then - for c=1,#collected do +local function command(collected,cmd,otherwise) + local n = collected and #collected + if n and n > 0 then + for c=1,n do local e = collected[c] local ix = e.ix if not ix then @@ -943,6 +946,8 @@ local function command(collected,cmd) end texsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",e.name,"::",ix,"}") end + elseif otherwise then + texsprint(ctxcatcodes,"\\xmlw{",otherwise,"}{#1}") end end diff --git a/tex/context/base/m-barcodes.mkiv b/tex/context/base/m-barcodes.mkiv index b0eae1485..b86149cb9 100644 --- a/tex/context/base/m-barcodes.mkiv +++ b/tex/context/base/m-barcodes.mkiv @@ -35,7 +35,7 @@ % \definefont[barcodefont][file:texgyreheros-regular] \startluacode -plugins.barcodes = { } +moduledata.barcodes = { } local function split(code) local t = { string.byte(code,1,#code) } @@ -53,7 +53,7 @@ local function split(code) end end -function plugins.barcodes.isbn_1(original) +function moduledata.barcodes.isbn_1(original) local code = string.gsub(original,"%-","") local t, s, m, c = split(code) if t then @@ -68,7 +68,7 @@ function plugins.barcodes.isbn_1(original) tex.sprint(code) end -function plugins.barcodes.isbn_2(original) +function moduledata.barcodes.isbn_2(original) local code = string.gsub(original,"%-","") local t, s, m, c = split(code) if t and #t == 12 then @@ -85,13 +85,13 @@ end \vbox { \hbox { \hskip3.7mm - \scale[width=34mm]{\barcodefont ISBN \ctxlua{plugins.barcodes.isbn_2("\getvariable{barcode}{code}")}} + \scale[width=34mm]{\barcodefont ISBN \ctxlua{moduledata.barcodes.isbn_2("\getvariable{barcode}{code}")}} } \par \normalexpanded { \noexpand \setPSTRICKS { \noexpand \pspicture(-4mm,-1mm)(38mm,26mm) \noexpand \psbarcode { - \ctxlua{plugins.barcodes.isbn_1("\getvariable{barcode}{code}")} + \ctxlua{moduledata.barcodes.isbn_1("\getvariable{barcode}{code}")} } { includetext guardwhitespace } { diff --git a/tex/context/base/m-mathcrap.mkiv b/tex/context/base/m-mathcrap.mkiv new file mode 100644 index 000000000..37dbbedeb --- /dev/null +++ b/tex/context/base/m-mathcrap.mkiv @@ -0,0 +1,76 @@ +%D \module +%D [ file=m-mathcrap, +%D version=2010.05.30, +%D title=\CONTEXT\ Modules, +%D subtitle=Math Crap, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright=PRAGMA ADE] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This is meant for those who want to use the (incomplete and sort of useless) +%D unicode superscripts and subscripts. We should look ahead and collapse them +%D but I will only implement that in calcmath when the need is there. Now the +%D spacing can be somewhat non optimal but probably that does not matter here. +%D +%D \startbuffer +%D $a₀₁₂₃₄₅₆₇₈₉₋₌₊$ +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank + +\unprotect + +\unexpanded\def\mathunicodesupercrap#1{\mathortext{{^{#1}}}{\high{#1}}} +\unexpanded\def\mathunicodesubcrap #1{\mathortext{{_{#1}}}{\low {#1}}} + +\ifdefined\installanddefineactivecharacter\else + + \def\installanddefineactivecharacter #1 #2% we need this as command + {\normalexpanded{\noexpand\installactivecharacter \utfchar{#1} }% + \defineactivecharacter #1 {#2}} + +\fi + +\installanddefineactivecharacter "2070 {\mathunicodesupercrap 0} +\installanddefineactivecharacter "00B9 {\mathunicodesupercrap 1}₀ +\installanddefineactivecharacter "00B2 {\mathunicodesupercrap 2}₀ +\installanddefineactivecharacter "00B3 {\mathunicodesupercrap 3}₀ +\installanddefineactivecharacter "2074 {\mathunicodesupercrap 4} +\installanddefineactivecharacter "2075 {\mathunicodesupercrap 5} +\installanddefineactivecharacter "2076 {\mathunicodesupercrap 6} +\installanddefineactivecharacter "2077 {\mathunicodesupercrap 7} +\installanddefineactivecharacter "2078 {\mathunicodesupercrap 8} +\installanddefineactivecharacter "2079 {\mathunicodesupercrap 9} +\installanddefineactivecharacter "207A {\mathunicodesupercrap +} +\installanddefineactivecharacter "207B {\mathunicodesupercrap -} +\installanddefineactivecharacter "207C {\mathunicodesupercrap =} +\installanddefineactivecharacter "207D {\mathunicodesupercrap (} +\installanddefineactivecharacter "207E {\mathunicodesupercrap )} +\installanddefineactivecharacter "207F {\mathunicodesupercrap n} + +\installanddefineactivecharacter "2080 {\mathunicodesubcrap 0} +\installanddefineactivecharacter "2081 {\mathunicodesubcrap 1} +\installanddefineactivecharacter "2082 {\mathunicodesubcrap 2} +\installanddefineactivecharacter "2083 {\mathunicodesubcrap 3} +\installanddefineactivecharacter "2084 {\mathunicodesubcrap 4} +\installanddefineactivecharacter "2085 {\mathunicodesubcrap 5} +\installanddefineactivecharacter "2086 {\mathunicodesubcrap 6} +\installanddefineactivecharacter "2087 {\mathunicodesubcrap 7} +\installanddefineactivecharacter "2088 {\mathunicodesubcrap 8} +\installanddefineactivecharacter "2089 {\mathunicodesubcrap 9} +\installanddefineactivecharacter "208A {\mathunicodesubcrap +} +\installanddefineactivecharacter "208B {\mathunicodesubcrap -} +\installanddefineactivecharacter "208C {\mathunicodesubcrap =} +\installanddefineactivecharacter "208D {\mathunicodesubcrap (} +\installanddefineactivecharacter "208E {\mathunicodesubcrap )} +\installanddefineactivecharacter "2090 {\mathunicodesubcrap A} +\installanddefineactivecharacter "2091 {\mathunicodesubcrap E} +\installanddefineactivecharacter "2092 {\mathunicodesubcrap O} +\installanddefineactivecharacter "2093 {\mathunicodesubcrap X} +%installanddefineactivecharacter "2094 {\mathunicodesubcrap ?} % SCHWAA + +\protect \endinput diff --git a/tex/context/base/m-pstricks.lua b/tex/context/base/m-pstricks.lua index 35cae93f6..4fb80c7ed 100644 --- a/tex/context/base/m-pstricks.lua +++ b/tex/context/base/m-pstricks.lua @@ -17,8 +17,9 @@ if not modules then modules = { } end modules ['m-pstricks'] = { local format, lower, concat, gmatch = string.format, string.lower, table.concat, string.gmatch local variables = interfaces.variables -plugins = plugins or { } -plugins.pstricks = plugins.pstricks or { } +moduledata.pstricks = moduledata.pstricks or { } + +local report_pstricks = logs.new("pstricks") local template = [[ \starttext @@ -41,13 +42,13 @@ local template = [[ local modules = { } local graphics = 0 -function plugins.pstricks.usemodule(names) +function moduledata.pstricks.usemodule(names) for name in gmatch(names,"([^%s,]+)") do modules[#modules+1] = format([[\readfile{%s}{}{}]],name) end end -function plugins.pstricks.process(n) +function moduledata.pstricks.process(n) graphics = graphics + 1 local name = string.format("%s-pstricks-%04i",tex.jobname,graphics) local data = buffers.collect("def-"..n) @@ -65,9 +66,9 @@ function plugins.pstricks.process(n) if lfs.isfile(pdffile) then context.externalfigure( { pdffile }, { object = variables.no } ) else - logs.report("plugins","pstricks run failed, no pdf file") + report_pstricks("run failed, no pdf file") end else - logs.report("plugins","pstricks run failed, no ps file") + report_pstricks("run failed, no ps file") end end diff --git a/tex/context/base/m-pstricks.mkiv b/tex/context/base/m-pstricks.mkiv index c800ec199..c976982a6 100644 --- a/tex/context/base/m-pstricks.mkiv +++ b/tex/context/base/m-pstricks.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\ctxloadluafile{m-pstricks}{} +\registerctxluafile{m-pstricks}{} %D \startbuffer %D \usePSTRICKSmodule[pst-barcode] @@ -57,8 +57,8 @@ \definebuffer[PSTRICKS] -\unexpanded\def\processPSTRICKS {\ctxlua{plugins.pstricks.process(\thebuffernumber{PSTRICKS})}} -\unexpanded\def\usePSTRICKSmodule[#1]{\ctxlua{plugins.pstricks.usemodule("#1")}} +\unexpanded\def\processPSTRICKS {\ctxlua{moduledata.pstricks.process(\thebuffernumber{PSTRICKS})}} +\unexpanded\def\usePSTRICKSmodule[#1]{\ctxlua{moduledata.pstricks.usemodule("#1")}} \unexpanded\def\setPSTRICKS #1{\setbuffer[def-\thebuffernumber{PSTRICKS}]#1\endbuffer} \let\stopPSTRICKS\processPSTRICKS diff --git a/tex/context/base/m-punk.mkiv b/tex/context/base/m-punk.mkiv index 65bf03974..051d51485 100644 --- a/tex/context/base/m-punk.mkiv +++ b/tex/context/base/m-punk.mkiv @@ -92,7 +92,7 @@ do instances = instances or metapost.characters.instances or 10 local fontname = file.removesuffix(file.basename(name)) local hash = file.robustname(string.format("%s %05i %03i", fontname, scalefactor*1000, instances)) - local lists = containers.read(fonts.mp.cache(), hash) + local lists = containers.read(fonts.mp.cache, hash) if not lists then statistics.starttiming(flusher) -- we can use a format per font @@ -137,7 +137,7 @@ do } end metapost.reset(mpxformat) -- saves memory - lists = containers.write(fonts.mp.cache(), hash, lists) + lists = containers.write(fonts.mp.cache, hash, lists) statistics.stoptiming(flusher) end variants = variants + #lists diff --git a/tex/context/base/m-timing.tex b/tex/context/base/m-timing.tex index f02a90087..55185b0b2 100644 --- a/tex/context/base/m-timing.tex +++ b/tex/context/base/m-timing.tex @@ -36,7 +36,7 @@ \ctxloadluafile{trac-tim}{} \startluacode -local progress = plugins.progress +local progress = moduledata.progress function progress.show(filename,parameters,nodes,other) for n, name in pairs(parameters or progress.parameters(filename)) do @@ -51,16 +51,16 @@ end % \everyfirstshipout \startnotmode[no-timing] - \appendtoks\ctxlua{plugins.progress.store()}\to\everystarttext - \appendtoks\ctxlua{plugins.progress.store()}\to\everyshipout - \ctxlua{main.register_stop_actions(function() plugins.progress.save() end)} + \appendtoks\ctxlua{moduledata.progress.store()}\to\everystarttext + \appendtoks\ctxlua{moduledata.progress.store()}\to\everyshipout + \ctxlua{luatex.register_stop_actions(function() moduledata.progress.save() end)} \stopnotmode \def\ShowNamedUsage#1#2#3% {\setbox\scratchbox\vbox\bgroup\startMPcode begingroup ; save p, q, b, h, w ; path p, q, b ; numeric h, w ; - p := \ctxlua{tex.sprint(plugins.progress.path("#1","#2"))} ; + p := \ctxlua{tex.sprint(moduledata.progress.path("#1","#2"))} ; % p := p shifted -llcorner p ; if bbwidth(p) > 1 : h := 100 ; w := 2 * h ; @@ -71,7 +71,7 @@ end draw b withcolor \MPcolor{usage:frame} ; draw p withcolor \MPcolor{usage:line} ; if ("#3" <> "") and ("#3" <> "#2") : - q := \ctxlua{tex.sprint(plugins.progress.path("#1","#3"))} ; + q := \ctxlua{tex.sprint(moduledata.progress.path("#1","#3"))} ; % q := q shifted -llcorner q ; if bbwidth(q) > 1 : q := q xstretched w ; @@ -87,16 +87,16 @@ end \startlinecorrection \box\scratchbox \endgraf \hbox to \scratchdimen{\tttf\strut\detokenize{#2}\hss - min:\ctxlua{tex.sprint(plugins.progress.bot("#1","\detokenize{#2}"))}, % - max:\ctxlua{tex.sprint(plugins.progress.top("#1","\detokenize{#2}"))}, % - pages:\ctxlua{tex.sprint(plugins.progress.pages("#1"))}% + min:\ctxlua{tex.sprint(moduledata.progress.bot("#1","\detokenize{#2}"))}, % + max:\ctxlua{tex.sprint(moduledata.progress.top("#1","\detokenize{#2}"))}, % + pages:\ctxlua{tex.sprint(moduledata.progress.pages("#1"))}% }% \stoplinecorrection \fi} -\def\LoadUsage #1{\ctxlua{plugins.progress.convert("#1")}} -\def\ShowUsage #1{\ctxlua{plugins.progress.show("#1",nil,nil,"elapsed_time")}} -\def\ShowMemoryUsage#1{\ctxlua{plugins.progress.show("#1",nil,{}, "elapsed_time")}} -\def\ShowNodeUsage #1{\ctxlua{plugins.progress.show("#1",{},nil, "elapsed_time")}} +\def\LoadUsage #1{\ctxlua{moduledata.progress.convert("#1")}} +\def\ShowUsage #1{\ctxlua{moduledata.progress.show("#1",nil,nil,"elapsed_time")}} +\def\ShowMemoryUsage#1{\ctxlua{moduledata.progress.show("#1",nil,{}, "elapsed_time")}} +\def\ShowNodeUsage #1{\ctxlua{moduledata.progress.show("#1",{},nil, "elapsed_time")}} \endinput diff --git a/tex/context/base/math-def.mkiv b/tex/context/base/math-def.mkiv index 50c9902dd..af7166f80 100644 --- a/tex/context/base/math-def.mkiv +++ b/tex/context/base/math-def.mkiv @@ -113,6 +113,8 @@ \def\plainbigdelimiters % traditional method {\chardef\bigmathdelimitermethod\plustwo} +\plainbigdelimiters % is default for the moment but not so nice + \def\doplainbigmath#1#2% {{\hbox{$% \nulldelimiterspace\zeropoint\relax diff --git a/tex/context/base/math-dim.lua b/tex/context/base/math-dim.lua index 62d805126..fbaffe4fb 100644 --- a/tex/context/base/math-dim.lua +++ b/tex/context/base/math-dim.lua @@ -249,7 +249,6 @@ function mathematics.dimensions(dimens) end t[variable] = tt end ---~ logs.report("warning", "version 0.47 is needed for proper delimited math") local d = { AxisHeight = t . axis . text_style, AccentBaseHeight = t . accent_base_height . text_style, diff --git a/tex/context/base/math-ent.lua b/tex/context/base/math-ent.lua index e5e5b98f0..d387f9ee5 100644 --- a/tex/context/base/math-ent.lua +++ b/tex/context/base/math-ent.lua @@ -5,6 +5,8 @@ if not modules then modules = { } end modules ['math-ent'] = { copyright = "derived from the mathml 2.0 specification", } +-- this might go into char-def + mathematics.entities={ ["Aacute"]=0x000C1, ["aacute"]=0x000E1, diff --git a/tex/context/base/math-ext.lua b/tex/context/base/math-ext.lua index 673103677..32d0263d9 100644 --- a/tex/context/base/math-ext.lua +++ b/tex/context/base/math-ext.lua @@ -11,6 +11,8 @@ local trace_virtual = false trackers.register("math.virtual", function(v) trace_ mathematics = mathematics or { } characters = characters or { } +local report_math = logs.new("mathematics") + mathematics.extras = mathematics.extras or { } characters.math = characters.math or { } @@ -22,7 +24,7 @@ function mathematics.extras.add(unicode,t) if unicode >= min and unicode <= max then mathdata[unicode], chardata[unicode] = t, t else - logs.report("math extra","extra U+%04X should be in range U+%04X - U+%04X",unicode,min,max) + report_math("extra U+%04X should be in range U+%04X - U+%04X",unicode,min,max) end end @@ -45,7 +47,7 @@ function mathematics.extras.copy(tfmdata) local nextchar = characters[nextnext] if nextchar then if trace_virtual then - logs.report("math extra","extra U+%04X in %s at %s maps on U+%04X (class: %s, name: %s)",unicode,file.basename(tfmdata.fullname),tfmdata.size,nextslot,extradesc.mathclass or "?",extradesc.mathname or "?") + report_math("extra U+%04X in %s at %s maps on U+%04X (class: %s, name: %s)",unicode,file.basename(tfmdata.fullname),tfmdata.size,nextslot,extradesc.mathclass or "?",extradesc.mathname or "?") end characters[unicode] = nextchar break @@ -53,11 +55,12 @@ function mathematics.extras.copy(tfmdata) end end end - if not characters[unicode] then + if not characters[unicode] then -- can be set in previous loop for i=1,#nextinsize do - local nextbase = characters[nextinsize[i]] + local nextslot = nextinsize[i] + local nextbase = characters[nextslot] if nextbase then - characters[unicode] = nextchar + characters[unicode] = nextbase -- still ok? break end end @@ -126,6 +129,16 @@ mathematics.extras.add(0xFE323, { unicodeslot=0xFE323, } ) +mathematics.extras.add(0xFE324, { + category="sm", + description="MATHEMATICAL SHORT BAR MIRRORED", +-- direction="on", +-- linebreak="nu", + mathclass="relation", + mathname="mapsfromchar", + unicodeslot=0xFE324, +} ) + --~ mathematics.extras.add(0xFE304, { --~ category="sm", --~ description="TOP AND BOTTOM PARENTHESES", diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua index 63d7cad38..b5927f998 100644 --- a/tex/context/base/math-ini.lua +++ b/tex/context/base/math-ini.lua @@ -15,6 +15,8 @@ local texsprint, format, utfchar, utfbyte = tex.sprint, string.format, utf.char, local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end) +local report_math = logs.new("mathematics") + mathematics = mathematics or { } mathematics.extrabase = 0xFE000 -- here we push some virtuals @@ -154,11 +156,11 @@ end local function report(class,family,unicode,name) local nametype = type(name) if nametype == "string" then - logs.report("mathematics","%s:%s %s U+%05X (%s) => %s",classname,class,family,unicode,utfchar(unicode),name) + report_math("%s:%s %s U+%05X (%s) => %s",classname,class,family,unicode,utfchar(unicode),name) elseif nametype == "number" then - logs.report("mathematics","%s:%s %s U+%05X (%s) => U+%05X",classname,class,family,unicode,utfchar(unicode),name) + report_math("%s:%s %s U+%05X (%s) => U+%05X",classname,class,family,unicode,utfchar(unicode),name) else - logs.report("mathematics","%s:%s %s U+%05X (%s)", classname,class,family,unicode,utfchar(unicode)) + report_math("%s:%s %s U+%05X (%s)", classname,class,family,unicode,utfchar(unicode)) end end diff --git a/tex/context/base/math-ini.mkiv b/tex/context/base/math-ini.mkiv index 828a6eccb..8feeae432 100644 --- a/tex/context/base/math-ini.mkiv +++ b/tex/context/base/math-ini.mkiv @@ -250,10 +250,10 @@ {\normalhbox\bgroup\mf \dowithnextbox{\flushnextbox\egroup}\normalhbox} -\def\mbox +\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible {\ifmmode\normalmbox\else\normalhbox\fi} -\def\enablembox +\unexpanded\def\enablembox {\appendtoks \ifx\normalhbox\undefined\let\normalhbox\hbox\fi \let\hbox\mbox diff --git a/tex/context/base/math-int.mkiv b/tex/context/base/math-int.mkiv index 2af471b5c..9bb7b1a14 100644 --- a/tex/context/base/math-int.mkiv +++ b/tex/context/base/math-int.mkiv @@ -53,22 +53,45 @@ %D More integrals (AM): -\definemathcommand [iint] {\repeatintegral\plusone } -\definemathcommand [iiint] {\repeatintegral\plustwo } -\definemathcommand [iiiint] {\repeatintegral\plusthree} - %def\integralrepeatsymbol{\intop} \def\integralrepeatsymbol{{\int}} -\def\repeatintegral#1% +% \def\repeatintegral#1% +% {\scratchtoks\emptytoks +% \let\dointlimits\donothing +% \let\dodointlimits\intlimits +% \dorecurse{#1}{\appendtoks \integralrepeatsymbol \dointkern \to \scratchtoks}% +% \appendtoks \intop \dointlimits \dodointlimits \to \scratchtoks +% \edef\dodorepeatintegral{\the\scratchtoks}% +% \futurelet\next\dorepeatintegral} + +% \definemathcommand [iint] {\repeatintegral\plusone } +% \definemathcommand [iiint] {\repeatintegral\plustwo } +% \definemathcommand [iiiint] {\repeatintegral\plusthree} + +\def\fakerepeatintegral#1% {\scratchtoks\emptytoks - \let\dointlimits\donothing - \let\dodointlimits\intlimits - \dorecurse{#1}{\appendtoks \integralrepeatsymbol \dointkern \to \scratchtoks} + \dorecurse{#1}{\appendtoks \integralrepeatsymbol \dointkern \to \scratchtoks}% \appendtoks \intop \dointlimits \dodointlimits \to \scratchtoks - \edef\dodorepeatintegral{\the\scratchtoks}% + \edef\dodorepeatintegral{\the\scratchtoks}} + +\def\repeatintegral#1#2#3% + {\let\dointlimits\donothing + \let\dodointlimits\intlimits + \iffontchar\textfont\zerocount#1\relax + %\edef\dodorepeatintegral{\utfchar{#1}}% + \let\dodorepeatintegral#2% + \else + \fakerepeatintegral{#3}% + \fi \futurelet\next\dorepeatintegral} +% This is a temporary solution, as we will make a virtual glyph in lm. + +\definemathcommand [iint] {\repeatintegral{"222B}\normaliint \plusone } +\definemathcommand [iiint] {\repeatintegral{"222C}\normaliiint \plustwo } +\definemathcommand [iiiint] {\repeatintegral{"222D}\normaliiiint\plusthree} + %D If the \type{\limits} option is used after \type{\iint}, use %D \type{\mathop} and fudge the left hand space a bit to make the %D subscript visually centered. diff --git a/tex/context/base/math-map.lua b/tex/context/base/math-map.lua index 2d34dc1c3..b6a12bf31 100644 --- a/tex/context/base/math-map.lua +++ b/tex/context/base/math-map.lua @@ -26,6 +26,8 @@ local texattribute = tex.attribute local trace_greek = false trackers.register("math.greek", function(v) trace_greek = v end) +local report_math = logs.new("mathematics") + mathematics = mathematics or { } -- we could use one level less and have tf etc be tables directly but the @@ -400,7 +402,7 @@ function mathematics.remap_alphabets(char,mathalphabet,mathgreek) local alphabet = r and r.alphabet or "regular" local style = r and r.style or "tf" if trace_greek then - logs.report("math","before: char: %05X, alphabet: %s %s, lcgreek: %s, ucgreek: %s",char,alphabet,style,remapping[lc].what,remapping[uc].what) + report_math("before: char: %05X, alphabet: %s %s, lcgreek: %s, ucgreek: %s",char,alphabet,style,remapping[lc].what,remapping[uc].what) end local s = remapping[islc or isuc][style] if s then @@ -408,7 +410,7 @@ function mathematics.remap_alphabets(char,mathalphabet,mathgreek) mathalphabet, style = data and data.attribute or mathalphabet, s end if trace_greek then - logs.report("math","after : char: %05X, alphabet: %s %s, lcgreek: %s, ucgreek: %s",char,alphabet,style,remapping[lc].what,remapping[uc].what) + report_math("after : char: %05X, alphabet: %s %s, lcgreek: %s, ucgreek: %s",char,alphabet,style,remapping[lc].what,remapping[uc].what) end end end @@ -420,13 +422,13 @@ function mathematics.remap_alphabets(char,mathalphabet,mathgreek) -- nothing to remap elseif char >= 0x030 and char <= 0x039 then local o = offset.digits - newchar = (type(o) == "table" and (o[char] or char)) or (char - 0x030 + o) + newchar = o and ((type(o) == "table" and (o[char] or char)) or (char - 0x030 + o)) elseif char >= 0x041 and char <= 0x05A then local o = offset.ucletters - newchar = (type(o) == "table" and (o[char] or char)) or (char - 0x041 + o) + newchar = o and ((type(o) == "table" and (o[char] or char)) or (char - 0x041 + o)) elseif char >= 0x061 and char <= 0x07A then local o = offset.lcletters - newchar = (type(o) == "table" and (o[char] or char)) or (char - 0x061 + o) + newchar = o and ((type(o) == "table" and (o[char] or char)) or (char - 0x061 + o)) elseif islcgreek[char] then newchar = offset.lcgreek[char] elseif isucgreek[char] then diff --git a/tex/context/base/math-noa.lua b/tex/context/base/math-noa.lua index 02bbe0a62..20f7e5d12 100644 --- a/tex/context/base/math-noa.lua +++ b/tex/context/base/math-noa.lua @@ -27,6 +27,8 @@ local trace_remapping = false trackers.register("math.remapping", function(v) local trace_processing = false trackers.register("math.processing", function(v) trace_processing = v end) local trace_analyzing = false trackers.register("math.analyzing", function(v) trace_analyzing = v end) +local report_noads = logs.new("noads") + local noad_ord = 0 local noad_op_displaylimits = 1 local noad_op_limits = 2 @@ -85,50 +87,53 @@ local all_noads = { noads.processors = noads.processors or { } -local function process(start,what,n) +local function process(start,what,n,parent) if n then n = n + 1 else n = 0 end while start do if trace_processing then - logs.report("math","%s%s",rep(" ",n or 0),tostring(start)) + report_noads("%s%s",rep(" ",n or 0),tostring(start)) end local id = start.id local proc = what[id] if proc then - proc(start,what,n) + local done, newstart = proc(start,what,n,parent or start.prev) + if newstart then + start = newstart + end elseif id == math_char or id == math_text_char or id == math_delim then break elseif id == math_style then -- has a next elseif id == math_noad then - local noad = start.nucleus if noad then process(noad,what,n) end -- list - noad = start.sup if noad then process(noad,what,n) end -- list - noad = start.sub if noad then process(noad,what,n) end -- list + local noad = start.nucleus if noad then process(noad,what,n,start) end -- list + noad = start.sup if noad then process(noad,what,n,start) end -- list + noad = start.sub if noad then process(noad,what,n,start) end -- list elseif id == math_box or id == math_sub then - local noad = start.list if noad then process(noad,what,n) end -- list + local noad = start.list if noad then process(noad,what,n,start) end -- list elseif id == math_fraction then - local noad = start.num if noad then process(noad,what,n) end -- list - noad = start.denom if noad then process(noad,what,n) end -- list - noad = start.left if noad then process(noad,what,n) end -- delimiter - noad = start.right if noad then process(noad,what,n) end -- delimiter + local noad = start.num if noad then process(noad,what,n,start) end -- list + noad = start.denom if noad then process(noad,what,n,start) end -- list + noad = start.left if noad then process(noad,what,n,start) end -- delimiter + noad = start.right if noad then process(noad,what,n,start) end -- delimiter elseif id == math_choice then - local noad = start.display if noad then process(noad,what,n) end -- list - noad = start.text if noad then process(noad,what,n) end -- list - noad = start.script if noad then process(noad,what,n) end -- list - noad = start.scriptscript if noad then process(noad,what,n) end -- list + local noad = start.display if noad then process(noad,what,n,start) end -- list + noad = start.text if noad then process(noad,what,n,start) end -- list + noad = start.script if noad then process(noad,what,n,start) end -- list + noad = start.scriptscript if noad then process(noad,what,n,start) end -- list elseif id == math_fence then - local noad = start.delim if noad then process(noad,what,n) end -- delimiter + local noad = start.delim if noad then process(noad,what,n,start) end -- delimiter elseif id == math_radical then - local noad = start.nucleus if noad then process(noad,what,n) end -- list - noad = start.sup if noad then process(noad,what,n) end -- list - noad = start.sub if noad then process(noad,what,n) end -- list - noad = start.left if noad then process(noad,what,n) end -- delimiter - noad = start.degree if noad then process(noad,what,n) end -- list + local noad = start.nucleus if noad then process(noad,what,n,start) end -- list + noad = start.sup if noad then process(noad,what,n,start) end -- list + noad = start.sub if noad then process(noad,what,n,start) end -- list + noad = start.left if noad then process(noad,what,n,start) end -- delimiter + noad = start.degree if noad then process(noad,what,n,start) end -- list elseif id == math_accent then - local noad = start.nucleus if noad then process(noad,what,n) end -- list - noad = start.sup if noad then process(noad,what,n) end -- list - noad = start.sub if noad then process(noad,what,n) end -- list - noad = start.accent if noad then process(noad,what,n) end -- list - noad = start.bot_accent if noad then process(noad,what,n) end -- list + local noad = start.nucleus if noad then process(noad,what,n,start) end -- list + noad = start.sup if noad then process(noad,what,n,start) end -- list + noad = start.sub if noad then process(noad,what,n,start) end -- list + noad = start.accent if noad then process(noad,what,n,start) end -- list + noad = start.bot_accent if noad then process(noad,what,n,start) end -- list else -- glue, penalty, etc end @@ -146,7 +151,7 @@ local mathgreek = attributes.private("mathgreek") noads.processors.relocate = { } local function report_remap(tag,id,old,new,extra) - logs.report("math","remapping %s in font %s from U+%04X (%s) to U+%04X (%s)%s",tag,id,old,utfchar(old),new,utfchar(new),extra or "") + report_noads("remapping %s in font %s from U+%04X (%s) to U+%04X (%s)%s",tag,id,old,utfchar(old),new,utfchar(new),extra or "") end local remap_alphabets = mathematics.remap_alphabets @@ -247,9 +252,9 @@ end local mathsize = attributes.private("mathsize") -noads.processors.resize = { } +local resize = { } noads.processors.resize = resize -noads.processors.resize[math_fence] = function(pointer) +resize[math_fence] = function(pointer) if pointer.subtype == 1 then -- left local a = has_attribute(pointer,mathsize) if a and a > 0 then @@ -266,7 +271,7 @@ noads.processors.resize[math_fence] = function(pointer) end function noads.resize_characters(head,style,penalties) - process(head,noads.processors.resize) + process(head,resize) return true end @@ -274,13 +279,13 @@ end local mathpunctuation = attributes.private("mathpunctuation") -noads.processors.respace = { } +local respace = { } noads.processors.respace = respace local chardata = characters.data -- only [nd,ll,ul][po][nd,ll,ul] -noads.processors.respace[math_noad] = function(pointer) +respace[math_noad] = function(pointer) if pointer.subtype == noad_ord then local a = has_attribute(pointer,mathpunctuation) if a and a > 0 then @@ -327,9 +332,8 @@ noads.processors.respace[math_noad] = function(pointer) end end - function noads.respace_characters(head,style,penalties) - noads.process(head,noads.processors.respace) + process(head,respace) return true end diff --git a/tex/context/base/math-vfu.lua b/tex/context/base/math-vfu.lua index 5023e6b4d..dccb30c92 100644 --- a/tex/context/base/math-vfu.lua +++ b/tex/context/base/math-vfu.lua @@ -11,10 +11,13 @@ if not modules then modules = { } end modules ['math-vfu'] = { -- characters report it to the ConTeXt mailing list. local type, next = type, next +local max = math.max local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end) local trace_timings = false trackers.register("math.timings", function(v) trace_timings = v end) +local report_virtual = logs.new("virtual math") + fonts.enc.math = fonts.enc.math or { } local shared = { } @@ -69,20 +72,19 @@ local function brace(main,characters,id,size,unicode,first,rule,left,right,rule, end local function arrow(main,characters,id,size,unicode,arrow,minus,isleft) - if characters[unicode] then - if isleft then - t = { - { extender = 0, glyph = arrow }, - { extender = 1, glyph = minus }, - } - else - t = { - { extender = 0, glyph = minus }, - { extender = 1, glyph = arrow }, - } - end - --~ main.characters[unicode] = { horiz_variants = t } - characters[unicode].horiz_variants = t + local chr = characters[unicode] + if not chr then + -- skip + elseif isleft then + chr.horiz_variants = { + { extender = 0, glyph = arrow }, + { extender = 1, glyph = minus }, + } + else + chr.horiz_variants = { + { extender = 0, glyph = minus }, + { extender = 1, glyph = arrow }, + } end end @@ -226,32 +228,107 @@ local function vertbar(main,characters,id,size,parent,scale,unicode) end end +local function jointwo(main,characters,id,size,unicode,u1,d12,u2) + local c1, c2 = characters[u1], characters[u2] + if c1 and c2 then + local w1, w2 = c1.width, c2.width + local mu = size/18 + characters[unicode] = { + width = w1 + w2 - d12*mu, + height = max(c1.height or 0, c2.height or 0), + depth = max(c1.depth or 0, c2.depth or 0), + commands = { + { "slot", id, u1 }, + { "right", -d12*mu } , + { "slot", id, u2 }, + } + } + end +end + +local function jointhree(main,characters,id,size,unicode,u1,d12,u2,d23,u3) + local c1, c2, c3 = characters[u1], characters[u2], characters[u3] + if c1 and c2 and c3 then + local w1, w2, w3 = c1.width, c2.width, c3.width + local mu = size/18 + characters[unicode] = { + width = w1 + w2 + w3 - d12*mu - d23*mu, + height = max(c1.height or 0, c2.height or 0, c3.height or 0), + depth = max(c1.depth or 0, c2.depth or 0, c3.depth or 0), + commands = { + { "slot", id, u1 }, + { "right", - d12*mu } , + { "slot", id, u2 }, + { "right", - d23*mu }, + { "slot", id, u3 }, + } + } + end +end + +local function stack(main,characters,id,size,unicode,u1,d12,u2) + local c1, c2 = characters[u1], characters[u2] + if c1 and c2 then + local w1, w2 = c1.width, c2.width + local h1, h2 = c1.height, c2.height + local d1, d2 = c1.depth, c2.depth + local mu = size/18 + characters[unicode] = { + width = w1, + height = h1 + h2 + d12, + depth = d1, + commands = { + { "slot", id, u1 }, + { "right", - w1/2 - w2/2 } , + { "down", -h1 + d2 -d12*mu } , + { "slot", id, u2 }, + } + } + end +end + function fonts.vf.math.alas(main,id,size) local characters = main.characters for i=0x7A,0x7D do make(main,characters,id,size,i,1) end - brace (main,characters,id,size,0x23DE,0xFF17A,0xFF301,0xFF17D,0xFF17C,0xFF301,0xFF17B) - brace (main,characters,id,size,0x23DF,0xFF27C,0xFF401,0xFF27B,0xFF27A,0xFF401,0xFF27D) - parent (main,characters,id,size,0x23DC,0xFF17A,0xFF301,0xFF17B) - parent (main,characters,id,size,0x23DD,0xFF27C,0xFF401,0xFF27D) - negate (main,characters,id,size,0x2260,0x003D) - dots (main,characters,id,size,0x2026) -- ldots - dots (main,characters,id,size,0x22EE) -- vdots - dots (main,characters,id,size,0x22EF) -- cdots - dots (main,characters,id,size,0x22F1) -- ddots - dots (main,characters,id,size,0x22F0) -- udots - minus (main,characters,id,size,0xFF501) - arrow (main,characters,id,size,0x2190,0xFE190,0xFF501,true) -- left - arrow (main,characters,id,size,0x2192,0xFE192,0xFF501,false) -- right - vertbar(main,characters,id,size,0x0007C,0.10,0xFF601) -- big : 0.85 bodyfontsize - vertbar(main,characters,id,size,0xFF601,0.30,0xFF602) -- Big : 1.15 bodyfontsize - vertbar(main,characters,id,size,0xFF602,0.30,0xFF603) -- bigg : 1.45 bodyfontsize - vertbar(main,characters,id,size,0xFF603,0.30,0xFF604) -- Bigg : 1.75 bodyfontsize - vertbar(main,characters,id,size,0x02225,0.10,0xFF605) - vertbar(main,characters,id,size,0xFF605,0.30,0xFF606) - vertbar(main,characters,id,size,0xFF606,0.30,0xFF607) - vertbar(main,characters,id,size,0xFF607,0.30,0xFF608) + brace (main,characters,id,size,0x23DE,0xFF17A,0xFF301,0xFF17D,0xFF17C,0xFF301,0xFF17B) + brace (main,characters,id,size,0x23DF,0xFF27C,0xFF401,0xFF27B,0xFF27A,0xFF401,0xFF27D) + parent (main,characters,id,size,0x23DC,0xFF17A,0xFF301,0xFF17B) + parent (main,characters,id,size,0x23DD,0xFF27C,0xFF401,0xFF27D) + negate (main,characters,id,size,0x2260,0x003D) + dots (main,characters,id,size,0x2026) -- ldots + dots (main,characters,id,size,0x22EE) -- vdots + dots (main,characters,id,size,0x22EF) -- cdots + dots (main,characters,id,size,0x22F1) -- ddots + dots (main,characters,id,size,0x22F0) -- udots + minus (main,characters,id,size,0xFF501) + arrow (main,characters,id,size,0x2190,0xFE190,0xFF501,true) -- left + arrow (main,characters,id,size,0x2192,0xFE192,0xFF501,false) -- right + vertbar (main,characters,id,size,0x0007C,0.10,0xFF601) -- big : 0.85 bodyfontsize + vertbar (main,characters,id,size,0xFF601,0.30,0xFF602) -- Big : 1.15 bodyfontsize + vertbar (main,characters,id,size,0xFF602,0.30,0xFF603) -- bigg : 1.45 bodyfontsize + vertbar (main,characters,id,size,0xFF603,0.30,0xFF604) -- Bigg : 1.75 bodyfontsize + vertbar (main,characters,id,size,0x02016,0.10,0xFF605) + vertbar (main,characters,id,size,0xFF605,0.30,0xFF606) + vertbar (main,characters,id,size,0xFF606,0.30,0xFF607) + vertbar (main,characters,id,size,0xFF607,0.30,0xFF608) + jointwo (main,characters,id,size,0x21A6,0xFE321,0,0x02192) -- \mapstochar\rightarrow + jointwo (main,characters,id,size,0x21A9,0x02190,3,0xFE323) -- \leftarrow\joinrel\rhook + jointwo (main,characters,id,size,0x21AA,0xFE322,3,0x02192) -- \lhook\joinrel\rightarrow + stack (main,characters,id,size,0x2259,0x0003D,3,0x02227) -- \buildrel\wedge\over= + jointwo (main,characters,id,size,0x22C8,0x022B3,4,0x022B2) -- \mathrel\triangleright\joinrel\mathrel\triangleleft (4 looks better than 3) + jointwo (main,characters,id,size,0x2284,0x00338,0,0x02282) -- \not\subset + jointwo (main,characters,id,size,0x2285,0x00338,0,0x02283) -- \not\supset + jointwo (main,characters,id,size,0x22A7,0x0007C,3,0x0003D) -- \mathrel|\joinrel= + jointwo (main,characters,id,size,0x27F5,0x02190,3,0x0002D) -- \leftarrow\joinrel\relbar + jointwo (main,characters,id,size,0x27F6,0x0002D,3,0x02192) -- \relbar\joinrel\rightarrow + jointwo (main,characters,id,size,0x27F7,0x02190,3,0x02192) -- \leftarrow\joinrel\rightarrow + jointwo (main,characters,id,size,0x27F8,0x021D0,3,0x0003D) -- \Leftarrow\joinrel\Relbar + jointwo (main,characters,id,size,0x27F9,0x0003D,3,0x021D2) -- \Relbar\joinrel\Rightarrow + jointwo (main,characters,id,size,0x27FA,0x021D0,3,0x021D2) -- \Leftarrow\joinrel\Rightarrow + jointhree(main,characters,id,size,0x27FB,0x02190,3,0x0002D,0,0xFE324) -- \leftarrow\joinrel\relbar\mapsfromchar + jointhree(main,characters,id,size,0x27FC,0xFE321,0,0x0002D,3,0x02192) -- \mapstochar\relbar\joinrel\rightarrow end local unique = 0 -- testcase: \startTEXpage \math{!\text{-}\text{-}\text{-}} \stopTEXpage @@ -268,7 +345,7 @@ function fonts.basecopy(tfmtable,name) end t.characters = c else - logs.report("math virtual","font %s has no characters",name) + report_virtual("font %s has no characters",name) end if parameters then for k, v in next, parameters do @@ -276,7 +353,7 @@ function fonts.basecopy(tfmtable,name) end t.parameters = p else - logs.report("math virtual","font %s has no parameters",name) + report_virtual("font %s has no parameters",name) end -- tricky ... what if fullname does not exist if fullname then @@ -310,14 +387,14 @@ function fonts.vf.math.define(specification,set) local ssname = ss.name if ss.optional and fonts.vf.math.optional then if trace_virtual then - logs.report("math virtual","loading font %s subfont %s with name %s at %s is skipped",name,s,ssname,size) + report_virtual("loading font %s subfont %s with name %s at %s is skipped",name,s,ssname,size) end else if ss.features then ssname = ssname .. "*" .. ss.features end if ss.main then main = s end local f, id = fonts.tfm.read_and_define(ssname,size) if not f then - logs.report("math virtual","loading font %s subfont %s with name %s at %s is skipped, not found",name,s,ssname,size) + report_virtual("loading font %s subfont %s with name %s at %s is skipped, not found",name,s,ssname,size) else n = n + 1 okset[n] = ss @@ -325,7 +402,30 @@ function fonts.vf.math.define(specification,set) lst[n] = { id = id, size = size } if not shared[s] then shared[n] = { } end if trace_virtual then - logs.report("math virtual","loading font %s subfont %s with name %s at %s as id %s using encoding %s",name,s,ssname,size,id,ss.vector or "none") + report_virtual("loading font %s subfont %s with name %s at %s as id %s using encoding %s",name,s,ssname,size,id,ss.vector or "none") + end + if not ss.checked then + ss.checked = true + local vector = fonts.enc.math[ss.vector] + if vector then + -- we resolve named glyphs only once as we can assume that vectors + -- are unique to a font set (when we read an afm we get those names + -- mapped onto the private area) + for unicode, index in next, vector do + if not tonumber(index) then + local u = f.unicodes + u = u and u[index] + if u then + if trace_virtual then + report_virtual("resolving name %s to %s",index,u) + end + else + report_virtual("unable to resolve name %s",index) + end + vector[unicode] = u + end + end + end end end end @@ -356,7 +456,7 @@ function fonts.vf.math.define(specification,set) mm.big_op_spacing3 = fp[11] or 0 -- big_op_spacing3 minimum baselineskip above displayed op mm.big_op_spacing4 = fp[12] or 0 -- big_op_spacing4 minimum baselineskip below displayed op mm.big_op_spacing5 = fp[13] or 0 -- big_op_spacing5 padding above and below displayed limits - -- logs.report("math virtual","loading and virtualizing font %s at size %s, setting ex parameters",name,size) + -- report_virtual("loading and virtualizing font %s at size %s, setting ex parameters",name,size) elseif ss.parameters then mp.x_height = fp.x_height or mp.x_height mm.x_height = mm.x_height or fp.x_height or 0 -- x_height height of x @@ -375,10 +475,10 @@ function fonts.vf.math.define(specification,set) mm.delim1 = fp[20] or 0 -- delim1 size of \atopwithdelims delimiters in display styles mm.delim2 = fp[21] or 0 -- delim2 size of \atopwithdelims delimiters in non-displays mm.axis_height = fp[22] or 0 -- axis_height height of fraction lines above the baseline - -- logs.report("math virtual","loading and virtualizing font %s at size %s, setting sy parameters",name,size) + -- report_virtual("loading and virtualizing font %s at size %s, setting sy parameters",name,size) end else - logs.report("math virtual","font %s, no parameters set",name) + report_virtual("font %s, no parameters set",name) end local vectorname = ss.vector if vectorname then @@ -399,9 +499,9 @@ function fonts.vf.math.define(specification,set) local ru = rv[unicode] if not ru then 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) + report_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,number.topoints(size)) + report_virtual( "the mapping is incomplete for '%s' at %s",name,number.topoints(size)) already_reported = true end rv[unicode] = true @@ -577,7 +677,7 @@ function fonts.vf.math.define(specification,set) fonts.vf.math.alas(main,#lst,size) end if trace_virtual or trace_timings then - logs.report("math virtual","loading and virtualizing font %s at size %s took %0.3f seconds",name,size,os.clock()-start) + report_virtual("loading and virtualizing font %s at size %s took %0.3f seconds",name,size,os.clock()-start) end main.has_italic = true main.type = "virtual" -- not needed @@ -1015,7 +1115,8 @@ fonts.enc.math["tex-sy"] = { [0x027E8] = 0x68, -- <, langle [0x027E9] = 0x69, -- >, rangle [0x0007C] = 0x6A, -- |, mid, lvert, rvert - [0x02225] = 0x6B, -- parallel, Vert, lVert, rVert, arrowvert + [0x02225] = 0x6B, -- parallel + -- [0x02016] = 0x00, -- Vert, lVert, rVert, arrowvert, Arrowvert [0x02195] = 0x6C, -- updownarrow [0x021D5] = 0x6D, -- Updownarrow [0x0005C] = 0x6E, -- \, backslash, setminus @@ -1304,6 +1405,11 @@ fonts.enc.math["tex-mb"] = { [0x003F6] = 0x7F, -- epsiloninv \backepsilon } +fonts.enc.math["tex-mc"] = { + -- this file has no tfm so it gets mapped in the private space + [0xFE324] = "mapsfromchar", +} + fonts.enc.math["tex-fraktur"] = { -- [0x1D504] = 0x41, -- A (fraktur A) -- [0x1D505] = 0x42, -- B diff --git a/tex/context/base/meta-ini.mkiv b/tex/context/base/meta-ini.mkiv index 61acbca32..1072cb8f2 100644 --- a/tex/context/base/meta-ini.mkiv +++ b/tex/context/base/meta-ini.mkiv @@ -134,8 +134,6 @@ \def\endMPgraphicgroup {\endgroup} -\newconditional \METAFUNinitialized - \def\MPaskedfigure{false} \def\currentMPinitializations @@ -160,7 +158,6 @@ \def\dostopcurrentMPgraphic {\global\MPinstancetoks\emptytoks - \global\settrue\METAFUNinitialized % becomes obsolete \endgroup} \unexpanded\long\def\processMPgraphic#1% todo: extensions and inclusions outside beginfig @@ -1210,7 +1207,7 @@ %D In any case we need to tell the converter what the inherited color %D is to start with. Case~3 is kind of unpredictable as it closely %D relates to the order in which paths are flushed. If you want to -%Dinherit automatically from the surrounding, you can best stick to +%D inherit automatically from the surrounding, you can best stick to %D variant 1. Variant 0 (an isolated graphic) is the default. %D %D \startbuffer diff --git a/tex/context/base/meta-pdf.lua b/tex/context/base/meta-pdf.lua index 23f8d4de0..9a9b13028 100644 --- a/tex/context/base/meta-pdf.lua +++ b/tex/context/base/meta-pdf.lua @@ -15,6 +15,8 @@ local lpegmatch = lpeg.match local round = math.round local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes +local report_mptopdf = logs.new("mptopdf") + local pdfrgbcode = lpdf.rgbcode local pdfcmykcode = lpdf.cmykcode local pdfgraycode = lpdf.graycode @@ -55,7 +57,7 @@ local function texcode(str) texsprint(ctxcatcodes,str) end -function mpscode(str) +local function mpscode(str) if ignore_path then pdfcode("h W n") if extra_path_code then @@ -304,9 +306,9 @@ end -- not supported in mkiv , use mplib instead -handlers[10] = function() logs.report("mptopdf","skipping special %s",10) end -handlers[20] = function() logs.report("mptopdf","skipping special %s",20) end -handlers[50] = function() logs.report("mptopdf","skipping special %s",50) end +handlers[10] = function() report_mptopdf("skipping special %s",10) end +handlers[20] = function() report_mptopdf("skipping special %s",20) end +handlers[50] = function() report_mptopdf("skipping special %s",50) end --end of not supported @@ -320,7 +322,7 @@ function mps.setrgbcolor(r,g,b) -- extra check if handler then handler(s) else - logs.report("mptopdf","unknown special handler %s (1)",h) + report_mptopdf("unknown special handler %s (1)",h) end elseif r == 0.123 and g < 0.1 then g, b = round(g*1000), round(b*1000) @@ -330,7 +332,7 @@ function mps.setrgbcolor(r,g,b) -- extra check if handler then handler(s) else - logs.report("mptopdf","unknown special handler %s (2)",h) + report_mptopdf("unknown special handler %s (2)",h) end else pdfcode(pdffinishtransparencycode()) diff --git a/tex/context/base/metatex.lus b/tex/context/base/metatex.lus new file mode 100644 index 000000000..df7bc1914 --- /dev/null +++ b/tex/context/base/metatex.lus @@ -0,0 +1,9 @@ +if not modules then modules = { } end modules ['metatex'] = { + version = 1.001, + comment = "companion to metatex.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +return "luat-cod.lua" diff --git a/tex/context/base/metatex.tex b/tex/context/base/metatex.tex index e90af709c..d99f75ead 100644 --- a/tex/context/base/metatex.tex +++ b/tex/context/base/metatex.tex @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D We can experiment here with runtime loading, id est no longer +%D We can experiment here with runtime loading, i.e. no longer %D use a format. However, we still need a stub then but it could %D as well be luatools (mtxrun) itself then. @@ -51,7 +51,9 @@ \newtoks\metatexversiontoks \metatexversiontoks\expandafter{\metatexversion} % at the lua end +%loadcorefile{norm-ctx} \loadcorefile{syst-pln} % plain tex initializations of internal registers (no further code) +\loadmarkfile{syst-mes} \loadmarkfile{luat-cod} % \loadmarkfile{luat-bas} % @@ -85,6 +87,10 @@ \loadmarkfile{char-ini} \loadmarkfile{char-enc} % \registerctxluafile{char-enc}{1.001} +% attributes + +\loadmarkfile{attr-ini} + % nodes \loadmarkfile{node-ini} diff --git a/tex/context/base/mlib-ctx.lua b/tex/context/base/mlib-ctx.lua index cc5682e6f..d04d9b370 100644 --- a/tex/context/base/mlib-ctx.lua +++ b/tex/context/base/mlib-ctx.lua @@ -11,6 +11,8 @@ if not modules then modules = { } end modules ['mlib-ctx'] = { local format, join = string.format, table.concat local sprint = tex.sprint +local report_mplib = logs.new("mplib") + local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming metapost = metapost or {} @@ -29,7 +31,7 @@ function metapost.getclippath(instance,mpsformat,data,initializations,preamble) local result = mpx:execute(format("%s;beginfig(1);%s;%s;endfig;",preamble or "",initializations or "",data)) stoptiming(metapost.exectime) if result.status > 0 then - logs.report("metafun", "%s: %s", result.status, result.error or result.term or result.log) + report_mplib("%s: %s", result.status, result.error or result.term or result.log) result = nil else result = metapost.filterclippath(result) diff --git a/tex/context/base/mlib-pdf.lua b/tex/context/base/mlib-pdf.lua index 352070408..28f9c57ca 100644 --- a/tex/context/base/mlib-pdf.lua +++ b/tex/context/base/mlib-pdf.lua @@ -10,6 +10,8 @@ local format, concat, gsub = string.format, table.concat, string.gsub local texsprint = tex.sprint local abs, sqrt, round = math.abs, math.sqrt, math.round +local report_mplib = logs.new("mplib") + local copy_node, write_node = node.copy, node.write local ctxcatcodes = tex.ctxcatcodes @@ -69,7 +71,7 @@ function metapost.flush_literal(d) -- \def\MPLIBtoPDF#1{\ctxlua{metapost.flush_l literal.data = savedliterals[d] write_node(literal) else - logs.report("metapost","problem flushing literal %s",d) + report_mplib("problem flushing literal %s",d) end end diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua index 8b36660d3..f00c99cdb 100644 --- a/tex/context/base/mlib-pps.lua +++ b/tex/context/base/mlib-pps.lua @@ -24,6 +24,8 @@ local ctxcatcodes = tex.ctxcatcodes local trace_textexts = false trackers.register("metapost.textexts", function(v) trace_textexts = v end) +local report_mplib = logs.new("mplib") + colors = colors or { } local rgbtocmyk = colors.rgbtocmyk or function() return 0,0,0,1 end @@ -117,11 +119,11 @@ function metapost.specials.register(str) -- only colors if cc then cc[n] = data else - logs.report("mplib","problematic special: %s (no colordata class %s)", str or "?",class) + report_mplib("problematic special: %s (no colordata class %s)", str or "?",class) end else -- there is some bug to be solved, so we issue a message - logs.report("mplib","problematic special: %s", str or "?") + report_mplib("problematic special: %s", str or "?") end end --~ if match(str,"^%%%%MetaPostOption: multipass") then @@ -248,7 +250,7 @@ function metapost.specials.ps(specification,object,result) -- positions local label = specification x = x - metapost.llx y = metapost.ury - y - -- logs.report("mplib", "todo: position '%s' at (%s,%s) with (%s,%s)",label,x,y,w,h) + -- report_mplib( "todo: position '%s' at (%s,%s) with (%s,%s)",label,x,y,w,h) sprint(ctxcatcodes,format("\\dosavepositionwhd{%s}{0}{%sbp}{%sbp}{%sbp}{%sbp}{0pt}",label,x,y,w,h)) return { }, nil, nil, nil end @@ -472,8 +474,8 @@ function metapost.specials.tf(specification,object) -- metapost.textext_current = metapost.first_box + n - 1 -- end if trace_textexts then - -- logs.report("metapost","first pass: order %s, box %s",n,metapost.textext_current) - logs.report("metapost","first pass: order %s",n) + -- report_mplib("first pass: order %s, box %s",n,metapost.textext_current) + report_mplib("first pass: order %s",n) end -- sprint(ctxcatcodes,format("\\MPLIBsettext{%s}{%s}",metapost.textext_current,str)) sprint(ctxcatcodes,format("\\MPLIBsettext{%s}{%s}",n,str)) @@ -488,8 +490,7 @@ function metapost.specials.ts(specification,object,result,flusher) if n and str then n = tonumber(n) if trace_textexts then - -- logs.report("metapost","second pass: order %s, box %s",n,metapost.textext_current) - logs.report("metapost","second pass: order %s",n) + report_mplib("second pass: order %s",n) end local op = object.path local first, second, fourth = op[1], op[2], op[4] @@ -700,7 +701,7 @@ do local texmess = (dquote/ditto + (1 - etex))^0 local function ignore(s) - logs.report("mplib","ignoring verbatim tex: %s",s) + report_mplib("ignoring verbatim tex: %s",s) return "" end @@ -755,7 +756,7 @@ function metapost.text_texts_data() --~ local box = texbox[i] for n, box in next, textexts do if trace_textexts then - logs.report("metapost","passed data: order %s, box %s",n,i) + report_mplib("passed data: order %s",n) end if box then t[#t+1] = format(text_data_template,n,box.width/factor,n,box.height/factor,n,box.depth/factor) diff --git a/tex/context/base/mlib-pps.mkiv b/tex/context/base/mlib-pps.mkiv index 0a78a8704..a27eb56df 100644 --- a/tex/context/base/mlib-pps.mkiv +++ b/tex/context/base/mlib-pps.mkiv @@ -43,9 +43,13 @@ \def\MPLIBsettext#1% #2% {\dowithnextbox{\ctxlua{metapost.settext(\number\nextbox,#1)}}\hbox} +% \def\MPLIBgettextscaled#1#2#3% why a copy +% {\ctxlua{metapost.gettext(\number\MPtextbox,#1)}% \black has no use here (applied to box) +% \vbox to \zeropoint{\vss\hbox to \zeropoint{\black\scale[sx=#2,sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\hss}}} + \def\MPLIBgettextscaled#1#2#3% why a copy - {\ctxlua{metapost.gettext(\number\MPtextbox,#1)}% - \vbox to \zeropoint{\vss\hbox to \zeropoint{\black\scale[sx=#2,sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\hss}}} + {\ctxlua{metapost.gettext(\number\MPtextbox,#1)}% we need the colorhack or else the color backend does not sync + \vbox to \zeropoint{\vss\hbox to \zeropoint{\scale[\c!sx=#2,\c!sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\forcecolorhack\hss}}} \def\MPLIBgraphictext#1% {\startTEXpage[\c!scale=10000]#1\stopTEXpage} diff --git a/tex/context/base/mlib-run.lua b/tex/context/base/mlib-run.lua index f352e1db1..b961fa02c 100644 --- a/tex/context/base/mlib-run.lua +++ b/tex/context/base/mlib-run.lua @@ -31,6 +31,8 @@ nears zero.
local trace_graphics = false trackers.register("metapost.graphics", function(v) trace_graphics = v end) +local report_mplib = logs.new("mplib") + local format, gsub, match = string.format, string.gsub, string.match local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming @@ -121,20 +123,20 @@ end function metapost.reporterror(result) if not result then - metapost.report("mp error: no result object returned") + report_mplib("mp error: no result object returned") elseif result.status > 0 then local t, e, l = result.term, result.error, result.log if t and t ~= "" then - metapost.report("mp terminal: %s",t) + report_mplib("mp terminal: %s",t) end if e then - metapost.report("mp error: %s",(e=="" and "?") or e) + report_mplib("mp error: %s",(e=="" and "?") or e) end if not t and not e and l then metapost.lastlog = metapost.lastlog .. "\n" .. l - metapost.report("mp log: %s",l) + report_mplib("mp log: %s",l) else - metapost.report("mp error: unknown, no error, terminal or log messages") + report_mplib("mp error: unknown, no error, terminal or log messages") end else return false @@ -142,22 +144,63 @@ function metapost.reporterror(result) return true end -function metapost.checkformat(mpsinput, mpsformat, dirname) - mpsinput = file.addsuffix(mpsinput or "metafun", "mp") - mpsformat = file.removesuffix(file.basename(mpsformat or texconfig.formatname or (tex and tex.formatname) or mpsinput)) - local mpsbase = file.removesuffix(file.basename(mpsinput)) +--~ function metapost.checkformat(mpsinput) +--~ local mpsversion = environment.version or "unset version" +--~ local mpsinput = file.addsuffix(mpsinput or "metafun", "mp") +--~ local mpsformat = file.removesuffix(file.basename(mpsformat or texconfig.formatname or (tex and tex.formatname) or mpsinput)) +--~ local mpsbase = file.removesuffix(file.basename(mpsinput)) +--~ if mpsbase ~= mpsformat then +--~ mpsformat = mpsformat .. "-" .. mpsbase +--~ end +--~ mpsformat = file.addsuffix(mpsformat, "mem") +--~ local pth = file.dirname(texconfig.formatname or "") -- to be made dynamic +--~ if pth ~= "" then +--~ mpsformat = file.join(pth,mpsformat) +--~ end +--~ if lfs.isfile(mpsformat) then +--~ commands.writestatus("mplib","loading '%s' from '%s'", mpsinput, mpsformat) +--~ local mpx, result = metapost.load(mpsformat) +--~ if mpx then +--~ local result = mpx:execute("show mp_parent_version ;") +--~ if not result.log then +--~ metapost.reporterror(result) +--~ else +--~ local version = match(result.log,">> *(.-)[\n\r]") or "unknown" +--~ version = gsub(version,"[\'\"]","") +--~ if version ~= mpsversion then +--~ commands.writestatus("mplib","version mismatch: %s <> %s", version or "unknown", mpsversion) +--~ else +--~ return mpx +--~ end +--~ end +--~ else +--~ commands.writestatus("mplib","error in loading '%s' from '%s'", mpsinput, mpsformat) +--~ metapost.reporterror(result) +--~ end +--~ end +--~ commands.writestatus("mplib","making '%s' into '%s'", mpsinput, mpsformat) +--~ metapost.make(mpsinput,mpsformat,mpsversion) -- somehow return ... fails here +--~ if lfs.isfile(mpsformat) then +--~ commands.writestatus("mplib","loading '%s' from '%s'", mpsinput, mpsformat) +--~ return metapost.load(mpsformat) +--~ else +--~ commands.writestatus("mplib","problems with '%s' from '%s'", mpsinput, mpsformat) +--~ end +--~ end + +function metapost.checkformat(mpsinput) + local mpsversion = environment.version or "unset version" + local mpsinput = file.addsuffix(mpsinput or "metafun", "mp") + local mpsformat = file.removesuffix(file.basename(texconfig.formatname or (tex and tex.formatname) or mpsinput)) + local mpsbase = file.removesuffix(file.basename(mpsinput)) if mpsbase ~= mpsformat then mpsformat = mpsformat .. "-" .. mpsbase end mpsformat = file.addsuffix(mpsformat, "mem") - local pth = dirname or file.dirname(texconfig.formatname or "") - if pth ~= "" then - mpsformat = file.join(pth,mpsformat) - end - local the_version = environment.version or "unset version" - if lfs.isfile(mpsformat) then - commands.writestatus("mplib","loading '%s' from '%s'", mpsinput, mpsformat) - local mpx, result = metapost.load(mpsformat) + local mpsformatfullname = caches.getfirstreadablefile(mpsformat,"formats") or "" + if mpsformatfullname ~= "" then + commands.writestatus("mplib","loading '%s' from '%s'", mpsinput, mpsformatfullname) + local mpx, result = metapost.load(mpsformatfullname) if mpx then local result = mpx:execute("show mp_parent_version ;") if not result.log then @@ -165,24 +208,25 @@ function metapost.checkformat(mpsinput, mpsformat, dirname) else local version = match(result.log,">> *(.-)[\n\r]") or "unknown" version = gsub(version,"[\'\"]","") - if version ~= the_version then - commands.writestatus("mplib","version mismatch: %s <> %s", version or "unknown", the_version) + if version ~= mpsversion then + commands.writestatus("mplib","version mismatch: %s <> %s", version or "unknown", mpsversion) else return mpx end end else - commands.writestatus("mplib","error in loading '%s' from '%s'", mpsinput, mpsformat) + commands.writestatus("mplib","error in loading '%s' from '%s'", mpsinput, mpsformatfullname) metapost.reporterror(result) end end - commands.writestatus("mplib","making '%s' into '%s'", mpsinput, mpsformat) - metapost.make(mpsinput,mpsformat,the_version) -- somehow return ... fails here - if lfs.isfile(mpsformat) then - commands.writestatus("mplib","loading '%s' from '%s'", mpsinput, mpsformat) - return metapost.load(mpsformat) + local mpsformatfullname = caches.setfirstwritablefile(mpsformat,"formats") + commands.writestatus("mplib","making '%s' into '%s'", mpsinput, mpsformatfullname) + metapost.make(mpsinput,mpsformatfullname,mpsversion) -- somehow return ... fails here + if lfs.isfile(mpsformatfullname) then + commands.writestatus("mplib","loading '%s' from '%s'", mpsinput, mpsformatfullname) + return metapost.load(mpsformatfullname) else - commands.writestatus("mplib","problems with '%s' from '%s'", mpsinput, mpsformat) + commands.writestatus("mplib","problems with '%s' from '%s'", mpsinput, mpsformatfullname) end end @@ -258,7 +302,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, local str = (result.term ~= "" and result.term) or "no terminal output" if not str:is_empty() then metapost.lastlog = metapost.lastlog .. "\n" .. str - metapost.report("mp log: %s",str) + report_mplib("mp log: %s",str) end end if result.fig then @@ -266,7 +310,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, end end else - metapost.report("mp error: invalid graphic component %s",i) + report_mplib("mp error: invalid graphic component %s",i) end end else @@ -284,13 +328,13 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, end -- todo: error message if not result then - metapost.report("mp error: no result object returned") + report_mplib("mp error: no result object returned") elseif result.status > 0 then - metapost.report("mp error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error")) + report_mplib("mp error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error")) else if metapost.showlog then metapost.lastlog = metapost.lastlog .. "\n" .. result.term - metapost.report("mp info: %s",result.term or "no-term") + report_mplib("mp info: %s",result.term or "no-term") end if result.fig then converted = metapost.convert(result, trialrun, flusher, multipass, askedfig) @@ -308,11 +352,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, end function metapost.convert() - metapost.report('mp warning: no converter set') -end - -function metapost.report(...) - logs.report("mplib",...) + report_mplib('mp warning: no converter set') end -- handy @@ -326,7 +366,7 @@ function metapost.directrun(formatname,filename,outputformat,astable,mpdata) if not data then logs.simple("unknown file '%s'",filename or "?") else - local mpx = metapost.checkformat(formatname,formatname,caches.setpath("formats")) + local mpx = metapost.checkformat(formatname) if not mpx then logs.simple("unknown format '%s'",formatname or "?") else diff --git a/tex/context/base/mtx-context-arrange.tex b/tex/context/base/mtx-context-arrange.tex index 73431567d..7b764c495 100644 --- a/tex/context/base/mtx-context-arrange.tex +++ b/tex/context/base/mtx-context-arrange.tex @@ -1,4 +1,4 @@ -% engine=luatex +engine=luatex %D \module %D [ file=mtx-context-arrange, diff --git a/tex/context/base/mult-cld.lua b/tex/context/base/mult-cld.lua index 81038b68b..a9fb1ff1c 100644 --- a/tex/context/base/mult-cld.lua +++ b/tex/context/base/mult-cld.lua @@ -51,7 +51,7 @@ end function context.trace(intercept) local normalflush = flush flush = function(c,...) - logs.report("context",concat({...})) + trace_context(concat({...})) if not intercept then normalflush(c,...) end @@ -62,6 +62,8 @@ end trackers.register("context.flush", function(v) if v then context.trace() end end) trackers.register("context.intercept", function(v) if v then context.trace(true) end end) +local trace_context = logs.new("context") + local function writer(k,...) if k then flush(ctxcatcodes,k) @@ -109,9 +111,9 @@ local function writer(k,...) flush(ctxcatcodes,tostring(ti)) -- end elseif typ == "thread" then - logs.report("interfaces","coroutines not supported as we cannot yeild across boundaries") + trace_context("coroutines not supported as we cannot yeild across boundaries") else - logs.report("interfaces","error: %s gets a weird argument %s",k,tostring(ti)) + trace_context("error: %s gets a weird argument %s",k,tostring(ti)) end end end diff --git a/tex/context/base/mult-ini.mkiv b/tex/context/base/mult-ini.mkiv index e20548f9b..493a04cea 100644 --- a/tex/context/base/mult-ini.mkiv +++ b/tex/context/base/mult-ini.mkiv @@ -437,56 +437,74 @@ \def\doignorevalue#1#2#3% {\dosetvalue{#1}{#2}{}} -\def\dosetvalue#1#2% - {\let\c!internal!\c!internal!n - \ifcsname\k!prefix!#2\endcsname - \let\c!internal!\c!internal!y - \@EA\def\csname#1\csname\k!prefix!#2\endcsname%\endcsname - \else - \let\c!internal!\c!internal!y - \@EA\def\csname#1#2%\endcsname - \fi\endcsname} - -\def\dosetevalue#1#2% - {\let\c!internal!\c!internal!n - \ifcsname\k!prefix!#2\endcsname - \let\c!internal!\c!internal!y - \@EA\edef\csname#1\csname\k!prefix!#2\endcsname%\endcsname - \else - \let\c!internal!\c!internal!y - \@EA\edef\csname#1#2%\endcsname - \fi\endcsname} - -\def\dosetgvalue#1#2% - {\let\c!internal!\c!internal!n - \ifcsname\k!prefix!#2\endcsname - \let\c!internal!\c!internal!y - \@EA\gdef\csname#1\csname\k!prefix!#2\endcsname%\endcsname - \else - \let\c!internal!\c!internal!y - \@EA\gdef\csname#1#2%\endcsname - \fi\endcsname} - -\def\dosetxvalue#1#2% - {\let\c!internal!\c!internal!n - \ifcsname\k!prefix!#2\endcsname - \let\c!internal!\c!internal!y - \@EA\xdef\csname#1\csname\k!prefix!#2\endcsname%\endcsname - \else - \let\c!internal!\c!internal!y - \@EA\xdef\csname#1#2%\endcsname - \fi\endcsname} - -\def\docopyvalue#1#2#3% real tricky expansion, quite unreadable - {\let\c!internal!\c!internal!n - \ifcsname\k!prefix!#3\endcsname - \let\c!internal!\c!internal!y - \@EA\def\csname#1\csname\k!prefix!#3\endcsname - \@EA\endcsname\@EA{\csname#2\csname\k!prefix!#3\endcsname\endcsname}% - \else - \let\c!internal!\c!internal!y - \@EA\def\csname#1#3\@EA\endcsname\@EA{\csname#2#3\endcsname}% - \fi} +% \def\dosetvalue#1#2% +% {\let\c!internal!\c!internal!n +% \ifcsname\k!prefix!#2\endcsname +% \let\c!internal!\c!internal!y +% \@EA\def\csname#1\csname\k!prefix!#2\endcsname%\endcsname +% \else +% \let\c!internal!\c!internal!y +% \@EA\def\csname#1#2%\endcsname +% \fi\endcsname} + +% \def\dosetevalue#1#2% +% {\let\c!internal!\c!internal!n +% \ifcsname\k!prefix!#2\endcsname +% \let\c!internal!\c!internal!y +% \@EA\edef\csname#1\csname\k!prefix!#2\endcsname%\endcsname +% \else +% \let\c!internal!\c!internal!y +% \@EA\edef\csname#1#2%\endcsname +% \fi\endcsname} + +% \def\dosetgvalue#1#2% +% {\let\c!internal!\c!internal!n +% \ifcsname\k!prefix!#2\endcsname +% \let\c!internal!\c!internal!y +% \@EA\gdef\csname#1\csname\k!prefix!#2\endcsname%\endcsname +% \else +% \let\c!internal!\c!internal!y +% \@EA\gdef\csname#1#2%\endcsname +% \fi\endcsname} + +% \def\dosetxvalue#1#2% +% {\let\c!internal!\c!internal!n +% \ifcsname\k!prefix!#2\endcsname +% \let\c!internal!\c!internal!y +% \@EA\xdef\csname#1\csname\k!prefix!#2\endcsname%\endcsname +% \else +% \let\c!internal!\c!internal!y +% \@EA\xdef\csname#1#2%\endcsname +% \fi\endcsname} + +% \def\docopyvalue#1#2#3% real tricky expansion, quite unreadable +% {\let\c!internal!\c!internal!n +% \ifcsname\k!prefix!#3\endcsname +% \let\c!internal!\c!internal!y +% \@EA\def\csname#1\csname\k!prefix!#3\endcsname +% \@EA\endcsname\@EA{\csname#2\csname\k!prefix!#3\endcsname\endcsname}% +% \else +% \let\c!internal!\c!internal!y +% \@EA\def\csname#1#3\@EA\endcsname\@EA{\csname#2#3\endcsname}% +% \fi} + +% \def\dosetvalue #1#2{\@EA \def\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +% \def\dosetevalue#1#2{\@EA\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +% \def\dosetgvalue#1#2{\@EA\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +% \def\dosetxvalue#1#2{\@EA\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} + +% \def\docopyvalue#1#2#3% real tricky expansion, quite unreadable +% {\ifcsname\k!prefix!#3\endcsname +% \@EA\def\csname#1\csname\k!prefix!#3\endcsname\@EA\endcsname\@EA{\csname#2\csname\k!prefix!#3\endcsname\endcsname}% +% \else +% \@EA\def\csname#1#3\@EA\endcsname\@EA{\csname#2#3\endcsname}% +% \fi} + +\def\dosetvalue #1#2{\@EA \def\csname#1#2\endcsname} +\def\dosetevalue #1#2{\@EA\edef\csname#1#2\endcsname} +\def\dosetgvalue #1#2{\@EA\gdef\csname#1#2\endcsname} +\def\dosetxvalue #1#2{\@EA\xdef\csname#1#2\endcsname} +\def\docopyvalue#1#2#3{\@EA \def\csname#1#3\@EA\endcsname\@EA{\csname#2#3\endcsname}} %D We can now redefine some messages that will be %D introduced in the multi||lingual system module. @@ -744,22 +762,26 @@ %D user constants (keywords) become system variables %D \stopnarrower -%D Anno 2003 I've forgotten why the \type {\c!internal} is -%D still in there; it's probably a left over from the time that +%D The \type {\c!internal} is a left over from the time that %D the user interface documents were not using a specification %D alongside a keyword specification but used a shared file in %D which case we need to go in both directions. -\let\c!internal!y \string -\def\c!internal!n {-} -\let\c!internal! \c!internal!y - % temporary mkiv hack (we can best just store the whole table in memory) +% \let\c!internal!y \string +% \def\c!internal!n {-} +% \let\c!internal! \c!internal!y + +% \def\setinterfaceconstant#1#2% +% {\ctxlua{interfaces.setconstant("#1","#2")}% +% \setvalue{\c!prefix!#1}{\c!internal!#1}% +% \setvalue{\k!prefix!#2}{#1}} + \def\setinterfaceconstant#1#2% {\ctxlua{interfaces.setconstant("#1","#2")}% - \setvalue{\c!prefix!#1}{\c!internal!#1}% - \setvalue{\k!prefix!#2}{#1}} + %\setvalue{\k!prefix!#2}{#1}% + \setvalue{\c!prefix!#1}{#1}} \def\setinterfacevariable#1#2% {\ctxlua{interfaces.setvariable("#1","#2")}% diff --git a/tex/context/base/node-dum.lua b/tex/context/base/node-dum.lua index f39a0873f..9483e51fc 100644 --- a/tex/context/base/node-dum.lua +++ b/tex/context/base/node-dum.lua @@ -6,7 +6,20 @@ if not modules then modules = { } end modules ['node-dum'] = { license = "see context related readme files" } -nodes = nodes or { } +nodes = nodes or { } +fonts = fonts or { } +attributes = attributes or { } + +local traverse_id = node.traverse_id +local free_node = node.free +local remove_node = node.remove +local new_node = node.new + +local glyph = node.id('glyph') + +-- fonts + +local fontdata = fonts.ids or { } function nodes.simple_font_handler(head) -- lang.hyphenate(head) @@ -17,3 +30,98 @@ function nodes.simple_font_handler(head) head = node.kerning(head) return head end + +if tex.attribute[0] ~= 0 then + + texio.write_nl("log","!") + texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be") + texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special") + texio.write_nl("log","! purposed so setting them at the TeX end might break the font handler.") + texio.write_nl("log","!") + + tex.attribute[0] = 0 -- else no features + +end + +nodes.protect_glyphs = node.protect_glyphs +nodes.unprotect_glyphs = node.unprotect_glyphs + +function nodes.process_characters(head) + local usedfonts, done, prevfont = { }, false, nil + for n in traverse_id(glyph,head) do + local font = n.font + if font ~= prevfont then + prevfont = font + local used = usedfonts[font] + if not used then + local tfmdata = fontdata[font] + if tfmdata then + local shared = tfmdata.shared -- we need to check shared, only when same features + if shared then + local processors = shared.processes + if processors and #processors > 0 then + usedfonts[font] = processors + done = true + end + end + end + end + end + end + if done then + for font, processors in next, usedfonts do + for i=1,#processors do + local h, d = processors[i](head,font,0) + head, done = h or head, done or d + end + end + end + return head, true +end + +-- helper + +function nodes.kern(k) + local n = new_node("kern",1) + n.kern = k + return n +end + +function nodes.remove(head, current, free_too) + local t = current + head, current = remove_node(head,current) + if t then + if free_too then + free_node(t) + t = nil + else + t.next, t.prev = nil, nil + end + end + return head, current, t +end + +function nodes.delete(head,current) + return nodes.remove(head,current,true) +end + +nodes.before = node.insert_before +nodes.after = node.insert_after + +-- attributes + +attributes.unsetvalue = -0x7FFFFFFF + +local numbers, last = { }, 127 + +function attributes.private(name) + local number = numbers[name] + if not number then + if last < 255 then + last = last + 1 + end + number = last + numbers[name] = number + end + return number +end diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua index c6e3be448..aabcb0db0 100644 --- a/tex/context/base/node-fin.lua +++ b/tex/context/base/node-fin.lua @@ -170,7 +170,7 @@ end local insert_node_before = node.insert_before local insert_node_after = node.insert_after -local nsdata, nsdone, nsforced, nsselector, nstrigger +local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger local current, current_selector, done = 0, 0, false -- nb, stack has a local current ! function states.initialize(namespace,attribute,head) diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua index b0d073425..594cfc1a1 100644 --- a/tex/context/base/node-fnt.lua +++ b/tex/context/base/node-fnt.lua @@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['node-fnt'] = { license = "see context related readme files" } +if not context then os.exit() end -- generic function in node-dum + local next, type = next, type local trace_characters = false trackers.register("nodes.characters", function(v) trace_characters = v end) @@ -33,20 +35,6 @@ local fontdata = fonts.ids -- happen often; we could consider processing sublists but that might need mor -- checking later on; the current approach also permits variants -if tex.attribute[0] < 0 then - - texio.write_nl("log","!") - texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be") - texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special") - texio.write_nl("log","! purposed so setting them at the TeX end might break the font handler.") - texio.write_nl("log","!") - - tex.attribute[0] = 0 -- else no features - -end - --- this will be redone and split in a generic one and a context one - function nodes.process_characters(head) -- either next or not, but definitely no already processed list starttiming(nodes) @@ -100,16 +88,17 @@ function nodes.process_characters(head) prevattr = attr end end + -- we could combine these and just make the attribute nil if u == 1 then local font, processors = next(usedfonts) local n = #processors if n > 0 then - local h, d = processors[1](head,font,false) + local h, d = processors[1](head,font,0) head, done = h or head, done or d if n > 1 then for i=2,n do - local h, d = processors[i](head,font,false) + local h, d = processors[i](head,font,0) head, done = h or head, done or d end end @@ -117,11 +106,11 @@ function nodes.process_characters(head) elseif u > 0 then for font, processors in next, usedfonts do local n = #processors - local h, d = processors[1](head,font,false) + local h, d = processors[1](head,font,0) head, done = h or head, done or d if n > 1 then for i=2,n do - local h, d = processors[i](head,font,false) + local h, d = processors[i](head,font,0) head, done = h or head, done or d end end @@ -162,46 +151,5 @@ function nodes.process_characters(head) return head, true end -if node.protect_glyphs then - - nodes.protect_glyphs = node.protect_glyphs - nodes.unprotect_glyphs = node.unprotect_glyphs - -else do - - -- initial value subtype : X000 0001 = 1 = 0x01 = char - -- - -- expected before linebreak : X000 0000 = 0 = 0x00 = glyph - -- X000 0010 = 2 = 0x02 = ligature - -- X000 0100 = 4 = 0x04 = ghost - -- X000 1010 = 10 = 0x0A = leftboundary lig - -- X001 0010 = 18 = 0x12 = rightboundary lig - -- X001 1010 = 26 = 0x1A = both boundaries lig - -- X000 1100 = 12 = 0x1C = leftghost - -- X001 0100 = 20 = 0x14 = rightghost - - function nodes.protect_glyphs(head) - local done = false - for g in traverse_id(glyph,head) do - local s = g.subtype - if s == 1 then - done, g.subtype = true, 256 - elseif s <= 256 then - done, g.subtype = true, 256 + s - end - end - return done - end - - function nodes.unprotect_glyphs(head) - local done = false - for g in traverse_id(glyph,head) do - local s = g.subtype - if s > 256 then - done, g.subtype = true, s - 256 - end - end - return done - end - -end end +nodes.protect_glyphs = node.protect_glyphs +nodes.unprotect_glyphs = node.unprotect_glyphs diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua index 36e240238..8f507e9b1 100644 --- a/tex/context/base/node-ini.lua +++ b/tex/context/base/node-ini.lua @@ -17,54 +17,6 @@ local utf = unicode.utf8 local next, type = next, type local format, concat, match, utfchar = string.format, table.concat, string.match, utf.char -local chardata = characters and characters.data - ---[[ldx-- -We start with a registration system for atributes so that we can use the -symbolic names later on.
---ldx]]-- - -attributes = attributes or { } - -attributes.names = attributes.names or { } -attributes.numbers = attributes.numbers or { } -attributes.list = attributes.list or { } -attributes.unsetvalue = -0x7FFFFFFF - -storage.register("attributes/names", attributes.names, "attributes.names") -storage.register("attributes/numbers", attributes.numbers, "attributes.numbers") -storage.register("attributes/list", attributes.list, "attributes.list") - -local names, numbers, list = attributes.names, attributes.numbers, attributes.list - -function attributes.define(name,number) -- at the tex end - if not numbers[name] then - numbers[name], names[number], list[number] = number, name, { } - end -end - ---[[ldx-- -We can use the attributes in the range 127-255 (outside user space). These
-are only used when no attribute is set at the \TEX\ end which normally
-happens in
Access to nodes is what gives
At some point we ran into a problem that the glue specification of the zeropoint dimension was overwritten when adapting a glue spec @@ -225,33 +231,16 @@ and hide it for the user. And yes, LuaTeX now gives a warning as well.
]]-- -if tex.luatexversion > 51 then - - function nodes.writable_spec(n) - local spec = n.spec - if not spec then - spec = copy_node(glue_spec) - n.spec = spec - elseif not spec.writable then - spec = copy_node(spec) - n.spec = spec - end - return spec - end - -else - - function nodes.writable_spec(n) - local spec = n.spec - if not spec then - spec = copy_node(glue_spec) - else - spec = copy_node(spec) - end +function nodes.writable_spec(n) + local spec = n.spec + if not spec then + spec = copy_node(glue_spec) + n.spec = spec + elseif not spec.writable then + spec = copy_node(spec) n.spec = spec - return spec end - + return spec end local cache = { } @@ -300,3 +289,5 @@ end) -- \topofboxstack statistics.register("node memory usage", function() -- comes after cleanup ! return status.node_mem_usage end) + +lua.registerfinalizer(nodes.cleanup_reserved) diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua index 9dd89bcda..74a730893 100644 --- a/tex/context/base/node-rul.lua +++ b/tex/context/base/node-rul.lua @@ -8,6 +8,8 @@ if not modules then modules = { } end modules ['node-rul'] = { -- this will go to an auxiliary module -- beware: rules now have a dir field +-- +-- todo: make robust for layers ... order matters local glyph = node.id("glyph") local disc = node.id("disc") @@ -45,6 +47,8 @@ end local trace_ruled = false trackers.register("nodes.ruled", function(v) trace_ruled = v end) +local report_ruled = logs.new("ruled") + local floor = math.floor local n_tostring, n_tosequence = nodes.ids_tostring, nodes.tosequence @@ -86,6 +90,9 @@ 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 +-- +-- this one needs to take layers into account (i.e. we need a list of +-- critical attributes) local function process_words(attribute,data,flush,head,parent) -- we have hlistdir and local dir local n = head @@ -172,8 +179,14 @@ function nodes.rules.define(settings) texwrite(#data) end +local a_viewerlayer = attributes.private("viewerlayer") + local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but acceptable for this purpose -- check for f and l +if f.id ~= glyph then + -- saveguard ... we need to deal with rules and so (math) + return head +end local r, m if true then f, l = strip_range(f,l) @@ -181,7 +194,7 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a 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 = d.method, d.offset, d.continue, d.dy, d.rulethickness, d.unit, d.order, d.max, d.ma, d.ca, d.ta - local e = dimenfactor(unit,fontdata[f.font]) + local e = dimenfactor(unit,fontdata[f.font]) -- what if no glyph node local colorspace = (ma > 0 and ma) or has_attribute(f,a_colorspace) or 1 local color = (ca > 0 and ca) or has_attribute(f,a_color) local transparency = (ta > 0 and ta) or has_attribute(f,a_transparency) @@ -200,6 +213,12 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a local ht = (offset+(i-1)*dy+rulethickness)*e - m local dp = -(offset+(i-1)*dy-rulethickness)*e + m local r = new_rule(w,ht,dp) + local v = has_attribute(f,a_viewerlayer) +-- quick hack +if v then + set_attribute(r,a_viewerlayer,v) +end +-- if color then set_attribute(r,a_colorspace,colorspace) set_attribute(r,a_color,color) @@ -213,11 +232,11 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a insert_after(head,k,r) l = r else - head, _ = insert_before(head,f,r) + head = insert_before(head,f,r) insert_after(head,r,k) end if trace_ruled then - logs.report("ruled", "level: %s, width: %i, height: %i, depth: %i, nodes: %s, text: %s", + report_ruled("level: %s, width: %i, height: %i, depth: %i, nodes: %s, text: %s", level,w,ht,dp,n_tostring(f,l),n_tosequence(f,l,true)) -- level,r.width,r.height,r.depth,n_tostring(f,l),n_tosequence(f,l,true)) end @@ -240,6 +259,8 @@ end local trace_shifted = false trackers.register("nodes.shifted", function(v) trace_shifted = v end) +local report_shifted = logs.new("shifted") + local a_shifted = attributes.private('shifted') nodes.shifts = nodes.shifts or { } @@ -274,7 +295,7 @@ local function flush_shifted(head,first,last,data,level,parent,strip) -- not tha 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)) + 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-spl.lua b/tex/context/base/node-spl.lua new file mode 100644 index 000000000..d6ecdfa13 --- /dev/null +++ b/tex/context/base/node-spl.lua @@ -0,0 +1,589 @@ +if not modules then modules = { } end modules ['node-spl'] = { + version = 1.001, + comment = "companion to node-spl.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This module is dedicated to the oriental tex project and for +-- the moment is too experimental to be publicly supported. +-- +-- We could cache solutions: say that we store the featureset and +-- all 'words' -> replacement ... so we create a large solution +-- database (per font) +-- +-- This module can be optimized by using a dedicated dynamics handler +-- but I'll only do that when the rest of the code is stable. +-- +-- Todo: bind setups to paragraph. + +local gmatch, concat, format, remove = string.gmatch, table.concat, string.format, table.remove +local next, tostring, tonumber = next, tostring, tonumber +local utfchar = utf.char +local random = math.random +local variables = interfaces.variables + +local trace_split = false trackers.register("parbuilders.solutions.splitters.splitter", function(v) trace_split = v end) +local trace_optimize = false trackers.register("parbuilders.solutions.splitters.optimizer", function(v) trace_optimize = v end) +local trace_colors = false trackers.register("parbuilders.solutions.splitters.colors", function(v) trace_colors = v end) +local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end) + +local report_fonts = logs.new("fonts") +local report_splitter = logs.new("splitter") +local report_optimizer = logs.new("optimizer") + +local glyph = node.id("glyph") +local glue = node.id("glue") +local kern = node.id("kern") +local disc = node.id("disc") +local hlist = node.id("hlist") +local whatsit = node.id("whatsit") + +local find_node_tail = node.tail or node.slide +local free_node = node.free +local free_nodelist = node.flush_list +local has_attribute = node.has_attribute +local set_attribute = node.set_attribute +local new_node = node.new +local copy_node = node.copy +local copy_nodelist = node.copy_list +local traverse_nodes = node.traverse +local traverse_ids = node.traverse_id +local protect_nodes = node.protect_glyphs +local hpack_nodes = node.hpack +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local repack_hlist = nodes.repack_hlist + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local process_characters = nodes.process_characters +local inject_kerns = nodes.inject_kerns +local set_dynamics = fonts.otf.set_dynamics +local fontdata = fonts.ids + +parbuilders.solutions = parbuilders.solutions or { } +parbuilders.solutions.splitters = parbuilders.solutions.splitters or { } + +local splitters = parbuilders.solutions.splitters + +local preroll = true +local variant = "normal" +local split = attributes.private('splitter') +local cache = { } +local solutions = { } -- attribute sets +local variants = { } +local max_less = 0 +local max_more = 0 +local criterium = 0 +local randomseed = nil +local optimize = nil -- set later + +function splitters.setup(setups) + local method = aux.settings_to_hash(setups.method or "") + if method[variables.preroll] then + preroll = true + else + preroll = false + end + for k, v in next, method do + if variants[k] then + optimize = variants[k] + end + end + randomseed = tonumber(setups.randomseed) + criterium = tonumber(setups.criterium) or criterium +end + +local function convert(featuresets,name,set,what) + local list, numbers = set[what], { } + if list then + local setups = fonts.define.specify.context_setups + for i=1,#list do + local feature = list[i] + local fs = featuresets[feature] + local fn = fs and fs.number + if not fn then + -- fall back on global features + fs = setups[feature] + fn = fs and fs.number + end + if fn then + numbers[#numbers+1] = fn + if trace_goodies or trace_optimize then + report_fonts("solution %s of '%s' uses feature '%s' with number %s",i,name,feature,fn) + end + else + report_fonts("solution %s has an invalid feature reference '%s'",i,name,tostring(feature)) + end + end + return #numbers > 0 and numbers + end +end + +local function initialize(goodies) + local solutions = goodies.solutions + if solutions then + local featuresets = goodies.featuresets + local goodiesname = goodies.name + if trace_goodies or trace_optimize then + report_fonts("checking solutions in '%s'",goodiesname) + end + for name, set in next, solutions do + set.less = convert(featuresets,name,set,"less") + set.more = convert(featuresets,name,set,"more") + end + end +end + +fonts.goodies.register("solutions",initialize) + +function splitters.define(name,parameters) + local setups = fonts.define.specify.context_setups + local settings = aux.settings_to_hash(parameters) -- todo: interfacing + local goodies, solution, less, more = settings.goodies, settings.solution, settings.less, settings.more + local less_set, more_set + local l = less and aux.settings_to_array(less) + local m = more and aux.settings_to_array(more) + if goodies then + goodies = fonts.goodies.get(goodies) -- also in tfmdata + if goodies then + local featuresets = goodies.featuresets + local solution = solution and goodies.solutions[solution] + if l and #l > 0 then + less_set = convert(featuresets,name,settings,"less") -- take from settings + else + less_set = solution and solution.less -- take from goodies + end + if m and #m > 0 then + more_set = convert(featuresets,name,settings,"more") -- take from settings + else + more_set = solution and solution.more -- take from goodies + end + end + else + if l then + for i=1,#l do + local ss = setups[l[i]] + if ss then + less_set[#less_set+1] = ss.number + end + end + end + if m then + for i=1,#m do + local ss = setups[m[i]] + if ss then + more_set[#more_set+1] = ss.number + end + end + end + end + if trace_optimize then + report_fonts("defining solutions '%s', less: '%s', more: '%s'",name,concat(less_set or {}," "),concat(more_set or {}," ")) + end + solutions[#solutions+1] = { + solution = solution, + less = less_set or { }, + more = more_set or { }, + settings = settings, -- for tracing + } +--~ print(table.serialize(solutions[#solutions])) + tex.write(#solutions) +end + +local user_node_one = nodes.register(new_node("whatsit",44)) user_node_one.user_id, user_node_one.type = 1, 100 +local user_node_two = nodes.register(new_node("whatsit",44)) user_node_two.user_id, user_node_two.type = 2, 100 +local text_node_trt = nodes.register(new_node("whatsit", 7)) text_node_trt.dir = "+TRT" + +local fcs = (fonts.color and fonts.color.set) or function() end + +local nofwords, noftries, nofadapted, nofkept, nofparagraphs = 0, 0, 0, 0, 0 + +function splitters.split(head) + -- quite fast + local current, done, rlmode, start, stop, attribute = head, false, false, nil, nil, 0 + cache, max_less, max_more = { }, 0, 0 + local function flush() -- we can move this + local font = start.font + local last = stop.next + local list = last and copy_nodelist(start,last) or copy_nodelist(start) + local n = #cache + 1 + local user_one = copy_node(user_node_one) + local user_two = copy_node(user_node_two) + user_one.value, user_two.value = n, n + head, start = insert_node_before(head,start,user_one) + insert_node_after(head,stop,user_two) + if rlmode == "TRT" or rlmode == "+TRT" then + local dirnode = copy_node(text_node_trt) + list.prev = dirnode + dirnode.next = list + list = dirnode + end + local c = { + original = list, + attribute = attribute, + direction = rlmode, + font = font + } + if trace_split then + report_splitter( "cached %4i: font: %s, attribute: %s, word: %s, direction: %s", n, + font, attribute, nodes.list_to_utf(list,true), rlmode) + end + cache[n] = c + local solution = solutions[attribute] + local l, m = #solution.less, #solution.more + if l > max_less then max_less = l end + if m > max_more then max_more = m end + start, stop, done = nil, nil, true + end + while current do + local id = current.id + if id == glyph and current.subtype < 255 then + local a = has_attribute(current,split) + if not a then + start, stop = nil, nil + elseif not start then + start, stop, attribute = current, current, a + elseif a ~= attribute then + start, stop = nil, nil + else + stop = current + end + current = current.next + elseif id == disc then + start, stop, current = nil, nil, current.next + elseif id == whatsit then + if start then + flush() + end + local subtype = current.subtype + if subtype == 7 or subtype == 6 then + rlmode = current.dir + end + current = current.next + else + if start then + flush() + end + current = current.next + end + end + if start then + flush() + end + nofparagraphs = nofparagraphs + 1 + nofwords = nofwords + #cache + return head, done +end + +local function collect_words(list) + local words, word = { }, nil + for current in traverse_ids(whatsit,list) do + if current.subtype == 44 then + local user_id = current.user_id + if user_id == 1 then + word = { current.value, current, current } + words[#words+1] = word + elseif user_id == 2 then + word[3] = current + end + end + end + return words -- check for empty (elsewhere) +end + +-- we could avoid a hpack but hpack is not that slow + +local function doit(word,list,best,width,badness,line,set,listdir) + local changed = 0 + local n = word[1] + local found = cache[n] + if found then + local original, attribute, direction = found.original, found.attribute, found.direction + local solution = solutions[attribute] + local features = solution and solution[set] + if features then + local featurenumber = features[best] -- not ok probably + if featurenumber then + noftries = noftries + 1 + local first = copy_nodelist(original) + if not trace_colors then + for n in traverse_nodes(first) do -- maybe fast force so no attr needed + set_attribute(n,0,featurenumber) -- this forces dynamics + end + elseif set == "less" then + for n in traverse_nodes(first) do + fcs(n,"font:isol") + set_attribute(n,0,featurenumber) + end + else + for n in traverse_nodes(first) do + fcs(n,"font:medi") + set_attribute(n,0,featurenumber) + end + end + local font = found.font + local dynamics = found.dynamics + if not dynamics then -- we cache this + dynamics = fontdata[font].shared.dynamics + found.dynamics = dynamics + end + local processors = found[featurenumber] + if not processors then -- we cache this too + processors = set_dynamics(font,dynamics,featurenumber) + found[featurenumber] = processors + end + for i=1,#processors do -- often more than 1 + first = processors[i](first,font,featurenumber) -- we can make a special one that already passes the dynamics + end + first = inject_kerns(first) + local h = word[2].next -- head of current word + local t = word[3].prev -- tail of current word + if first.id == whatsit then + local temp = first + first = first.next + free_node(temp) + end + local last = find_node_tail(first) + -- replace [u]h->t by [u]first->last + local next, prev = t.next, h.prev + prev.next, first.prev = first, prev + if next then + last.next, next.prev = next, last + end + -- check new pack + local temp, b = repack_hlist(list,width,'exactly',listdir) + if b > badness then + if trace_optimize then + report_optimizer("line %s, badness before: %s, after: %s, criterium: %s -> quit",line,badness,b,criterium) + end + -- remove last insert + prev.next, h.prev = h, prev + if next then + t.next, next.prev = next, t + else + t.next = nil + end + last.next = nil + free_nodelist(first) + else + if trace_optimize then + report_optimizer("line %s, badness before: %s, after: %s, criterium: %s -> continue",line,badness,b,criterium) + end + -- free old h->t + t.next = nil + free_nodelist(h) + changed, badness = changed + 1, b + end + if b <= criterium then + return true, changed + end + end + end + end + return false, changed +end + +-- We repeat some code but adding yet another layer of indirectness is not +-- making things better. + +variants[variables.normal] = function(words,list,best,width,badness,line,set,listdir) + local changed = 0 + for i=1,#words do + local done, c = doit(words[i],list,best,width,badness,line,set,listdir) + changed = changed + c + if done then + break + end + end + if changed > 0 then + nofadapted = nofadapted + 1 + -- todo: get rid of pack when ok because we already have packed and we only need the last b + local list, b = repack_hlist(list,width,'exactly',listdir) + return list, true, changed, b -- badness + else + nofkept = nofkept + 1 + return list, false, 0, badness + end +end + +variants[variables.reverse] = function(words,list,best,width,badness,line,set,listdir) + local changed = 0 + for i=#words,1,-1 do + local done, c = doit(words[i],list,best,width,badness,line,set,listdir) + changed = changed + c + if done then + break + end + end + if changed > 0 then + nofadapted = nofadapted + 1 + -- todo: get rid of pack when ok because we already have packed and we only need the last b + local list, b = repack_hlist(list,width,'exactly',listdir) + return list, true, changed, b -- badness + else + nofkept = nofkept + 1 + return list, false, 0, badness + end +end + +variants[variables.random] = function(words,list,best,width,badness,line,set,listdir) + local changed = 0 + while #words > 0 do + local done, c = doit(remove(words,random(1,#words)),list,best,width,badness,line,set,listdir) + changed = changed + c + if done then + break + end + end + if changed > 0 then + nofadapted = nofadapted + 1 + -- todo: get rid of pack when ok because we already have packed and we only need the last b + local list, b = repack_hlist(list,width,'exactly',listdir) + return list, true, changed, b -- badness + else + nofkept = nofkept + 1 + return list, false, 0, badness + end +end + +optimize = variants.normal -- the default + +local function show_quality(current,what,line) + local set = current.glue_set + local sign = current.glue_sign + local order = current.glue_order + local amount = set * ((sign == 2 and -1) or 1) + report_optimizer("line %s, %s, amount %s, set %s, sign %s (%s), order %s",line,what,amount,set,sign,how,order) +end + +function splitters.optimize(head) + local nc = #cache + if nc > 0 then + starttiming(splitters) + local listdir = nil -- todo ! ! ! + if randomseed then + math.setrandomseedi(randomseed) + randomseed = nil + end + local line = 0 + local tex_hbadness, tex_hfuzz = tex.hbadness, tex.hfuzz + tex.hbadness, tex.hfuzz = 10000, number.maxdimen + if trace_optimize then + report_optimizer("preroll: %s, variant: %s, preroll criterium: %s, cache size: %s", + tostring(preroll),variant,criterium,nc) + end + for current in traverse_ids(hlist,head) do + -- report_splitter("before: [%s] => %s",current.dir,nodes.tosequence(current.list,nil)) + line = line + 1 + local sign, dir, list, width = current.glue_sign, current.dir, current.list, current.width + local temp, badness = repack_hlist(list,width,'exactly',dir) -- it would be nice if the badness was stored in the node + if badness > 0 then + if sign == 0 then + if trace_optimize then + report_optimizer("line %s, badness %s, okay",line,badness) + end + else + local set, max + if sign == 1 then + if trace_optimize then + report_optimizer("line %s, badness %s, underfull, trying more",line,badness) + end + set, max = "more", max_more + else + if trace_optimize then + report_optimizer("line %s, badness %s, overfull, trying less",line,badness) + end + set, max = "less", max_less + end + -- we can keep the best variants + local lastbest, lastbadness = nil, badness + if preroll then + local bb, base + for i=1,max do + if base then + free_nodelist(base) + end + base = copy_nodelist(list) + local words = collect_words(base) -- beware: words is adapted + for j=i,max do + local temp, done, changes, b = optimize(words,base,j,width,badness,line,set,dir) + base = temp + if trace_optimize then + report_optimizer("line %s, alternative: %s.%s, changes: %s, badness %s",line,i,j,changes,b) + end + bb = b + if b <= criterium then + break + end + -- if done then + -- break + -- end + end + if bb and bb > criterium then -- needs checking + if not lastbest then + lastbest, lastbadness = i, bb + elseif bb > lastbadness then + lastbest, lastbadness = i, bb + end + else + break + end + end + free_nodelist(base) + end + local words = collect_words(list) + for best=lastbest or 1,max do + local temp, done, changes, b = optimize(words,list,best,width,badness,line,set,dir) + current.list = temp + if trace_optimize then + report_optimizer("line %s, alternative: %s, changes: %s, badness %s",line,best,changes,b) + end + if done then + if b <= criterium then -- was == 0 + protect_nodes(list) + break + end + end + end + end + else + if trace_optimize then + report_optimizer("line %s, not bad enough",line) + end + end + -- we pack inside the outer hpack and that way keep the original wd/ht/dp as bonus + current.list = hpack_nodes(current.list,width,'exactly',listdir) + -- report_splitter("after: [%s] => %s",temp.dir,nodes.tosequence(temp.list,nil)) + end + for i=1,nc do + local ci = cache[i] + free_nodelist(ci.original) + end + cache = { } + tex.hbadness, tex.hfuzz = tex_hbadness, tex_hfuzz + stoptiming(splitters) + end +end + +statistics.register("optimizer statistics", function() + if nofwords > 0 then + local elapsed = statistics.elapsedtime(splitters) + local average = noftries/elapsed + return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %0.3f seconds used, %s adapted, %0.1f lines per second", + nofwords,nofparagraphs,noftries,nofadapted+nofkept,elapsed,nofadapted,average) + end +end) + +function splitters.enable() + tasks.enableaction("processors", "parbuilders.solutions.splitters.split") + tasks.enableaction("finalizers", "parbuilders.solutions.splitters.optimize") +end + +function splitters.disable() + tasks.disableaction("processors", "parbuilders.solutions.splitters.split") + tasks.disableaction("finalizers", "parbuilders.solutions.splitters.optimize") +end diff --git a/tex/context/base/node-spl.mkiv b/tex/context/base/node-spl.mkiv new file mode 100644 index 000000000..af98f45c7 --- /dev/null +++ b/tex/context/base/node-spl.mkiv @@ -0,0 +1,114 @@ +%D \module +%D [ file=node-spl, +%D version=2009.05.19, +%D title=\CONTEXT\ Node Macros, +%D subtitle=Splitters, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright=PRAGMA] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Node Support / Splitters} + +\registerctxluafile{node-spl}{1.001} + +\definesystemattribute[splitter] \chardef\splitterattribute \dogetattributeid{splitter} + +%D This module is specially made for the oriental \TEX\ project. The working is as +%D follows (and tuned for fonts like Idris' Husayni. The following method came to +%D my mind after a couple of Skype sessions with Idris while working on the rough +%D edges of the Husayni font and playing with font dynamics. +%D +%D \startitemize[packed] +%D +%D \item We define a couple of features sets, some can have stylistics variants +%D that result in the same words getting a different width. Normally this +%D happens in a goodies file. +%D +%D \item We group such features in a solution set. A solutionset can be enabled +%D by setting an attribute. +%D +%D \item For each paragraph we identify words that get this set applied. We replace +%D these words by a user node that refers to the original. +%D +%D \item For each word we apply the features to a copy that we associate with this +%D original word. +%D +%D \item At the end we have a paragraph (node list) with user nodes that point to a +%D cache that has originals and processed variants. +%D +%D \item When the paragraph is broken into lines we optimize the spacing by +%D substituting variants. +%D +%D \stopitemize +%D +%D This approach permits us to use a dedicated paragraph builder, one that treats +%D the user nodes special and takes the alternatives into account. +%D +%D Currently we assume only one solution being active. Maybe some day I'll support +%D a mixture. This is only one way of optimizing and after several experiments this +%D one was chosen as testcase. It took quite some experiments (and time) to get thus +%D far. +%D +%D The is experimental code for the Oriental \TEX\ project and aspects of it might +%D change. +%D +%D \starttyping +%D \setupfontsolutions[method={random,preroll},criterium=1,randomseed=101] +%D +%D \definefontsolution % actually only the last run needs to be done this way +%D [FancyHusayni] +%D [goodies=husayni, +%D solution=experimental] +%D +%D \definedfont[husayni*husayni-default at 24pt] +%D \setupinterlinespace[line=36pt] +%D \righttoleft +%D \enabletrackers[parbuilders.solutions.splitters.colors] +%D \setfontsolution[FancyHusayni] +%D alb alb alb \par +%D \resetfontsolution +%D \disabletrackers[parbuilders.solutions.splitters.colors] +%D \stoptyping + +\unprotect + +\newtoks\everysetupfontsolutions + +\unexpanded\def\definefontsolution + {\dodoubleargument\dodefinefontsolution} + +\def\dodefinefontsolution[#1][#2]% we could set the attribute at the lua end + {\setxvalue{\??fu:#1}{\attribute\splitterattribute\ctxlua{parbuilders.solutions.splitters.define("#1","#2")}\relax}} + +\unexpanded\def\setfontsolution[#1]% + {\ctxlua{parbuilders.solutions.splitters.enable()}% + \csname\??fu:#1\endcsname} + +\unexpanded\def\resetfontsolution + {\ctxlua{parbuilders.solutions.splitters.disable()}% + \attribute\splitterattribute\attributeunsetvalue} + +\letvalue{\??fu:\v!reset}\resetfontsolution + +\unexpanded\def\setupfontsolutions[#1]% + {\getparameters[\??fu][#1]% + \the\everysetupfontsolutions} + +\appendtoks + \ctxlua{parbuilders.solutions.splitters.setup { + method = "\@@fumethod", + criterium = "\@@fucriterium", + }}% +\to \everysetupfontsolutions + +% We initialize this module at the \LUA\ end. +% +% \setupfontsolutions +% [\c!method={\v!normal,preroll}, +% \c!criterium=0] + +\protect diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua index 5acd70baf..880b21b81 100644 --- a/tex/context/base/node-tra.lua +++ b/tex/context/base/node-tra.lua @@ -16,6 +16,8 @@ local format, match, concat, rep, utfchar = string.format, string.match, table.c local ctxcatcodes = tex.ctxcatcodes +local report_nodes = logs.new("nodes") + fonts = fonts or { } fonts.tfm = fonts.tfm or { } fonts.ids = fonts.ids or { } @@ -380,13 +382,13 @@ end function nodes.report(t,done) if done then if status.output_active then - logs.report("nodes","output, changed, %s nodes",nodes.count(t)) + report_nodes("output, changed, %s nodes",nodes.count(t)) else texio.write("nodes","normal, changed, %s nodes",nodes.count(t)) end else if status.output_active then - logs.report("nodes","output, unchanged, %s nodes",nodes.count(t)) + report_nodes("output, unchanged, %s nodes",nodes.count(t)) else texio.write("nodes","normal, unchanged, %s nodes",nodes.count(t)) end diff --git a/tex/context/base/node-tsk.lua b/tex/context/base/node-tsk.lua index 206b4a266..66f691ec8 100644 --- a/tex/context/base/node-tsk.lua +++ b/tex/context/base/node-tsk.lua @@ -10,6 +10,8 @@ if not modules then modules = { } end modules ['node-tsk'] = { local trace_tasks = false trackers.register("tasks.creation", function(v) trace_tasks = v end) +local report_tasks = logs.new("tasks") + tasks = tasks or { } tasks.data = tasks.data or { } @@ -87,7 +89,7 @@ end function tasks.showactions(name,group,action,where,kind) local data = tasks.data[name] if data then - logs.report("nodes","task %s, list:\n%s",name,sequencer.nodeprocessor(data.list)) + report_tasks("task %s, list:\n%s",name,sequencer.nodeprocessor(data.list)) end end @@ -118,7 +120,7 @@ function tasks.actions(name,n) -- we optimize for the number or arguments (no .. if not runner then created = created + 1 if trace_tasks then - logs.report("nodes","creating task runner '%s'",name) + report_tasks("creating runner '%s'",name) end runner = compile(data.list,nodeprocessor,0) data.runner = runner @@ -132,7 +134,7 @@ function tasks.actions(name,n) -- we optimize for the number or arguments (no .. if not runner then created = created + 1 if trace_tasks then - logs.report("nodes","creating task runner '%s' with 1 extra arguments",name) + report_tasks("creating runner '%s' with 1 extra arguments",name) end runner = compile(data.list,nodeprocessor,1) data.runner = runner @@ -146,7 +148,7 @@ function tasks.actions(name,n) -- we optimize for the number or arguments (no .. if not runner then created = created + 1 if trace_tasks then - logs.report("nodes","creating task runner '%s' with 2 extra arguments",name) + report_tasks("creating runner '%s' with 2 extra arguments",name) end runner = compile(data.list,nodeprocessor,2) data.runner = runner @@ -160,7 +162,7 @@ function tasks.actions(name,n) -- we optimize for the number or arguments (no .. if not runner then created = created + 1 if trace_tasks then - logs.report("nodes","creating task runner '%s' with 3 extra arguments",name) + report_tasks("creating runner '%s' with 3 extra arguments",name) end runner = compile(data.list,nodeprocessor,3) data.runner = runner @@ -174,7 +176,7 @@ function tasks.actions(name,n) -- we optimize for the number or arguments (no .. if not runner then created = created + 1 if trace_tasks then - logs.report("nodes","creating task runner '%s' with 4 extra arguments",name) + report_tasks("creating runner '%s' with 4 extra arguments",name) end runner = compile(data.list,nodeprocessor,4) data.runner = runner @@ -188,7 +190,7 @@ function tasks.actions(name,n) -- we optimize for the number or arguments (no .. if not runner then created = created + 1 if trace_tasks then - logs.report("nodes","creating task runner '%s' with 5 extra arguments",name) + report_tasks("creating runner '%s' with 5 extra arguments",name) end runner = compile(data.list,nodeprocessor,5) data.runner = runner @@ -202,7 +204,7 @@ function tasks.actions(name,n) -- we optimize for the number or arguments (no .. if not runner then created = created + 1 if trace_tasks then - logs.report("nodes","creating task runner '%s' with n extra arguments",name) + report_tasks("creating runner '%s' with n extra arguments",name) end runner = compile(data.list,nodeprocessor,"n") data.runner = runner diff --git a/tex/context/base/page-flt.lua b/tex/context/base/page-flt.lua index 74d1e4e8c..b0f332993 100644 --- a/tex/context/base/page-flt.lua +++ b/tex/context/base/page-flt.lua @@ -14,6 +14,8 @@ local copy_node_list = node.copy_list local trace_floats = false trackers.register("graphics.floats", function(v) trace_floats = v end) -- name might change +local report_floats = logs.new("floats") + -- we use floatbox, floatwidth, floatheight -- text page leftpage rightpage (todo: top, bottom, margin, order) @@ -83,22 +85,26 @@ end function floats.save(which,data) which = which or default - local stack = stacks[which] - noffloats = noffloats + 1 local b = texbox.floatbox - local w, h, d = b.width, b.height, b.depth - local t = { - n = noffloats, - data = data or { }, - box = copy_node_list(b), - } - texbox.floatbox = nil - insert(stack,t) - setcount("global","savednoffloats",#stacks[default]) - if trace_floats then - logs.report("floats","saving %s float %s in slot %s (%i,%i,%i)",which,noffloats,#stack,w,h,d) + if b then + local stack = stacks[which] + noffloats = noffloats + 1 + local w, h, d = b.width, b.height, b.depth + local t = { + n = noffloats, + data = data or { }, + box = copy_node_list(b), + } + texbox.floatbox = nil + insert(stack,t) + setcount("global","savednoffloats",#stacks[default]) + if trace_floats then + report_floats("saving %s float %s in slot %s (%i,%i,%i)",which,noffloats,#stack,w,h,d) + else + interfaces.showmessage("floatblocks",2,noffloats) + end else - interfaces.showmessage("floatblocks",2,noffloats) + report_floats("unable to save %s float %s (empty)",which,noffloats) end end @@ -113,12 +119,12 @@ function floats.resave(which) insert(stack,1,last) setcount("global","savednoffloats",#stacks[default]) if trace_floats then - logs.report("floats","resaving %s float %s in slot %s (%i,%i,%i)",which,noffloats,#stack,w,h,d) + report_floats("resaving %s float %s in slot %s (%i,%i,%i)",which,noffloats,#stack,w,h,d) else interfaces.showmessage("floatblocks",2,noffloats) end else - logs.report("floats","unable to resave float") + report_floats("unable to resave float") end end @@ -129,14 +135,14 @@ function floats.flush(which,n) if t then local w, h, d = setdimensions(b) if trace_floats then - logs.report("floats","flushing %s float %s from slot %s (%i,%i,%i)",which,t.n,n,w,h,d) + report_floats("flushing %s float %s from slot %s (%i,%i,%i)",which,t.n,n,w,h,d) else interfaces.showmessage("floatblocks",3,t.n) end texbox.floatbox = b last = remove(stack,n) last.box = nil - setcount("global","savednoffloats",#stacks[default]) + setcount("global","savednoffloats",#stacks[default]) -- default? else setdimensions() end @@ -156,12 +162,12 @@ function floats.consult(which,n) if t then local w, h, d = setdimensions(b) if trace_floats then - logs.report("floats","consulting %s float %s in slot %s (%i,%i,%i)",which,t.n,n,w,h,d) + report_floats("consulting %s float %s in slot %s (%i,%i,%i)",which,t.n,n,w,h,d) end return t, b, n else if trace_floats then - logs.report("floats","nothing to consult") + report_floats("nothing to consult") end setdimensions() end diff --git a/tex/context/base/page-flt.mkiv b/tex/context/base/page-flt.mkiv index 944626b8e..370b40e89 100644 --- a/tex/context/base/page-flt.mkiv +++ b/tex/context/base/page-flt.mkiv @@ -230,4 +230,20 @@ \ifdefined\doflushfloats\else \let\doflushfloats\relax \fi \ifdefined\flushfloatbox\else \let\flushfloatbox\relax \fi +% temp hack, needed to prevent floatbox being forgotten during +% output, this will change to using another box for flushing +% +% \dorecurse{700}{text } \placefigure[top][]{First} {\framed{bla 1}} +% \placefigure[top][]{Second}{\framed{bla 2}} +% \dorecurse {40}{text } \placefigure[top][]{Third} {\framed{bla 3}} + +\newbox\savedfloatbox + +\appendtoks + \global\setbox\savedfloatbox\box\floatbox +\to \everybeforeoutput +\appendtoks + \global\setbox\floatbox\box\savedfloatbox +\to \everyafteroutput + \protect \endinput diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua index 1f2c96251..e11730eae 100644 --- a/tex/context/base/page-lin.lua +++ b/tex/context/base/page-lin.lua @@ -10,6 +10,8 @@ if not modules then modules = { } end modules ['page-lin'] = { local trace_numbers = false trackers.register("lines.numbers", function(v) trace_numbers = v end) +local report_lines = logs.new("lines") + local format = string.format local texsprint, texwrite, texbox = tex.sprint, tex.write, tex.box @@ -120,7 +122,7 @@ function nodes.lines.boxed.register(configuration) last = last + 1 data[last] = configuration if trace_numbers then - logs.report("lines","registering setup %s",last) + report_lines("registering setup %s",last) end return last end @@ -129,14 +131,14 @@ function nodes.lines.boxed.setup(n,configuration) local d = data[n] if d then if trace_numbers then - logs.report("lines","updating setup %s",n) + report_lines("updating setup %s",n) end for k,v in next, configuration do d[k] = v end else if trace_numbers then - logs.report("lines","registering setup %s (br)",n) + report_lines("registering setup %s (br)",n) end data[n] = configuration end @@ -154,7 +156,7 @@ local function check_number(n,a,skip) -- move inline local tag = d.tag or "" texsprint(ctxcatcodes, format("\\makenumber{%s}{%s}{%s}{%s}{%s}{%s}\\endgraf",tag,s,n.shift,n.width,the_left_margin(n.list),n.dir)) if trace_numbers then - logs.report("numbers","making number %s for setup %s: %s (%s)",#current_list,a,s,d.continue or "no") + report_lines("making number %s for setup %s: %s (%s)",#current_list,a,s,d.continue or "no") end else texsprint(ctxcatcodes, "\\skipnumber\\endgraf") diff --git a/tex/context/base/page-mul.mkiv b/tex/context/base/page-mul.mkiv index 88ec7a5e7..c64fd0c64 100644 --- a/tex/context/base/page-mul.mkiv +++ b/tex/context/base/page-mul.mkiv @@ -1415,7 +1415,6 @@ %D When handling lots of (small) floats spacing can get worse %D because of lining out the columns. - \def\doflushcolumnfloats {\ifpostponecolumnfloats\else \bgroup diff --git a/tex/context/base/page-str.lua b/tex/context/base/page-str.lua index c4d1957c3..234e5424f 100644 --- a/tex/context/base/page-str.lua +++ b/tex/context/base/page-str.lua @@ -20,6 +20,8 @@ local new_glyph = nodes.glyph local trace_collecting = false trackers.register("streams.collecting", function(v) trace_collecting = v end) local trace_flushing = false trackers.register("streams.flushing", function(v) trace_flushing = v end) +local report_streams = logs.new("streams") + streams = streams or { } local data, name, stack = { }, nil, { } @@ -63,7 +65,7 @@ function streams.collect(head,where) dana[1] = head end if trace_collecting then - logs.report("streams","appending snippet '%s' to slot %s",name,#dana) + report_streams("appending snippet '%s' to slot %s",name,#dana) end return nil, true else @@ -80,7 +82,7 @@ function streams.push(thename) if dana then dana[#dana+1] = false if trace_collecting then - logs.report("streams","pushing snippet '%s'",thename) + report_streams("pushing snippet '%s'",thename) end end end @@ -94,7 +96,7 @@ function streams.flush(name,copy) -- problem: we need to migrate afterwards -- nothing to flush elseif copy then if trace_flushing then - logs.report("streams","flushing copies of %s slots of '%s'",dn,name) + report_streams("flushing copies of %s slots of '%s'",dn,name) end for i=1,dn do local di = dana[i] @@ -107,7 +109,7 @@ function streams.flush(name,copy) -- problem: we need to migrate afterwards end else if trace_flushing then - logs.report("streams","flushing %s slots of '%s'",dn,name) + report_streams("flushing %s slots of '%s'",dn,name) end for i=1,dn do local di = dana[i] @@ -126,7 +128,7 @@ function streams.synchronize(list) -- this is an experiment ! list = aux.settings_to_array(list) local max = 0 if trace_flushing then - logs.report("streams","synchronizing list: %s",concat(list," ")) + report_streams("synchronizing list: %s",concat(list," ")) end for i=1,#list do local dana = data[list[i]] @@ -138,7 +140,7 @@ function streams.synchronize(list) -- this is an experiment ! end end if trace_flushing then - logs.report("streams","maximum number of slots: %s",max) + report_streams("maximum number of slots: %s",max) end for m=1,max do local height, depth = 0, 0 @@ -157,12 +159,12 @@ function streams.synchronize(list) -- this is an experiment ! end dana[m] = vbox if trace_flushing then - logs.report("streams","slot %s of '%s' is packed to height %s and depth %s",m,name,ht,dp) + report_streams("slot %s of '%s' is packed to height %s and depth %s",m,name,ht,dp) end end end if trace_flushing then - logs.report("streams","slot %s has max height %s and max depth %s",m,height,depth) + report_streams("slot %s has max height %s and max depth %s",m,height,depth) end local strutht, strutdp = texdimen.globalbodyfontstrutheight, texdimen.globalbodyfontstrutdepth local struthtdp = strutht + strutdp @@ -178,7 +180,7 @@ function streams.synchronize(list) -- this is an experiment ! -- actually we need to add glue and repack vbox.height, vbox.depth = height, depth if trace_flushing then - logs.report("streams","slot %s of '%s' with delta (%s,%s) is compensated",m,i,delta_height,delta_depth) + report_streams("slot %s of '%s' with delta (%s,%s) is compensated",m,i,delta_height,delta_depth) end else -- this is not yet ok as we also need to keep an eye on vertical spacing @@ -199,7 +201,7 @@ function streams.synchronize(list) -- this is an experiment ! vbox.list = nil free_node(vbox) if trace_flushing then - logs.report("streams","slot %s:%s with delta (%s,%s) is compensated by %s lines",m,i,delta_height,delta_depth,n) + report_streams("slot %s:%s with delta (%s,%s) is compensated by %s lines",m,i,delta_height,delta_depth,n) end end end diff --git a/tex/context/base/page-str.mkii b/tex/context/base/page-str.mkii index cfaebe398..71d76484e 100644 --- a/tex/context/base/page-str.mkii +++ b/tex/context/base/page-str.mkii @@ -325,51 +325,6 @@ \box2\vfill\page \egroup} - %D Although one can put floats in a stream, it sometimes makes sense - %D to keep them apart and this is what local floats do. - - \def\setuplocalfloats - {\getparameters[\??lf]} - - \setuplocalfloats - [%before=\blank, - %after=\blank, - inbetween=\blank] - - \installfloathandler \v!local \somelocalfloat - - \initializeboxstack{localfloats} - - \newcounter\noflocalfloats - - \def\resetlocalfloats - {\doglobal\newcounter\noflocalfloats - \initializeboxstack{localfloats}} - - \def\somelocalfloat[#1]% - {\doglobal\increment\noflocalfloats - \savebox{localfloats}{\noflocalfloats}{\box\floatbox}} - - \def\getlocalfloats - {\dorecurse\noflocalfloats - {\ifnum\recurselevel=\plusone % 1\relax - \getvalue{\??lf\c!before}% - \else - \getvalue{\??lf\c!inbetween}% - \fi - \dontleavehmode\hbox{\foundbox{localfloats}\recurselevel}% - \ifnum\recurselevel=\noflocalfloats\relax - \getvalue{\??lf\c!after}% - \fi}} - - \def\flushlocalfloats - {\getlocalfloats - \resetlocalfloats} - - \def\getlocalfloat#1{\expanded{\foundbox{localfloats}{\number#1}}} - - \def\forcelocalfloats{\let\forcedfloatmethod\v!local} - %D Because many arrangements are possible, we will implement %D some examples in a runtime loadable module \type {m-streams}. diff --git a/tex/context/base/s-abr-01.tex b/tex/context/base/s-abr-01.tex index a55eb95f1..b233eeee2 100644 --- a/tex/context/base/s-abr-01.tex +++ b/tex/context/base/s-abr-01.tex @@ -287,33 +287,36 @@ \def\SystemSpecialA#1{$\langle\it#1\rangle$} \def\SystemSpecialB#1{{\tttf<#1>}} -\def\CATCODE {\SystemSpecialA{catcode}} -\def\CATCODES {\SystemSpecialA{catcodes}} -\def\DIMENSION {\SystemSpecialA{dimension}} -\def\DIMENSIONS {\SystemSpecialA{dimensions}} -\def\COUNTER {\SystemSpecialA{counter}} -\def\COUNTERS {\SystemSpecialA{counters}} -\def\HBOX {\SystemSpecialA{hbox}} -\def\HBOXES {\SystemSpecialA{hboxes}} -\def\VBOX {\SystemSpecialA{vbox}} -\def\VBOXES {\SystemSpecialA{vboxes}} -\def\BOX {\SystemSpecialA{box}} -\def\BOXES {\SystemSpecialA{boxes}} -\def\TOKENLIST {\SystemSpecialA{token list}} -\def\TOKENLISTS {\SystemSpecialA{token lists}} -\def\NEWLINE {\SystemSpecialA{newline}} -\def\SKIP {\SystemSpecialA{skip}} -\def\SKIPS {\SystemSpecialA{skips}} -\def\MUSKIP {\SystemSpecialA{muskip}} -\def\MUSKIPS {\SystemSpecialA{muskips}} -\def\MARK {\SystemSpecialA{mark}} -\def\MARKS {\SystemSpecialA{marks}} +\unexpanded\def\CATCODE {\SystemSpecialA{catcode}} +\unexpanded\def\CATCODES {\SystemSpecialA{catcodes}} +\unexpanded\def\DIMENSION {\SystemSpecialA{dimension}} +\unexpanded\def\DIMENSIONS {\SystemSpecialA{dimensions}} +\unexpanded\def\COUNTER {\SystemSpecialA{counter}} +\unexpanded\def\COUNTERS {\SystemSpecialA{counters}} +\unexpanded\def\HBOX {\SystemSpecialA{hbox}} +\unexpanded\def\HBOXES {\SystemSpecialA{hboxes}} +\unexpanded\def\VBOX {\SystemSpecialA{vbox}} +\unexpanded\def\VBOXES {\SystemSpecialA{vboxes}} +\unexpanded\def\BOX {\SystemSpecialA{box}} +\unexpanded\def\BOXES {\SystemSpecialA{boxes}} +\unexpanded\def\TOKENLIST {\SystemSpecialA{token list}} +\unexpanded\def\TOKENLISTS {\SystemSpecialA{token lists}} +\unexpanded\def\NEWLINE {\SystemSpecialA{newline}} +\unexpanded\def\SKIP {\SystemSpecialA{skip}} +\unexpanded\def\SKIPS {\SystemSpecialA{skips}} +\unexpanded\def\MUSKIP {\SystemSpecialA{muskip}} +\unexpanded\def\MUSKIPS {\SystemSpecialA{muskips}} +\unexpanded\def\MARK {\SystemSpecialA{mark}} +\unexpanded\def\MARKS {\SystemSpecialA{marks}} -\def\SPACE {\SystemSpecialB{space}} -\def\EOF {\SystemSpecialB{eof}} -\def\TAB {\SystemSpecialB{tab}} -\def\NEWPAGE {\SystemSpecialB{newpage}} -\def\NEWLINE {\SystemSpecialB{newline}} +\unexpanded\def\SPACE {\SystemSpecialB{space}} +\unexpanded\def\EOF {\SystemSpecialB{eof}} +\unexpanded\def\TAB {\SystemSpecialB{tab}} +\unexpanded\def\NEWPAGE {\SystemSpecialB{newpage}} +\unexpanded\def\NEWLINE {\SystemSpecialB{newline}} + +\unexpanded\def\LUWATEEKH {لُواتيخ} % kh ī t ā w [u] l +\unexpanded\def\luwateekh {luwātīkh} \doifmodeelse {mkiv} { \unexpanded\def\THANH{H\agrave n Th\ecircumflexacute\ Th\agrave nh} diff --git a/tex/context/base/s-fnt-23.tex b/tex/context/base/s-fnt-23.tex index 096c8fbf5..dedcf06e4 100644 --- a/tex/context/base/s-fnt-23.tex +++ b/tex/context/base/s-fnt-23.tex @@ -11,6 +11,8 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +% last_data was written wrong so it needs checking + \startluacode local last_data = nil local format = string.format @@ -20,7 +22,7 @@ end function fonts.otf.show_shape(n) local tfmdata = fonts.ids[font.current()] - lastdata = tfmdata + last_data = tfmdata local charnum = tonumber(n) if not charnum then charnum = tfmdata.unicodes[n] @@ -197,7 +199,7 @@ end function fonts.otf.show_all_shapes(start,stop) local tfmdata = fonts.ids[font.current()] - lastdata = tfmdata + last_data = tfmdata start, stop = start or "\\startTEXpage\\gobbleoneargument", stop or "\\stopTEXpage" local unicodes, indices, descriptions = tfmdata.unicodes, tfmdata.indices, tfmdata.descriptions for _, unicode in next, table.sortedkeys(descriptions) do @@ -210,7 +212,7 @@ end end function fonts.otf.show_shape_field(unicode,name) - local tfmdata = lastdata or fonts.ids[font.current()] + local tfmdata = last_data or fonts.ids[font.current()] local d = tfmdata.descriptions[unicode] if d then if name == "unicode" then @@ -268,5 +270,6 @@ \startTEXpage \ShowGlyphShape{simplenaskhi}{100bp}{NameMe.1190} \stopTEXpage \ShowAllGlyphShapes{simplenaskhi}{100bp} +% \ShowAllGlyphShapes{xits}{100bp} \stoptext diff --git a/tex/context/base/s-fnt-25.tex b/tex/context/base/s-fnt-25.tex index a8b398716..132fa65f9 100644 --- a/tex/context/base/s-fnt-25.tex +++ b/tex/context/base/s-fnt-25.tex @@ -167,7 +167,7 @@ function document.showmathfont(id,slot) if cnext then report("\\mathfontlistentrynextlist{%s}",table.concat(cnext," => ")) end - if variants then + if cvariants then report("\\mathfontlistentryvariantslist{%s}",table.concat(cvariants," ")) end end @@ -179,16 +179,13 @@ end \endinput -\startbuffer[mathtest] - \begingroup\mm\mr\showmathfontcharacters\endgroup -\stopbuffer - \starttext - \usetypescript[cambria] \setupbodyfont[cambria, 12pt] \getbuffer[mathtest] - \usetypescript[lmvirtual] \setupbodyfont[lmvirtual,12pt] \getbuffer[mathtest] - \usetypescript[pxvirtual] \setupbodyfont[pxvirtual,12pt] \getbuffer[mathtest] - \usetypescript[txvirtual] \setupbodyfont[txvirtual,12pt] \getbuffer[mathtest] - \usetypescript[palatino] \setupbodyfont[palatino, 10pt] \getbuffer[mathtest] - \usetypescript[mathtimes] \setupbodyfont[mathtimes,12pt] \getbuffer[mathtest] + \setupbodyfont[cambria, 12pt] \showmathfontcharacters + \setupbodyfont[lmvirtual,12pt] \showmathfontcharacters + \setupbodyfont[pxvirtual,12pt] \showmathfontcharacters + \setupbodyfont[txvirtual,12pt] \showmathfontcharacters + \setupbodyfont[palatino, 10pt] \showmathfontcharacters + \setupbodyfont[mathtimes,12pt] \showmathfontcharacters + \setupbodyfont[stix, 12pt] \showmathfontcharacters \stoptext diff --git a/tex/context/base/s-mod-02.tex b/tex/context/base/s-mod-02.tex index 9dae3ecc0..fac5c23e6 100644 --- a/tex/context/base/s-mod-02.tex +++ b/tex/context/base/s-mod-02.tex @@ -37,15 +37,14 @@ \determineregistercharacteristics [index] [criterium=section] - \ifutilitydone - \pagereference - [index] - \placeregister - [index] - [balance=yes, - indicator=no, - criterium=section] - \fi} + \doifmode{*register} + {\pagereference + [index] + \placeregister + [index] + [balance=yes, + indicator=no, + criterium=section]}} \let\ComposeLists=\relax diff --git a/tex/context/base/s-pre-50.tex b/tex/context/base/s-pre-50.tex index 782f6aea1..41ae04821 100644 --- a/tex/context/base/s-pre-50.tex +++ b/tex/context/base/s-pre-50.tex @@ -62,7 +62,7 @@ %D Structure and trick. \def\StartSteps - {\checkutilities} + {\doifnotmode{mkiv}{\checkutilities}} \def\StopSteps {\resetcollector[contribution]} diff --git a/tex/context/base/scrp-cjk.lua b/tex/context/base/scrp-cjk.lua index 997baaa96..6ac6c5b11 100644 --- a/tex/context/base/scrp-cjk.lua +++ b/tex/context/base/scrp-cjk.lua @@ -327,7 +327,7 @@ local function process(head,first,last) if action then local font = first.font if font ~= lastfont then - lastfont, done = font, true + lastfont = font set_parameters(font,dataset) end action(head,first) @@ -359,7 +359,7 @@ local function process(head,first,last) previous = "start" end end - if upcoming == stop then + if upcoming == last then -- was stop break else first = upcoming @@ -530,7 +530,7 @@ local function process(head,first,last) if action then local font = first.font if font ~= lastfont then - lastfont, done = font, true + lastfont = font set_parameters(font,dataset) end action(head,first) @@ -562,7 +562,7 @@ local function process(head,first,last) previous = "start" end end - if upcoming == stop then + if upcoming == last then -- was stop break else first = upcoming diff --git a/tex/context/base/scrp-ini.lua b/tex/context/base/scrp-ini.lua index b28c297d0..292f1e779 100644 --- a/tex/context/base/scrp-ini.lua +++ b/tex/context/base/scrp-ini.lua @@ -9,6 +9,8 @@ if not modules then modules = { } end modules ['scrp-ini'] = { local trace_analyzing = false trackers.register("scripts.analyzing", function(v) trace_analyzing = v end) local trace_injections = false trackers.register("scripts.injections", function(v) trace_injections = v end) +local report_preprocessing = logs.new("preprocessing") + local set_attribute = node.set_attribute local has_attribute = node.has_attribute local first_character = node.first_character @@ -257,9 +259,9 @@ end local function traced_process(head,first,last,process,a) if start ~= last then local f, l = first, last - logs.report("preprocess","before %s: %s",names[a] or "?",nodes.tosequence(f,l)) + report_preprocessing("before %s: %s",names[a] or "?",nodes.tosequence(f,l)) process(head,first,last) - logs.report("preprocess","after %s: %s", names[a] or "?",nodes.tosequence(f,l)) + report_preprocessing("after %s: %s", names[a] or "?",nodes.tosequence(f,l)) end end diff --git a/tex/context/base/sort-ini.lua b/tex/context/base/sort-ini.lua index b745c9aa5..d029f9bef 100644 --- a/tex/context/base/sort-ini.lua +++ b/tex/context/base/sort-ini.lua @@ -20,6 +20,8 @@ local next, type, tonumber = next, type, tonumber local trace_tests = false trackers.register("sorters.tests", function(v) trace_tests = v end) +local report_sorters = logs.new("sorters") + sorters = { } sorters.comparers = { } sorters.splitters = { } @@ -252,7 +254,7 @@ function sorters.sort(entries,cmp) if trace_tests then sort(entries,function(a,b) local r = cmp(a,b) - logs.report("sorter","%s %s %s",pack(a),(not r and "?") or (r<0 and "<") or (r>0 and ">") or "=",pack(b)) + report_sorters("%s %s %s",pack(a),(not r and "?") or (r<0 and "<") or (r>0 and ">") or "=",pack(b)) return r == -1 end) local s @@ -263,9 +265,9 @@ function sorters.sort(entries,cmp) first = " " else s = first - logs.report("sorter",">> %s 0x%05X (%s 0x%05X)",first,utfbyte(first),letter,utfbyte(letter)) + report_sorters(">> %s 0x%05X (%s 0x%05X)",first,utfbyte(first),letter,utfbyte(letter)) end - logs.report("sorter"," %s",pack(entry)) + report_sorters(" %s",pack(entry)) end else sort(entries,function(a,b) diff --git a/tex/context/base/spac-ver.lua b/tex/context/base/spac-ver.lua index c75eb1baa..e06cb0ded 100644 --- a/tex/context/base/spac-ver.lua +++ b/tex/context/base/spac-ver.lua @@ -38,6 +38,11 @@ local trace_page_vspacing = false trackers.register("nodes.page_vspacing", local trace_collect_vspacing = false trackers.register("nodes.collect_vspacing", function(v) trace_collect_vspacing = v end) local trace_vspacing = false trackers.register("nodes.vspacing", function(v) trace_vspacing = v end) local trace_vsnapping = false trackers.register("nodes.vsnapping", function(v) trace_vsnapping = v end) +local trace_vpacking = false trackers.register("nodes.vpacking", function(v) trace_vpacking = v end) + +local report_vspacing = logs.new("vspacing") +local report_collapser = logs.new("collapser") +local report_snapper = logs.new("snapper") local skip_category = attributes.private('skip-category') local skip_penalty = attributes.private('skip-penalty') @@ -337,7 +342,7 @@ storage.register("vspacing/data/skip", vspacing.data.skip, "vspacing.data.skip") do -- todo: interface.variables local function logger(c,...) - logs.report("vspacing",concat {...}) + report_vspacing(concat {...}) texsprint(c,...) end @@ -360,7 +365,7 @@ do -- todo: interface.variables for s in gmatch(str,"([^ ,]+)") do local amount, keyword, detail = lpegmatch(splitter,s) if not keyword then - logs.report("vspacing","unknown directive: %s",s) + report_vspacing("unknown directive: %s",s) else local mk = map[keyword] if mk then @@ -513,13 +518,13 @@ local function show_tracing(head) for i=1,#trace_list do local tag, text = unpack(trace_list[i]) if tag == "info" then - logs.report("collapse",text) + report_collapser(text) else - logs.report("collapse"," %s: %s",tag,text) + report_collapser(" %s: %s",tag,text) end end - logs.report("collapse","before: %s",before) - logs.report("collapse","after : %s",after) + report_collapser("before: %s",before) + report_collapser("after : %s",after) end end @@ -582,13 +587,13 @@ function vspacing.snap_box(n,how) local s = has_attribute(list,snap_method) if s == 0 then if trace_vsnapping then - -- logs.report("snapper", "hlist not snapped, already done") + -- report_snapper("hlist not snapped, already done") end else local h, d, ch, cd, lines = snap_hlist(box,sv,box.height,box.depth) box.height, box.depth = ch, cd if trace_vsnapping then - logs.report("snapper", "hlist snapped from (%s,%s) to (%s,%s) using method '%s' (%s) for '%s' (%s lines)",h,d,ch,cd,sv.name,sv.specification,"direct",lines) + report_snapper("hlist snapped from (%s,%s) to (%s,%s) using method '%s' (%s) for '%s' (%s lines)",h,d,ch,cd,sv.name,sv.specification,"direct",lines) end set_attribute(list,snap_method,0) end @@ -609,7 +614,7 @@ local function forced_skip(head,current,width,where,trace) current = c end if trace then - logs.report("vspacing", "inserting forced skip of %s",width) + report_vspacing("inserting forced skip of %s",width) end return head, current end @@ -629,16 +634,16 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail if penalty_data then local p = make_penalty_node(penalty_data) if trace then trace_done("flushed due to " .. why,p) end - head, _ = insert_node_before(head,current,p) + head = insert_node_before(head,current,p) end if glue_data then if force_glue then if trace then trace_done("flushed due to " .. why,glue_data) end - head, _ = forced_skip(head,current,glue_data.spec.width,"before",trace) + head = forced_skip(head,current,glue_data.spec.width,"before",trace) free_glue_node(glue_data) elseif glue_data.spec.writable then if trace then trace_done("flushed due to " .. why,glue_data) end - head, _ = insert_node_before(head,current,glue_data) + head = insert_node_before(head,current,glue_data) else free_glue_node(glue_data) end @@ -649,7 +654,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail parskip, ignore_parskip, ignore_following, ignore_whitespace = nil, false, false, false end if trace_vsnapping then - logs.report("snapper", "global ht/dp = %s/%s, local ht/dp = %s/%s", + report_snapper("global ht/dp = %s/%s, local ht/dp = %s/%s", texdimen.globalbodyfontstrutheight, texdimen.globalbodyfontstrutdepth, texdimen.bodyfontstrutheight, texdimen.bodyfontstrutdepth) end @@ -662,21 +667,21 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail local s = has_attribute(current,snap_method) if not s then -- if trace_vsnapping then - -- logs.report("snapper", "hlist not snapped") + -- report_snapper("hlist not snapped") -- end elseif s == 0 then if trace_vsnapping then - -- logs.report("snapper", "hlist not snapped, already done") + -- report_snapper("hlist not snapped, already done") end else local sv = snapmethods[s] if sv then local h, d, ch, cd, lines = snap_hlist(current,sv) if trace_vsnapping then - logs.report("snapper", "hlist snapped from (%s,%s) to (%s,%s) using method '%s' (%s) for '%s' (%s lines)",h,d,ch,cd,sv.name,sv.specification,where,lines) + report_snapper("hlist snapped from (%s,%s) to (%s,%s) using method '%s' (%s) for '%s' (%s lines)",h,d,ch,cd,sv.name,sv.specification,where,lines) end elseif trace_vsnapping then - logs.report("snapper", "hlist not snapped due to unknown snap specification") + report_snapper("hlist not snapped due to unknown snap specification") end set_attribute(current,snap_method,0) end @@ -694,7 +699,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail elseif id == kern then if snap and trace_vsnapping and current.kern ~= 0 then --~ current.kern = 0 - logs.report("snapper", "kern of %s (kept)",current.kern) + report_snapper("kern of %s (kept)",current.kern) end flush("kern") current = current.next @@ -836,7 +841,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail local spec = writable_spec(current) spec.width = 0 if trace_vsnapping then - logs.report("snapper", "lineskip set to zero") + report_snapper("lineskip set to zero") end end else @@ -857,7 +862,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail local spec = writable_spec(current) spec.width = 0 if trace_vsnapping then - logs.report("snapper", "baselineskip set to zero") + report_snapper("baselineskip set to zero") end end else @@ -895,7 +900,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail local sv = snapmethods[s] local w, cw = snap_topskip(current,sv) if trace_vsnapping then - logs.report("snapper", "topskip snapped from %s to %s for '%s'",w,cw,where) + report_snapper("topskip snapped from %s to %s for '%s'",w,cw,where) end else if trace then trace_skip("topskip",sc,so,sp,current) end @@ -932,7 +937,7 @@ local function collapser(head,where,what,trace,snap) -- maybe also pass tail -- else -- other glue if snap and trace_vsnapping and current.spec.writable and current.spec.width ~= 0 then - logs.report("snapper", "%s of %s (kept)",skips[subtype],current.spec.width) + report_snapper("%s of %s (kept)",skips[subtype],current.spec.width) --~ current.spec.width = 0 end if trace then trace_skip(format("some glue (%s)",subtype),sc,so,sp,current) end @@ -989,7 +994,7 @@ end local stackhead, stacktail, stackhack = nil, nil, false local function report(message,lst) - logs.report("vspacing",message,count_nodes(lst,true),node_ids_to_string(lst)) + report_vspacing(message,count_nodes(lst,true),node_ids_to_string(lst)) end function nodes.handle_page_spacing(newhead,where) @@ -1144,14 +1149,14 @@ function nodes.builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direc local done = false if head then starttiming(builders) - if trace_callbacks then + if trace_vpacking then local before = nodes.count(head) head, done = actions(head,groupcode,size,packtype,maxdepth,direction) local after = nodes.count(head) if done then - tracer("vpack","changed",head,groupcode,before,after,true) + nodes.processors.tracer("vpack","changed",head,groupcode,before,after,true) else - tracer("vpack","unchanged",head,groupcode,before,after,true) + nodes.processors.tracer("vpack","unchanged",head,groupcode,before,after,true) end stoptiming(builders) else diff --git a/tex/context/base/strc-def.mkiv b/tex/context/base/strc-def.mkiv index 77793c7eb..94bc2fb14 100644 --- a/tex/context/base/strc-def.mkiv +++ b/tex/context/base/strc-def.mkiv @@ -12,7 +12,7 @@ \writestatus{loading}{ConTeXt Structure Macros / Definitions} -% \registerctxluafile{strc-def}{1.001} +%registerctxluafile{strc-def}{1.001} \unprotect diff --git a/tex/context/base/strc-doc.lua b/tex/context/base/strc-doc.lua index 7faf0d5b3..0c5cea64f 100644 --- a/tex/context/base/strc-doc.lua +++ b/tex/context/base/strc-doc.lua @@ -24,10 +24,7 @@ local variables = interfaces.variables local trace_sectioning = false trackers.register("structure.sectioning", function(v) trace_sectioning = v end) local trace_detail = false trackers.register("structure.detail", function(v) trace_detail = v end) -local function report(...) ---~ print(...) - logs.report("sectioning:",...) -end +local report_structure = logs.new("structure") structure = structure or { } structure.helpers = structure.helpers or { } @@ -207,7 +204,7 @@ function sections.somelevel(given) -- normally these are passed as argument but nowadays we provide several -- interfaces (we need this because we want to be compatible) if trace_detail then - logs.report("structure","name '%s', mapped level '%s', old depth '%s', new depth '%s', reset set '%s'",givenname,mappedlevel,olddepth,newdepth,resetset) + report_structure("name '%s', mapped level '%s', old depth '%s', new depth '%s', reset set '%s'",givenname,mappedlevel,olddepth,newdepth,resetset) end local u = given.userdata if u then @@ -223,7 +220,7 @@ function sections.somelevel(given) for i=olddepth+1,newdepth do local s = tonumber(sets.get("structure:resets",data.block,resetset,i)) if trace_detail then - logs.report("structure","new>old (%s>%s), reset set '%s', reset value '%s', current '%s'",olddepth,newdepth,resetset,s or "?",numbers[i] or "?") + report_structure("new>old (%s>%s), reset set '%s', reset value '%s', current '%s'",olddepth,newdepth,resetset,s or "?",numbers[i] or "?") end if not s or s == 0 then numbers[i] = numbers[i] or 0 @@ -238,7 +235,7 @@ function sections.somelevel(given) for i=olddepth,newdepth+1,-1 do local s = tonumber(sets.get("structure:resets",data.block,resetset,i)) if trace_detail then - logs.report("structure","newIt's more convenient to manipulate filenames (paths) in
This is a prelude to a more extensive logging module. For the sake
of parsing log files, in addition to the standard logging we will
@@ -27,65 +24,93 @@ provide an This looks pretty ugly but we need to speed things up a bit. Most of the code that had accumulated here is now separated in
-modules. We start with a registration system for atributes so that we can use the
-symbolic names later on. We can use the attributes in the range 127-255 (outside user space). These
-are only used when no attribute is set at the \TEX\ end which normally
-happens in Access to nodes is what gives When manipulating node lists in First of all, we noticed that the bottleneck is more with excessive
-callbacks (some gets called very often) and the conversion from and to
- This resulted in two special situations in passing nodes back to
- Insertion is handled (at least in When we collapse (something that we only do when really needed), we
-also ignore the empty nodes. [This is obsolete!] The next function is not that much needed but in At some point we ran into a problem that the glue specification
-of the zeropoint dimension was overwritten when adapting a glue spec
-node. This is a side effect of glue specs being shared. After a
-couple of hours tracing and debugging Taco and I came to the
-conclusion that it made no sense to complicate the spec allocator
-and settled on a writable flag. This all is a side effect of the
-fact that some glues use reserved memory slots (with the zeropoint
-glue being a noticeable one). So, next we wrap this into a function
-and hide it for the user. And yes, LuaTeX now gives a warning as
-well. Here we replace start by new glyph. First we delete the rest of the match. Here we deal with defining fonts. We do so by intercepting the
default loader that only handles %s",category,format(fmt,s,...)))
+ elseif fmt then
+ write_nl(format("")
write_nl("")
end
-function logs.xml.report_output_pages(p,b)
+function xmllog.report_output_pages(p,b)
write_nl(format("%s",category,fmt))
+ else
+ write_nl(format("",category))
+ end
+end
+
+function xmllog.line(fmt,...) -- new
if fmt then
write_nl(format("