diff options
author | Hans Hagen <pragma@wxs.nl> | 2021-06-24 19:37:45 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2021-06-24 19:37:45 +0200 |
commit | 820657bb1e9acfb36f24dfa8801526b0d5f2b464 (patch) | |
tree | fc93fd3936e84b9b0a6402719e185d35e332eee9 /tex | |
parent | 4272a26c49cbfee8917e5272fc0f964cbcfc4b03 (diff) | |
download | context-820657bb1e9acfb36f24dfa8801526b0d5f2b464.tar.gz |
2021-06-24 18:52:00
Diffstat (limited to 'tex')
96 files changed, 2626 insertions, 1267 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 090a16912..fcd325bb0 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2021.06.14 17:06} +\newcontextversion{2021.06.24 18:50} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index 96fe2716a..9d1f707b6 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2021.06.14 17:06} +\edef\contextversion{2021.06.24 18:50} %D For those who want to use this: diff --git a/tex/context/base/mkiv/back-exp.lua b/tex/context/base/mkiv/back-exp.lua index 5928da538..51c32ec1d 100644 --- a/tex/context/base/mkiv/back-exp.lua +++ b/tex/context/base/mkiv/back-exp.lua @@ -1640,7 +1640,7 @@ do d.__i__ = n data[n] = d elseif content == " " or content == "" then - if di.tg == "mspace" then + if d.tg == "mspace" then -- we append or prepend a space to a preceding or following mtext local parent = di.__p__ local index = di.__i__ -- == i diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua index f95ac301c..a69b2d707 100644 --- a/tex/context/base/mkiv/cldf-ini.lua +++ b/tex/context/base/mkiv/cldf-ini.lua @@ -400,19 +400,22 @@ local registerscanner if CONTEXTLMTXMODE > 0 then -- always permanent but we can consider to obey permanent==false + -- todo: make bitset instead of keys (nil is skipped anyway) + local function toflags(specification) - local protected = specification.protected and "protected" -- or "" + local protected = specification.protected and "protected" + local untraced = specification.untraced and "untraced" local usage = specification.usage if usage == "value" then - return "global", "value", "permanent", protected + return "global", "value", "permanent", "untraced", protected elseif usage == "condition" then - return "global", "conditional", "permanent", protected + return "global", "conditional", "permanent", "untraced", protected elseif specification.frozen then - return "global", "frozen", protected + return "global", "frozen", untraced, protected elseif specification.permanent == false or specification.onlyonce then -- for now onlyonce here - return "global", protected + return "global", untraced, protected else - return "global", "permanent", protected + return "global", "permanent", untraced, protected end end @@ -422,6 +425,7 @@ local registerscanner if CONTEXTLMTXMODE > 0 then storedscanners[name] = n namesofscanners[n] = name name = specification.public and name or (privatenamespace .. name) + -- print(name,n,toflags(specification)) setluatoken(name,n,toflags(specification)) end diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 29bb55997..5ae1a881c 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.06.14 17:06} +\newcontextversion{2021.06.24 18:50} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 4e6e0dcb9..20d33af39 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2021.06.14 17:06} +\edef\contextversion{2021.06.24 18:50} %D Kind of special: diff --git a/tex/context/base/mkiv/data-dec.lua b/tex/context/base/mkiv/data-dec.lua new file mode 100644 index 000000000..2a62b7dd9 --- /dev/null +++ b/tex/context/base/mkiv/data-dec.lua @@ -0,0 +1,56 @@ +if not modules then modules = { } end modules ['data-dec'] = { + version = 1.001, + comment = "companion to luat-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local loaddata = io.loaddata +local suffix = file.suffix +local resultof = os.resultof + +local decompressors = { } +resolvers.decompressors = decompressors + +local decompresslzma = nil +local decompressgzip = gzip.decompress + +local function decompressed(k) + local s = suffix(k) + if s == "xz" then + if decompresslzma == nil then + local lzma = require(resolvers.findfile("libs-imp-lzma.lmt")) + if lzma then + local decompress = lzma.decompress + decompresslzma = function(name) + return decompress(loaddata(k)) + end + else + decompresslzma = function(name) + -- todo: use a proper runner + return resultof("xz -d -c -q -q " .. name) + end + end + end + return decompresslzma(k) + elseif s == "gz" then + return decompressgzip(loaddata(k)) + end +end + +local cache = table.setmetatableindex(function(t,k) + local v = decompressed(k) or false + t[k] = v + return v +end) + +decompressors.decompress = decompress + +function decompressors.register(filename) + return cache[filename] +end + +function decompressors.unregister(filename) + cache[filename] = nil +end diff --git a/tex/context/base/mkiv/data-tar.lua b/tex/context/base/mkiv/data-tar.lua new file mode 100644 index 000000000..45de749b6 --- /dev/null +++ b/tex/context/base/mkiv/data-tar.lua @@ -0,0 +1,236 @@ +if not modules then modules = { } end modules ['data-tar'] = { + version = 1.001, + comment = "companion to luat-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local format, find, match = string.format, string.find, string.match + +local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) + +local report_tar = logs.reporter("resolvers","tar") + +--[[ldx-- +<p>We use a url syntax for accessing the tar file itself and file in it:</p> + +<typing> +tar:///oeps.tar?name=bla/bla.tex +tar:///oeps.tar?tree=tex/texmf-local +</typing> +--ldx]]-- + +local resolvers = resolvers +local findfile = resolvers.findfile +local registerfile = resolvers.registerfile +local splitmethod = resolvers.splitmethod +local starttiming = resolvers.starttiming +local stoptiming = resolvers.stoptiming + +local urlquery = url.query + +--- hm, zip sits in the global namespace, but tar doesn't + +local tar = utilities.tar or { } +utilities.tar = tar -- not needed + +local archives = tar.archives or { } +tar.archives = archives + +local registeredfiles = tar.registeredfiles or { } +tar.registeredfiles = registeredfiles + +-- foo.tar.xz : done +-- foo.tar.gz : todo +-- foo.tar : done + +local hashtar, fetchtar, wipetar do + + local suffix = file.suffix -- hassuffix .. no need to split + + local tarfiles = utilities.tar.file + local tarstrings = utilities.tar.string + + local hashtarfile = tar.files.hash + local fetchtarfile = tar.files.fetch + + local hashtarstring = tar.strings.hash + local fetchtarstring = tar.strings.fetch + + local register = resolvers.decompressors.register + + hashtar = function(archive,strip) + local a = register(archive) + if a then + return hashtarstring(a,archive) + else + return hashtarfile(archive,archive) + end + end + + fetchtar = function(archive,filename,list) + local a = register(archive) + if a then + return fetchtarstring(a,filename,list) + else + return fetchtarfile(archive,filename,list) + end + end + + wipetar = resolvers.decompressors.unregister + +end + +local function validfile(archive,name) + return archive[name] +end + +local function openarchive(name) + if not name or name == "" then + return nil + else + local arch = archives[name] + if not arch then + local full = findfile(name) or "" + arch = full ~= "" and hashtar(full,name) or false + archives[name] = arch + end + return arch + end +end + +local function closearchive(name) + if not name or (name == "" and archives[name]) then + archives[name] = nil + wipetar(name) + end +end + +tar.openarchive = openarchive +tar.closearchive = closearchive + +function resolvers.locators.tar(specification) + local archive = specification.filename + local tarfile = archive and archive ~= "" and openarchive(archive) + if trace_locating then + if tarfile then + report_tar("locator: archive %a found",archive) + else + report_tar("locator: archive %a not found",archive) + end + end +end + +function resolvers.concatinators.tar(tarfile,path,name) -- ok ? + if not path or path == "" then + return format('%s?name=%s',tarfile,name) + else + return format('%s?name=%s/%s',tarfile,path,name) + end +end + +local finders = resolvers.finders +local notfound = finders.notfound + +function finders.tar(specification) + local original = specification.original + local archive = specification.filename + if archive then + local query = urlquery(specification.query) + local queryname = query.name + if queryname then + local tfile = openarchive(archive) + if tfile then + if trace_locating then + report_tar("finder: archive %a found",archive) + end + if validfile(tfile,queryname) then + if trace_locating then + report_tar("finder: file %a found",queryname) + end + return specification.original + elseif trace_locating then + report_tar("finder: file %a not found",queryname) + end + elseif trace_locating then + report_tar("finder: unknown archive %a",archive) + end + end + end + if trace_locating then + report_tar("finder: %a not found",original) + end + return notfound() +end + +local openers = resolvers.openers +local notfound = openers.notfound +local textopener = openers.helpers.textopener + +function openers.tar(specification) + local original = specification.original + local archive = specification.filename + if archive then + local query = urlquery(specification.query) + local queryname = query.name + if queryname then + local tfile = openarchive(archive) + if tfile then + if trace_locating then + report_tar("opener; archive %a opened",archive) + end + local data = fetchtar(archive,queryname,tfile) + if data then + if trace_locating then + report_tar("opener: file %a found",queryname) + end + return textopener('tar',original,data) -- a string handle + elseif trace_locating then + report_tar("opener: file %a not found",queryname) + end + elseif trace_locating then + report_tar("opener: unknown archive %a",archive) + end + end + end + if trace_locating then + report_tar("opener: %a not found",original) + end + return notfound() +end + +loaders = resolvers.loaders +local notfound = loaders.notfound + +function loaders.tar(specification) + local original = specification.original + local archive = specification.filename + if archive then + local query = urlquery(specification.query) + local queryname = query.name + if queryname then + local tfile = openarchive(archive) + if tfile then + if trace_locating then + report_tar("loader: archive %a opened",archive) + end + local data = fetchtar(archive,queryname,tfile) + if data then + if trace_locating then + report_tar("loader; file %a loaded",original) + end + return true, data, #data + elseif trace_locating then + report_tar("loader: file %a not found",queryname) + end + elseif trace_locating then + report_tar("loader; unknown archive %a",archive) + end + end + end + if trace_locating then + report_tar("loader: %a not found",original) + end + return notfound() +end diff --git a/tex/context/base/mkiv/data-use.lua b/tex/context/base/mkiv/data-use.lua index a7ca2389e..168b62201 100644 --- a/tex/context/base/mkiv/data-use.lua +++ b/tex/context/base/mkiv/data-use.lua @@ -82,14 +82,14 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile,banner) -- tex functionality = LUATEXFUNCTIONALITY, } io.savedata(luvname,table.serialize(luvdata,true)) - lua.registerfinalizer(function() + lua.registerinitexfinalizer(function() if jit then logs.report("format banner","%s lua: %s jit",banner,LUAVERSION) else logs.report("format banner","%s lua: %s",banner,LUAVERSION) end logs.newline() - end) + end, "show banner") end end diff --git a/tex/context/base/mkiv/data-zip.lua b/tex/context/base/mkiv/data-zip.lua index 8d914b842..1a9310f17 100644 --- a/tex/context/base/mkiv/data-zip.lua +++ b/tex/context/base/mkiv/data-zip.lua @@ -70,10 +70,10 @@ if zipfiles then local readstring = streams.readstring local streamsize = streams.size - local metatable = { + local metatable = { -- irrelevant as the streams proivide the methods .. a leftover? close = streams.close, read = function(stream,n) - readstring(stream,n == "*a" and streamsize(stream) or n) + readstring(stream,n == "*a" and streamsize(stream) or n) -- no return ? end } diff --git a/tex/context/base/mkiv/font-cff.lua b/tex/context/base/mkiv/font-cff.lua index ff87292ba..8b01d92b7 100644 --- a/tex/context/base/mkiv/font-cff.lua +++ b/tex/context/base/mkiv/font-cff.lua @@ -572,6 +572,11 @@ do stack[top] = -(byte(b0)-251)*256 - byte(b1) - 108 end + -- local p_float = P("\255") * C(1) * C(1) * C(1) * C(1) / function(b0,b1,b2,b3) + -- top = top + 1 + -- stack[top] = 0 + -- end + local p_short = P("\28") * C(1) * C(1) / function(b1,b2) -- -32768 .. +32767 : b1<<8 | b2 top = top + 1 @@ -607,6 +612,7 @@ do + p_nibbles + p_single + p_double + -- + p_float + p_unsupported )^1 @@ -1825,13 +1831,13 @@ do stack[top] = -t*256 + 64148 - tab[i+1] i = i + 2 else - -- a 16.16 float - local n = 0x100 * tab[i+1] + tab[i+2] - if n >= 0x8000 then - stack[top] = n - 0x10000 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF - else - stack[top] = n + (0x100 * tab[i+3] + tab[i+4])/0xFFFF + -- a 16.16 float (used for italic but pretty unreliable) + local n1 = 0x100 * tab[i+1] + tab[i+2] + local n2 = 0x100 * tab[i+3] + tab[i+4] + if n1 >= 0x8000 then + n1 = n1 - 0x10000 end + stack[top] = n1 + n2/0xFFFF i = i + 5 end elseif t == 28 then diff --git a/tex/context/base/mkiv/font-imp-math.lua b/tex/context/base/mkiv/font-imp-math.lua index d2294e93c..c0185ca34 100644 --- a/tex/context/base/mkiv/font-imp-math.lua +++ b/tex/context/base/mkiv/font-imp-math.lua @@ -108,7 +108,8 @@ function fonts.helpers.mathscriptslots(tfmdata,textcode) end end end -local function initialize(tfmdata,key,value) + +local function initialize(tfmdata,value) if value then local rawdata = tfmdata.shared.rawdata local rawresources = rawdata and rawdata.resources diff --git a/tex/context/base/mkiv/font-imp-tweaks.lua b/tex/context/base/mkiv/font-imp-tweaks.lua index 9cbda97fa..6d522e48b 100644 --- a/tex/context/base/mkiv/font-imp-tweaks.lua +++ b/tex/context/base/mkiv/font-imp-tweaks.lua @@ -10,10 +10,15 @@ if not context then return end local addfeature = fonts.handlers.otf.addfeature +-- The mapping directives avoids a check and copying of the (kind of special code +-- mapping tables. + addfeature { name = "uppercasing", type = "substitution", prepend = true, + mapping = true, + -- valid = function() return true end, data = characters.uccodes } @@ -21,5 +26,115 @@ addfeature { name = "lowercasing", type = "substitution", prepend = true, + mapping = true, + -- valid = function() return true end, data = characters.lccodes } + +if CONTEXTLMTXMODE > 0 then + + local nuts = nodes.nuts + local isnextchar = nuts.isnextchar + local getdisc = nuts.getdisc + local setchar = nuts.setchar + + local disc_code = nodes.nodecodes.disc + + local lccodes = characters.lccodes + local uccodes = characters.uccodes + + function fonts.handlers.otf.handlers.ctx_camelcasing(head,dataset,sequence,initialrl,font,dynamic) + local first = false + local current = head + -- local scale = 1000 + -- local xscale = 1000 + -- local yscale = 1000 + local function check(current) + while current do + -- scale, xscale, yscale = getscales(current) + local nxt, char, id = isnextchar(current,font,dynamic) -- ,scale,xscale,yscale) + if char then + if first then + local lower = lccodes[char] + if lower ~= char then + setchar(current,lower) + end + else + local upper = uccodes[char] + if upper ~= char then + setchar(current,upper) + end + first = true + end + elseif id == disc_code then + local pre, post, replace = getdisc(current) + if pre then + check(pre) + end + if post then + check(post) + end + if replace then + check(replace) + end + else + first = false + end + current = nxt + end + end + check(current) + return head + end + + addfeature { + nocheck = true, + name = "camelcasing", + type = "ctx_camelcasing", + prepend = true, + data = "action", + } + +end + +do -- for the moment this is mostly a demo feature + + local digit = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" } + local single = { "'" } + local double = { '"' } + + local singleprime = 0x2032 -- "′" + local doubleprime = 0x2033 -- "″" + + addfeature { + -- nocheck = true, + name = "primes", + type = "chainsubstitution", + lookups = { + { + type = "substitution", + data = { ["'"] = singleprime }, + }, + { + type = "substitution", + data = { ["'"] = doubleprime }, + }, + }, + data = { + rules = { + { + before = { digit }, + current = { single }, + after = { digit }, + lookups = { 1 }, + }, + { + before = { digit }, + current = { single, single }, + lookups = { 2, 0 }, -- zero: gsub_remove + }, + }, + }, + } + +end diff --git a/tex/context/base/mkiv/font-osd.lua b/tex/context/base/mkiv/font-osd.lua index 2d0e685c1..a9ea878c0 100644 --- a/tex/context/base/mkiv/font-osd.lua +++ b/tex/context/base/mkiv/font-osd.lua @@ -118,7 +118,7 @@ local setstate = nuts.setstate local ischar = nuts.ischar -local insertnodeafter = nuts.insertafter +local insertnodeafter = nuts.insertafter local copy_node = nuts.copy local remove_node = nuts.remove local flushlist = nuts.flushlist @@ -130,7 +130,8 @@ local unsetvalue = attributes.unsetvalue local fontdata = fonts.hashes.identifiers -local a_syllabe = attributes.private('syllabe') +local a_syllabe = "syllable" -- attributes.private('syllabe') -- can be just a property key +local a_reordered = "reordered" -- attributes.private('reordered') -- can be just a property key local dotted_circle = 0x25CC local c_nbsp = 0x00A0 @@ -1332,7 +1333,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) if getchar(base) == c_nbsp then nbspaces = nbspaces - 1 if base == stop then - stop = getprev(stop) + stop = getprev(stop) end head = remove_node(head,base) flushnode(base) @@ -1514,7 +1515,7 @@ function handlers.devanagari_reorder_reph(head,start) start = startnext startattr = getprop(start,a_syllabe) break - elseif not c and ( vowel_modifier[char] or stress_tone_mark[char] ) then + elseif not c and (vowel_modifier[char] or stress_tone_mark[char]) then c = current end current = getnext(current) @@ -1616,10 +1617,8 @@ end -- return head, start, done -- end -local reordered_pre_base_reordering_consonants = { } -- shared ? not reset ? - function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) - if reordered_pre_base_reordering_consonants[start] then + if getprop(start,a_reordered) then return head, start, true end local current = start -- we could cache attributes here @@ -1643,7 +1642,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) setlink(start,next) setlink(current,start) -- setlink(current,start,next) -- maybe - reordered_pre_base_reordering_consonants[start] = true + setprop(start,"reordered",true) start = startnext return head, start, true -- elseif consonant[char] and (not getstate(current) or getstate(current,s_init)) then @@ -1679,7 +1678,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) setlink(getprev(current),start) setlink(start,current) end - reordered_pre_base_reordering_consonants[start] = true + setprop(start,"reordered",true) start = startnext break end @@ -2251,20 +2250,20 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe local already_below_mark -- = false local already_post_mark -- = false while dependent_vowel[v] do - local vowels = twopart_mark[v] or { v } - for k, v in next, vowels do - if pre_mark[v] and not already_pre_mark then - already_pre_mark = true - elseif above_mark[v] and not already_above_mark then - already_above_mark = true - elseif below_mark[v] and not already_below_mark then - already_below_mark = true - elseif post_mark[v] and not already_post_mark then - already_post_mark = true - else - return c - end - end + local vowels = twopart_mark[v] or { v } + for k, v in next, vowels do + if pre_mark[v] and not already_pre_mark then + already_pre_mark = true + elseif above_mark[v] and not already_above_mark then + already_above_mark = true + elseif below_mark[v] and not already_below_mark then + already_below_mark = true + elseif post_mark[v] and not already_post_mark then + already_post_mark = true + else + return c + end + end c = getnext(c) n = getnext(c) if not n then @@ -2440,21 +2439,21 @@ local function analyze_next_chars_two(c,font) local already_above_mark -- = false local already_below_mark -- = false local already_post_mark -- = false - while dependent_vowel[v] do - local vowels = twopart_mark[v] or { v } - for k, v in next, vowels do - if pre_mark[v] and not already_pre_mark then - already_pre_mark = true - elseif above_mark[v] and not already_above_mark then - already_above_mark = true - elseif below_mark[v] and not already_below_mark then - already_below_mark = true - elseif post_mark[v] and not already_post_mark then - already_post_mark = true - else - return c - end - end + while dependent_vowel[v] do + local vowels = twopart_mark[v] or { v } + for k, v in next, vowels do + if pre_mark[v] and not already_pre_mark then + already_pre_mark = true + elseif above_mark[v] and not already_above_mark then + already_above_mark = true + elseif below_mark[v] and not already_below_mark then + already_below_mark = true + elseif post_mark[v] and not already_post_mark then + already_post_mark = true + else + return c + end + end c = n n = getnext(c) if not n then @@ -2731,15 +2730,15 @@ local function method_one(head,font,attr) while current do local char = ischar(current,font) if char then - if n == 0 and not getstate(current) then - setstate(current,s_init) - end - n = n + 1 - else - n = 0 - end - current = getnext(current) - end + if n == 0 and not getstate(current) then + setstate(current,s_init) + end + n = n + 1 + else + n = 0 + end + current = getnext(current) + end return head, done end @@ -2841,15 +2840,15 @@ local function method_two(head,font,attr) while current do local char = ischar(current,font) if char then - if n == 0 and not getstate(current) then -- state can also be init - setstate(current,s_init) - end - n = n + 1 - else - n = 0 - end - current = getnext(current) - end + if n == 0 and not getstate(current) then -- state can also be init + setstate(current,s_init) + end + n = n + 1 + else + n = 0 + end + current = getnext(current) + end return head, done end diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua index 2643d022a..2c955dbce 100644 --- a/tex/context/base/mkiv/font-otc.lua +++ b/tex/context/base/mkiv/font-otc.lua @@ -102,8 +102,9 @@ local function validspecification(specification,name) specification = { dataset = dataset } else dataset = { { data = specification.data } } - specification.data = nil - specification.dataset = dataset + specification.data = nil + specification.coverage = dataset + specification.dataset = dataset end local first = dataset[1] if first then @@ -232,6 +233,7 @@ local function addfeature(data,feature,specifications) local unicode = tounicode(code) local description = descriptions[unicode] if not nocheck and not description then + -- todo: trace ! skip = skip + 1 else if type(replacement) == "table" then @@ -436,7 +438,30 @@ local function addfeature(data,feature,specifications) local prepare_single = prepare_pair -- we could have a better test on the spec - local function prepare_chain(list,featuretype,sublookups) + local function hassteps(lookups) + if lookups then + for i=1,#lookups do + local l = lookups[i] + if l then + for j=1,#l do + local l = l[j] + if l then + local n = l.nofsteps + if not n then + -- gsub_remove + return true + elseif n > 0 then + return true + end + end + end + end + end + end + return false + end + + local function prepare_chain(list,featuretype,sublookups,nocheck) -- todo: coveractions local rules = list.rules local coverage = { } @@ -473,6 +498,7 @@ local function addfeature(data,feature,specifications) local lookups = rule.lookups or false local subtype = nil if lookups and sublookups then + local l = { } for k, v in sortedhash(lookups) do local t = type(v) if t == "table" then @@ -483,58 +509,66 @@ local function addfeature(data,feature,specifications) v[i] = { vi } end end + l[k] = v elseif t == "number" then local lookup = sublookups[v] if lookup then - lookups[k] = { lookup } + l[k] = { lookup } if not subtype then subtype = lookup.type end elseif v == 0 then - lookups[k] = { { type = "gsub_remove" } } + l[k] = { { type = "gsub_remove", nosteps = true } } else - lookups[k] = false -- { false } -- new + l[k] = false -- { false } -- new end else - lookups[k] = false -- { false } -- new + l[k] = false -- { false } -- new end end + if nocheck then + -- fragile + rule.lookups = l --no, because checking can spoil it + end + lookups = l end if nofsequences > 0 then -- we merge coverage into one -- we copy as we can have different fonts - local hashed = { } - for i=1,nofsequences do - local t = { } - local s = sequence[i] - for i=1,#s do - local u = tounicode(s[i]) - if u then - t[u] = true + if hassteps(lookups) then + local hashed = { } + for i=1,nofsequences do + local t = { } + local s = sequence[i] + for i=1,#s do + local u = tounicode(s[i]) + if u then + t[u] = true + end end + hashed[i] = t end - hashed[i] = t - end - sequence = hashed - -- now we create the rule - rulesize = rulesize + 1 - rulehash[rulesize] = { - nofrules, -- 1 - lookuptype, -- 2 - sequence, -- 3 - start, -- 4 - stop, -- 5 - lookups, -- 6 (6/7 also signal of what to do) - replacements, -- 7 - subtype, -- 8 - } --- for unic in next, sequence[start] do - for unic in sortedhash(sequence[start]) do - local cu = coverage[unic] - if not cu then - coverage[unic] = rulehash -- can now be done cleaner i think + sequence = hashed + rulesize = rulesize + 1 + rulehash[rulesize] = { + nofrules, -- 1 + lookuptype, -- 2 + sequence, -- 3 + start, -- 4 + stop, -- 5 + lookups, -- 6 (6/7 also signal of what to do) + replacements, -- 7 + subtype, -- 8 + } + for unic in sortedhash(sequence[start]) do + local cu = coverage[unic] + if not cu then + coverage[unic] = rulehash -- can now be done cleaner i think + end end + sequence.n = nofsequences + else + -- report_otf("no steps for %a",lookuptype) -- e.g. in primes feature end - sequence.n = nofsequences end end rulehash.n = rulesize @@ -626,133 +660,164 @@ local function addfeature(data,feature,specifications) end local askedfeatures = specification.features or everywhere local askedsteps = specification.steps or specification.subtables or { specification.data } or { } - local featuretype = normalized[specification.type or "substitution"] or "substitution" + local featuretype = specification.type or "substitution" + local featureaction = false local featureflags = specification.flags or noflags local nocheck = specification.nocheck + local mapping = specification.mapping local featureorder = specification.order or { feature } local featurechain = (featuretype == "chainsubstitution" or featuretype == "chainposition") and 1 or 0 local nofsteps = 0 local steps = { } local sublookups = specification.lookups local category = nil + local steptype = nil + local sequence = nil + -- + if fonts.handlers.otf.handlers[featuretype] then + featureaction = true -- function based + else + featuretype = normalized[specification.type or "substitution"] or "substitution" + end -- checkflags(specification,resources) -- - if sublookups then - local s = { } - for i=1,#sublookups do - local specification = sublookups[i] - local askedsteps = specification.steps or specification.subtables or { specification.data } or { } - local featuretype = normalized[specification.type or "substitution"] or "substitution" - local featureflags = specification.flags or noflags - local nofsteps = 0 - local steps = { } - for i=1,#askedsteps do - local list = askedsteps[i] - local coverage = nil - local format = nil - if featuretype == "substitution" then - coverage = prepare_substitution(list,featuretype,nocheck) - elseif featuretype == "ligature" then - coverage = prepare_ligature(list,featuretype,nocheck) - elseif featuretype == "alternate" then - coverage = prepare_alternate(list,featuretype,nocheck) - elseif featuretype == "multiple" then - coverage = prepare_multiple(list,featuretype,nocheck) - elseif featuretype == "kern" or featuretype == "move" then - format = featuretype - coverage = prepare_kern(list,featuretype) - elseif featuretype == "pair" then - format = "pair" - coverage = prepare_pair(list,featuretype) - elseif featuretype == "single" then - format = "single" - coverage = prepare_single(list,featuretype) - end - if coverage and next(coverage) then - nofsteps = nofsteps + 1 - steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) + for k, v in next, askedfeatures do + if v[1] then + askedfeatures[k] = tohash(v) + end + end + -- + if featureflags[1] then featureflags[1] = "mark" end + if featureflags[2] then featureflags[2] = "ligature" end + if featureflags[3] then featureflags[3] = "base" end + -- + if featureaction then + + category = "gsub" + sequence = { + features = { [feature] = askedfeatures }, + flags = featureflags, + name = feature, -- redundant + order = featureorder, + type = featuretype, + -- steps = { }, + nofsteps = 0, -- just in case we test for that + } + + else + + if sublookups then + local s = { } + for i=1,#sublookups do + local specification = sublookups[i] + local askedsteps = specification.steps or specification.subtables or { specification.data } or { } + local featuretype = normalized[specification.type or "substitution"] or "substitution" + local featureflags = specification.flags or noflags + local nofsteps = 0 + local steps = { } + for i=1,#askedsteps do + local list = askedsteps[i] + local coverage = nil + local format = nil + if featuretype == "substitution" then + coverage = prepare_substitution(list,featuretype,nocheck) + elseif featuretype == "ligature" then + coverage = prepare_ligature(list,featuretype,nocheck) + elseif featuretype == "alternate" then + coverage = prepare_alternate(list,featuretype,nocheck) + elseif featuretype == "multiple" then + coverage = prepare_multiple(list,featuretype,nocheck) + elseif featuretype == "kern" or featuretype == "move" then + format = featuretype + coverage = prepare_kern(list,featuretype) + elseif featuretype == "pair" then + format = "pair" + coverage = prepare_pair(list,featuretype) + elseif featuretype == "single" then + format = "single" + coverage = prepare_single(list,featuretype) + end + if coverage and next(coverage) then + nofsteps = nofsteps + 1 + steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) + end end + -- + checkmerge(specification) + checksteps(specification) + -- + s[i] = { + [stepkey] = steps, + nofsteps = nofsteps, + flags = featureflags, + type = types[featuretype], + } + end + sublookups = s + end + + for i=1,#askedsteps do + local list = askedsteps[i] + local coverage = nil + local format = nil + if featuretype == "substitution" then + -- see font-imp-tweaks: we directly pass a mapping so no checks done + category = "gsub" + coverage = (mapping and list) or prepare_substitution(list,featuretype,nocheck) + elseif featuretype == "ligature" then + category = "gsub" + coverage = prepare_ligature(list,featuretype,nocheck) + elseif featuretype == "alternate" then + category = "gsub" + coverage = prepare_alternate(list,featuretype,nocheck) + elseif featuretype == "multiple" then + category = "gsub" + coverage = prepare_multiple(list,featuretype,nocheck) + elseif featuretype == "kern" or featuretype == "move" then + category = "gpos" + format = featuretype + coverage = prepare_kern(list,featuretype) + elseif featuretype == "pair" then + category = "gpos" + format = "pair" + coverage = prepare_pair(list,featuretype) + elseif featuretype == "single" then + category = "gpos" + format = "single" + coverage = prepare_single(list,featuretype) + elseif featuretype == "chainsubstitution" then + category = "gsub" + coverage = prepare_chain(list,featuretype,sublookups,nocheck) + elseif featuretype == "chainposition" then + category = "gpos" + coverage = prepare_chain(list,featuretype,sublookups,nocheck) + else + report_otf("not registering feature %a, unknown category",feature) + return end - -- - checkmerge(specification) - checksteps(specification) - -- - s[i] = { + if coverage and next(coverage) then + nofsteps = nofsteps + 1 + steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) + end + end + + if nofsteps > 0 then + sequence = { + chain = featurechain, + features = { [feature] = askedfeatures }, + flags = featureflags, + name = feature, -- redundant + order = featureorder, [stepkey] = steps, nofsteps = nofsteps, - flags = featureflags, type = types[featuretype], } end - sublookups = s end - for i=1,#askedsteps do - local list = askedsteps[i] - local coverage = nil - local format = nil - if featuretype == "substitution" then - category = "gsub" - coverage = prepare_substitution(list,featuretype,nocheck) - elseif featuretype == "ligature" then - category = "gsub" - coverage = prepare_ligature(list,featuretype,nocheck) - elseif featuretype == "alternate" then - category = "gsub" - coverage = prepare_alternate(list,featuretype,nocheck) - elseif featuretype == "multiple" then - category = "gsub" - coverage = prepare_multiple(list,featuretype,nocheck) - elseif featuretype == "kern" or featuretype == "move" then - category = "gpos" - format = featuretype - coverage = prepare_kern(list,featuretype) - elseif featuretype == "pair" then - category = "gpos" - format = "pair" - coverage = prepare_pair(list,featuretype) - elseif featuretype == "single" then - category = "gpos" - format = "single" - coverage = prepare_single(list,featuretype) - elseif featuretype == "chainsubstitution" then - category = "gsub" - coverage = prepare_chain(list,featuretype,sublookups) - elseif featuretype == "chainposition" then - category = "gpos" - coverage = prepare_chain(list,featuretype,sublookups) - else - report_otf("not registering feature %a, unknown category",feature) - return - end - if coverage and next(coverage) then - nofsteps = nofsteps + 1 - steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) - end - end - if nofsteps > 0 then + + if sequence then -- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... } - for k, v in next, askedfeatures do - if v[1] then - askedfeatures[k] = tohash(v) - end - end - -- - if featureflags[1] then featureflags[1] = "mark" end - if featureflags[2] then featureflags[2] = "ligature" end - if featureflags[3] then featureflags[3] = "base" end - local steptype = types[featuretype] - local sequence = { - chain = featurechain, - features = { [feature] = askedfeatures }, - flags = featureflags, - name = feature, -- redundant - order = featureorder, - [stepkey] = steps, - nofsteps = nofsteps, - type = steptype, - } - -- checkflags(sequence,resources) checkmerge(sequence) checksteps(sequence) @@ -782,11 +847,13 @@ local function addfeature(data,feature,specifications) end end end + end end if trace_loading then report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip) end + end otf.enhancers.addfeature = addfeature diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua index 6b564e4c1..eadf05890 100644 --- a/tex/context/base/mkiv/font-otl.lua +++ b/tex/context/base/mkiv/font-otl.lua @@ -314,7 +314,7 @@ local function copytotfm(data,cache_id) local properties = derivetable(data.properties) local descriptions = derivetable(data.descriptions) local goodies = derivetable(data.goodies) - local characters = { } + local characters = { } -- newtable if we knwo how many local parameters = { } local mathparameters = { } -- diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua index 4b154b256..2f8934508 100644 --- a/tex/context/base/mkiv/font-otr.lua +++ b/tex/context/base/mkiv/font-otr.lua @@ -1250,7 +1250,7 @@ readers.post = function(f,fontdata,specification) local version = readulong(f) fontdata.postscript = { version = version, - italicangle = round(1000*readfixed(f))/1000, + italicangle = readfixed(f), underlineposition = readfword(f), underlinethickness = readfword(f), monospaced = readulong(f), diff --git a/tex/context/base/mkiv/grph-img.lua b/tex/context/base/mkiv/grph-img.lua index 0dc5efa70..a982965ff 100644 --- a/tex/context/base/mkiv/grph-img.lua +++ b/tex/context/base/mkiv/grph-img.lua @@ -16,7 +16,7 @@ local round = math.round local concat = table.concat local suffixonly = file.suffix -local newreader = io.newreader +local newreader = io.newreader -- needs checking 0/1 based local setmetatableindex = table.setmetatableindex local setmetatablecall = table.setmetatablecall diff --git a/tex/context/base/mkiv/l-gzip.lua b/tex/context/base/mkiv/l-gzip.lua index f141b5ebb..aadb781da 100644 --- a/tex/context/base/mkiv/l-gzip.lua +++ b/tex/context/base/mkiv/l-gzip.lua @@ -5,176 +5,4 @@ if not modules then modules = { } end modules ['l-gzip'] = { license = "see context related readme files" } --- We only have a few official methods here: --- --- local decompressed = gzip.load (filename) --- local resultsize = gzip.save (filename,compresslevel) --- local compressed = gzip.compress (str,compresslevel) --- local decompressed = gzip.decompress (str) --- local iscompressed = gzip.compressed (str) --- local suffix, okay = gzip.suffix (filename) --- --- In LuaMetaTeX we have only xzip which implements a very few methods: --- --- compress (str,level,method,window,memory,strategy) --- decompress (str,window) --- adler32 (str,checksum) --- crc32 (str,checksum) --- --- Special window values are: --- --- flate : - 15 --- zlib : 15 --- gzip : 15 | 16 --- auto : 15 | 32 - -gzip = gzip or { } -- so in luatex we keep the old ones too - -if not zlib then - zlib = xzip -- in luametatex we shadow the old one -elseif not xzip then - xzip = zlib -end - -if zlib then - - local suffix = file.suffix - local suffixes = file.suffixes - local find = string.find - local openfile = io.open - - local gzipwindow = 15 + 16 -- +16: gzip, +32: gzip|zlib - local gziplevel = 3 - local identifier = "^\x1F\x8B\x08" - - local compress = zlib.compress - local decompress = zlib.decompress - - function gzip.load(filename) - local f = openfile(filename,"rb") - if not f then - -- invalid file - else - local data = f:read("*all") - f:close() - if data and data ~= "" then - if suffix(filename) == "gz" then - data = decompress(data,gzipwindow) - end - return data - end - end - end - - function gzip.save(filename,data,level) - if suffix(filename) ~= "gz" then - filename = filename .. ".gz" - end - local f = openfile(filename,"wb") - if f then - data = compress(data or "",level or gziplevel,nil,gzipwindow) - f:write(data) - f:close() - return #data - end - end - - function gzip.suffix(filename) - local suffix, extra = suffixes(filename) - local gzipped = extra == "gz" - return suffix, gzipped - end - - function gzip.compressed(s) - return s and find(s,identifier) - end - - function gzip.compress(s,level) - if s and not find(s,identifier) then -- the find check might go away - if not level then - level = gziplevel - elseif level <= 0 then - return s - elseif level > 9 then - level = 9 - end - return compress(s,level or gziplevel,nil,gzipwindow) or s - end - end - - function gzip.decompress(s) - if s and find(s,identifier) then - return decompress(s,gzipwindow) - else - return s - end - end - -end - --- In luametatex we can use this one but it doesn't look like there wil be stream --- support so for now we still use zlib (the performance difference is not that --- spectacular in our usage. - --- if flate then --- --- local type = type --- local find = string.find --- --- local compress = flate.gz_compress --- local decompress = flate.gz_decompress --- --- local absmax = 128*1024*1024 --- local initial = 64*1024 --- local identifier = "^\x1F\x8B\x08" --- --- function gzip.compressed(s) --- return s and find(s,identifier) --- end --- --- function gzip.compress(s,level) --- if s and not find(s,identifier) then -- the find check might go away --- if not level then --- level = 3 --- elseif level <= 0 then --- return s --- elseif level > 9 then --- level = 9 --- end --- return compress(s,level) or s --- end --- end --- --- function gzip.decompress(s,size,iterate) --- if s and find(s,identifier) then --- if type(size) ~= "number" then --- size = initial --- end --- if size > absmax then --- size = absmax --- end --- if type(iterate) == "number" then --- max = size * iterate --- elseif iterate == nil or iterate == true then --- iterate = true --- max = absmax --- end --- if max > absmax then --- max = absmax --- end --- while true do --- local d = decompress(s,size) --- if d then --- return d --- end --- size = 2 * size --- if not iterate or size > max then --- return false --- end --- end --- else --- return s --- end --- end --- --- end +-- now in util-zip diff --git a/tex/context/base/mkiv/l-lpeg.lua b/tex/context/base/mkiv/l-lpeg.lua index 50306e4ab..77e5cf12d 100644 --- a/tex/context/base/mkiv/l-lpeg.lua +++ b/tex/context/base/mkiv/l-lpeg.lua @@ -665,12 +665,12 @@ end -- lpeg.print(lpeg.P("a","b","c")) -- lpeg.print(lpeg.S("a","b","c")) --- print(lpeg.count("äáà a",lpeg.P("á") + lpeg.P("à "))) --- print(lpeg.count("äáà a",lpeg.UP("áà "))) --- print(lpeg.count("äáà a",lpeg.US("à á"))) --- print(lpeg.count("äáà a",lpeg.UR("aá"))) --- print(lpeg.count("äáà a",lpeg.UR("à á"))) --- print(lpeg.count("äáà a",lpeg.UR(0x0000,0xFFFF))) +-- print(lpeg.counter("äáà a",lpeg.P("á") + lpeg.P("à "))) +-- print(lpeg.counter("äáà a",lpeg.UP("áà "))) +-- print(lpeg.counter("äáà a",lpeg.US("à á"))) +-- print(lpeg.counter("äáà a",lpeg.UR("aá"))) +-- print(lpeg.counter("äáà a",lpeg.UR("à á"))) +-- print(lpeg.counter("äáà a",lpeg.UR(0x0000,0xFFFF))) function lpeg.is_lpeg(p) return p and lpegtype(p) == "pattern" diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua index c7584ccce..06cc35a79 100644 --- a/tex/context/base/mkiv/l-os.lua +++ b/tex/context/base/mkiv/l-os.lua @@ -187,7 +187,7 @@ local execute = os.execute local iopopen = io.popen local function resultof(command) - local handle = iopopen(command,"r") -- already has flush + local handle = iopopen(command,"rb") -- already has flush, b is new ! if handle then local result = handle:read("*all") or "" handle:close() diff --git a/tex/context/base/mkiv/lang-ini.lua b/tex/context/base/mkiv/lang-ini.lua index c8b5ee158..e286233bc 100644 --- a/tex/context/base/mkiv/lang-ini.lua +++ b/tex/context/base/mkiv/lang-ini.lua @@ -158,11 +158,16 @@ local function sethjcodes(instance,loaded,what,factor) loaded.codehash = h end -- - local function setcode(l) - local u = uccodes[l] + local function setcode(code) + local l = lccodes[code] -- just in case we get a mixture + local u = uccodes[code] -- just in case we get a mixture local s = l + if type(s) ~= "number" then + l = code + s = code + end if hjcounts then - local c = hjcounts[l] + local c = hjcounts[s] if c then c = c.count if not c then @@ -183,14 +188,14 @@ local function sethjcodes(instance,loaded,what,factor) h[l] = s if u ~= l and type(u) == "number" then sethjcode(instance,u,s) - h[u] = lccodes[l] + h[u] = s end end -- local s = tex.savinghyphcodes tex.savinghyphcodes = 0 if type(c) == "table" then - for l in next, c do + for l in sortedhash(c) do setcode(utfbyte(l)) end else diff --git a/tex/context/base/mkiv/luat-cnf.lua b/tex/context/base/mkiv/luat-cnf.lua index 550fa5892..7bb70ce20 100644 --- a/tex/context/base/mkiv/luat-cnf.lua +++ b/tex/context/base/mkiv/luat-cnf.lua @@ -261,4 +261,4 @@ local function makestub() logs.newline() end -lua.registerfinalizer(makestub,"create stub file") +lua.registerinitexfinalizer(makestub,"create stub file") diff --git a/tex/context/base/mkiv/luat-cod.lua b/tex/context/base/mkiv/luat-cod.lua index 25c716eeb..6175302a3 100644 --- a/tex/context/base/mkiv/luat-cod.lua +++ b/tex/context/base/mkiv/luat-cod.lua @@ -90,28 +90,6 @@ function lua.registercode(filename,options) end end -local finalizers = { } - -function lua.registerfinalizer(f,comment) - comment = comment or "unknown" - if type(f) == "function" then - finalizers[#finalizers+1] = { action = f, comment = comment } - else - print(format("\nfatal error: invalid finalizer, action: %s\n",comment)) - os.exit() - end -end - -function lua.finalize(logger) - for i=1,#finalizers do - local finalizer = finalizers[i] - finalizer.action() - if logger then - logger("finalize action: %s",finalizer.comment) - end - end -end - -- A first start with environments. This will be overloaded later. environment = environment or { } @@ -168,6 +146,38 @@ environment.jitsupported = JITSUPPORTED environment.initex = INITEXMODE environment.initexmode = INITEXMODE +if INITEXMODE then + + local finalizers = { } + + function lua.registerinitexfinalizer(f,comment) + comment = comment or "unknown" + if type(f) == "function" then + finalizers[#finalizers+1] = { action = f, comment = comment } + else + print(format("\nfatal error: invalid finalizer, action: %s\n",comment)) + os.exit() + end + end + + function lua.finalizeinitex(logger) + for i=1,#finalizers do + local finalizer = finalizers[i] + finalizer.action() + if logger then + logger("finalize action: %s",finalizer.comment) + end + end + end + +else + + function lua.registerinitexfinalizer() end + function lua.finalizeinitex () end + +end + + if not environment.luafilechunk then function environment.luafilechunk(filename) diff --git a/tex/context/base/mkiv/luat-lib.mkiv b/tex/context/base/mkiv/luat-lib.mkiv index f6bab870b..2879ca62a 100644 --- a/tex/context/base/mkiv/luat-lib.mkiv +++ b/tex/context/base/mkiv/luat-lib.mkiv @@ -53,13 +53,14 @@ \registerctxluafile{data-res}{} \registerctxluafile{data-inp}{} \registerctxluafile{data-out}{} -\registerctxluafile{data-fil}{} % opener gets overloaded in data-tex +\registerctxluafile{data-fil}{autosuffix} % opener gets overloaded in data-tex \registerctxluafile{data-pre}{} % after data-res \registerctxluafile{data-bin}{} % before data-tex \registerctxluafile{data-tex}{} % after data-pre \registerctxluafile{data-vir}{} \registerctxluafile{data-zip}{} +%registerctxluafile{data-tar}{} %registerctxluafile{data-crl}{} \registerctxluafile{data-sch}{} \registerctxluafile{data-tre}{} diff --git a/tex/context/base/mkiv/luat-run.lua b/tex/context/base/mkiv/luat-run.lua index 874287ee1..c778ad094 100644 --- a/tex/context/base/mkiv/luat-run.lua +++ b/tex/context/base/mkiv/luat-run.lua @@ -106,7 +106,7 @@ local function pre_dump_actions() for i=1,#dumpactions do dumpactions[i]() end - lua.finalize(trace_lua_dump and report_lua or nil) + lua.finalizeinitex(trace_lua_dump and report_lua or nil) end local function wrapup_synctex() diff --git a/tex/context/base/mkiv/luat-sto.lua b/tex/context/base/mkiv/luat-sto.lua index feb546400..be5134b84 100644 --- a/tex/context/base/mkiv/luat-sto.lua +++ b/tex/context/base/mkiv/luat-sto.lua @@ -90,7 +90,7 @@ if environment.initex then storage.max = max end - lua.registerfinalizer(dump,"dump storage") + lua.registerinitexfinalizer(dump,"dump storage") end diff --git a/tex/context/base/mkiv/lxml-ini.lua b/tex/context/base/mkiv/lxml-ini.lua index 6524670fc..980a83f1a 100644 --- a/tex/context/base/mkiv/lxml-ini.lua +++ b/tex/context/base/mkiv/lxml-ini.lua @@ -205,7 +205,6 @@ if CONTEXTLMTXMODE > 0 then end } - implement { name = "ifxmlempty", public = true, diff --git a/tex/context/base/mkiv/lxml-tex.lua b/tex/context/base/mkiv/lxml-tex.lua index 148484f51..95fafafac 100644 --- a/tex/context/base/mkiv/lxml-tex.lua +++ b/tex/context/base/mkiv/lxml-tex.lua @@ -2085,11 +2085,11 @@ do local e = getid(id) if e then local at = e.at - if at and at[a] ~= "" then - return true - end + att = at and at[a] or "" + else + att = "" end - return false + return att == "" end function lxml.refatt(id,a) diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua index 2b2173ae9..8132c6094 100644 --- a/tex/context/base/mkiv/mult-low.lua +++ b/tex/context/base/mkiv/mult-low.lua @@ -97,6 +97,12 @@ return { "mmodeifcode", "innerifcode", "voidifcode", "hboxifcode", "vboxifcode", "xifcode", "eofifcode", "trueifcode", "falseifcode", "caseifcode", "definedifcode", "csnameifcode", "fontcharifcode", -- + "overrulemathcontrolcode", "underrulemathcontrolcode", "radicalrulemathcontrolcode", "fractionrulemathcontrolcode", + "accentskewhalfmathcontrolcode", "accentskewapplymathcontrolcode", "accentitalickernmathcontrolcode", + "delimiteritalickernmathcontrolcode", "orditalickernmathcontrolcode", "charitalicwidthmathcontrolcode", + "charitalicnoreboxmathcontrolcode", "boxednoitalickernmathcontrolcode", "nostaircasekernmathcontrolcode", + "textitalickernmathcontrolcode", + -- "fontslantperpoint", "fontinterwordspace", "fontinterwordstretch", "fontinterwordshrink", "fontexheight", "fontemwidth", "fontextraspace", "slantperpoint", "mathexheight", "mathemwidth", @@ -177,6 +183,8 @@ return { "frozenflagcode", "tolerantflagcode", "protectedflagcode", "primitiveflagcode", "permanentflagcode", "noalignedflagcode", "immutableflagcode", "mutableflagcode", "globalflagcode", "overloadedflagcode", "immediateflagcode", "conditionalflagcode", "valueflagcode", "instanceflagcode", -- + "ordflattencode", "binflattencode", "relflattencode", "punctflattencode", "innerflattencode", + -- "prewordcode", "postwordcode", -- "continuewhenlmtxmode" @@ -563,6 +571,8 @@ return { -- "suggestedalias", -- + "showboxhere", + -- "newlocalcount", "newlocaldimen", "newlocalskip", "newlocalmuskip", "newlocaltoks", "newlocalbox", "newlocalwrite", "newlocalread", "setnewlocalcount", "setnewlocaldimen", "setnewlocalskip", "setnewlocalmuskip", "setnewlocaltoks", "setnewlocalbox", diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua index 6338bff40..2cb38e8a3 100644 --- a/tex/context/base/mkiv/mult-prm.lua +++ b/tex/context/base/mkiv/mult-prm.lua @@ -32,14 +32,11 @@ return { "iffontchar", "interactionmode", "interlinepenalties", - "lastchkdim", - "lastchknum", "lastlinefit", "lastnodetype", "marks", "muexpr", "mutoglue", - "numericscale", "numexpr", "pagediscards", "parshapedimen", @@ -120,6 +117,10 @@ return { "Umathdelimiterovervariant", "Umathdelimiterundervariant", "Umathdenominatorvariant", + "Umathextrasubpreshift", + "Umathextrasubshift", + "Umathextrasuppreshift", + "Umathextrasupshift", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", @@ -318,9 +319,11 @@ return { "explicithyphenpenalty", "firstvalidlanguage", "fontid", + "fontmathcontrol", "fontspecifiedsize", "formatname", "frozen", + "futurecsname", "futuredef", "futureexpand", "futureexpandis", @@ -396,6 +399,8 @@ return { "instance", "integerdef", "lastarguments", + "lastchkdim", + "lastchknum", "lastnamedcs", "lastnodesubtype", "leftmarginkern", @@ -423,11 +428,13 @@ return { "luatexbanner", "luatexrevision", "luatexversion", + "mathcontrolmode", "mathdelimitersmode", "mathdirection", "mathdisplayskipmode", "matheqnogapstep", "mathflattenmode", + "mathfontcontrol", "mathitalicsmode", "mathnolimitsmode", "mathpenaltiesmode", @@ -450,6 +457,7 @@ return { "normalizelinemode", "nospaces", "novrule", + "numericscale", "orelse", "orunless", "outputbox", @@ -492,6 +500,7 @@ return { "undent", "unletfrozen", "unletprotected", + "untraced", "vpack", "wordboundary", "wrapuppar", diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua index 408f8ea47..5c669f9da 100644 --- a/tex/context/base/mkiv/node-res.lua +++ b/tex/context/base/mkiv/node-res.lua @@ -590,7 +590,7 @@ statistics.register("node memory usage", function() -- comes after cleanup ! end end) -lua.registerfinalizer(cleanup, "cleanup reserved nodes") +lua.registerinitexfinalizer(cleanup, "cleanup reserved nodes") -- experiment diff --git a/tex/context/base/mkiv/node-syn.lua b/tex/context/base/mkiv/node-syn.lua index 8b8b628dd..4014445b0 100644 --- a/tex/context/base/mkiv/node-syn.lua +++ b/tex/context/base/mkiv/node-syn.lua @@ -231,8 +231,8 @@ local blockedsuffixes = { -- lfg = true, } -local sttags = table.setmetatableindex(function(t,name) - name = collapsepath(name) +local sttags = table.setmetatableindex(function(t,fullname) + local name = collapsepath(fullname) if blockedsuffixes[suffixonly(name)] then -- Just so that I don't get the ones on my development tree. nofblocked = nofblocked + 1 @@ -248,6 +248,9 @@ local sttags = table.setmetatableindex(function(t,name) else noftags = noftags + 1 t[name] = noftags + if name ~= fullname then + t[fullname] = noftags + end stnums[noftags] = name return noftags end diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 2558e805e..4c0c46993 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex dcbc15681..ca29ed3a5 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/supp-box.lua b/tex/context/base/mkiv/supp-box.lua index 4b9322ba7..2e7ca5924 100644 --- a/tex/context/base/mkiv/supp-box.lua +++ b/tex/context/base/mkiv/supp-box.lua @@ -171,7 +171,7 @@ implement { arguments = "integer", actions = function(n) -- we just hyphenate (as we pass a hpack) .. a bit too much casting but ... - local l = languages.hyphenators.handler(tonode(checkedlist(n))) + local l = languages.hyphenators.handler(checkedlist(n)) report_hyphenation("show: %s",listtoutf(l,false,true)) end } diff --git a/tex/context/base/mkiv/util-fil.lua b/tex/context/base/mkiv/util-fil.lua index 183f7bea8..0b20264ec 100644 --- a/tex/context/base/mkiv/util-fil.lua +++ b/tex/context/base/mkiv/util-fil.lua @@ -203,23 +203,23 @@ function files.readinteger4le(f) end function files.readfixed2(f) - local a, b = byte(f:read(2),1,2) - if a >= 0x80 then - tonumber((a - 0x100) .. "." .. b) - else - tonumber(( a ) .. "." .. b) + local n1, n2 = byte(f:read(2),1,2) + if n1 >= 0x80 then + n1 = n1 - 0x100 end + return n1 + n2/0xFF end -- (real) (n>>16) + ((n&0xffff)/65536.0)) but no cast in lua (we could use unpack) function files.readfixed4(f) local a, b, c, d = byte(f:read(4),1,4) - if a >= 0x80 then - tonumber((0x100 * a + b - 0x10000) .. "." .. (0x100 * c + d)) - else - tonumber((0x100 * a + b ) .. "." .. (0x100 * c + d)) + local n1 = 0x100 * a + b + local n2 = 0x100 * c + d + if n1 >= 0x8000 then + n1 = n1 - 0x10000 end + return n1 + n2/0xFFFF end -- (real) ((n<<16)>>(16+14)) + ((n&0x3fff)/16384.0)) diff --git a/tex/context/base/mkiv/util-sac.lua b/tex/context/base/mkiv/util-sac.lua index 522b0bc08..796a620ba 100644 --- a/tex/context/base/mkiv/util-sac.lua +++ b/tex/context/base/mkiv/util-sac.lua @@ -262,12 +262,11 @@ function streams.readfixed2(f) local i = f[2] local j = i + 1 f[2] = j + 1 - local a, b = byte(f[1],i,j) - if a >= 0x80 then - return tonumber((a - 0x100) .. "." .. b) or 0 - else - return tonumber((a ) .. "." .. b) or 0 + local n1, n2 = byte(f[1],i,j) + if n1 >= 0x80 then + n1 = n1 - 0x100 end + return n1 + n2/0xFF end function streams.readfixed4(f) @@ -275,11 +274,12 @@ function streams.readfixed4(f) local j = i + 3 f[2] = j + 1 local a, b, c, d = byte(f[1],i,j) - if a >= 0x80 then - return tonumber((0x100 * a + b - 0x10000) .. "." .. (0x100 * c + d)) or 0 - else - return tonumber((0x100 * a + b ) .. "." .. (0x100 * c + d)) or 0 + local n1 = 0x100 * a + b + local n2 = 0x100 * c + d + if n1 >= 0x8000 then + n1 = n1 - 0x10000 end + return n1 + n2/0xFFFF end if bit32 then @@ -507,10 +507,10 @@ do function io.newreader(str,method) local f, m if method == "string" then - f = openstring(str) + f = openstring(str,true) m = streams elseif method == "stream" then - f = openstream(str) + f = openstream(str,true) m = streams else f = openfile(str,"rb") @@ -522,6 +522,7 @@ do __index = function(t,k) local r = m[k] if k == "close" then + -- maybe use __toclose if f then m.close(f) f = nil diff --git a/tex/context/base/mkiv/util-tar.lua b/tex/context/base/mkiv/util-tar.lua new file mode 100644 index 000000000..0368a7db5 --- /dev/null +++ b/tex/context/base/mkiv/util-tar.lua @@ -0,0 +1,359 @@ +if not modules then modules = { } end modules ['util-tar'] = { + version = 1.001, + comment = "companion to luat-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, tonumber = type, tonumber +local gsub, escapedpattern = string.gsub, string.escapedpattern +local nameonly, dirname, makedirs = file.nameonly, file.dirname, dir.makedirs +local savedata = io.savedata +local newreader = io.newreader + +local report = logs.reporter("tar") + +local types = { + ["0"] = "file", + ["\0"] = "regular", + ["1"] = "link", + ["2"] = "symbolic", -- reserved + ["3"] = "character", + ["4"] = "block", + ["5"] = "directory", + ["6"] = "fifo", + ["7"] = "continuation", -- reserved + ["x"] = "extended", -- header +} + +local function asstring(str) + return str and gsub(str,"[\0 ]+$","") or nil +end + +local function asnumber(str) + str = gsub(str,"\0$","") + return tonumber(str,8) +end + +local function opentar(whatever,filename) + local f = newreader(filename,whatever) + if f then + f.metadata = { + nofpaths = 0, + noffiles = 0, + noflinks = 0, + nofbytes = 0, + } + return f + end +end + +local function readheader(t) + -- checksum + local p = t:getposition() + local h = t:readbytetable(512) + t:setposition(p) + for i=149,156 do -- nasty, one less + h[i] = 0 + end + local c = 256 + for i=1,512 do + c = c + h[i] + end + -- + local header = { + name = asstring(t:readstring(100)), -- 0 + mode = asnumber(t:readstring( 8)), -- 100 -- when we write: 0775 octal + uid = asnumber(t:readstring( 8)), -- 108 + gid = asnumber(t:readstring( 8)), -- 116 + size = asnumber(t:readstring( 12)), -- 124 + mtime = asnumber(t:readstring( 12)), -- 136 + checksum = asnumber(t:readstring( 6)), -- 148 -- actually 6 with space and \0 + dummy = t:skip (2) , + typeflag = t:readstring( 1) , -- 156 + linkname = asstring(t:readstring(100)), -- 157 + -- magic = asstring(t:readstring( 6)), -- 257 -- ustar\0 + -- version = 2 -- 263 + -- uname = 32 -- 265 + -- gname = 32 -- 297 + -- devmajor = 8 -- 329 + -- devminor = 8 -- 337 + -- prefix = 155 -- 345 + padding = t:skip (255) , -- 500 + } + local typeflag = header.typeflag + if typeflag then + header.filetype = types[typeflag] + if c == header.checksum then + return header + end + end +end + +local readers = { + + directory = function(t,h) + local metadata = t.metadata + local filename = h.name + if metadata.verbose then + report("%8s %s","",filename) + end + metadata.nofpaths = metadata.nofpaths + 1 + return true + end, + + file = function(t,h) + local metadata = t.metadata + local filename = h.name + local filesize = h.size + local pathname = dirname(filename) + if metadata.verbose then + report("% 8i : %s",filesize,filename) + end + if makedirs(pathname) then + savedata(filename,t:readstring(filesize)) + else + t.skip(filesize) + end + local position = t:getposition() + local target = position + (512 - position % 512) % 512 + t:setposition(target) + metadata.noffiles = metadata.noffiles + 1 + metadata.nofbytes = metadata.nofbytes + filesize + return true + end, + + link = function(t,h) + local metadata = t.metadata + local filename = h.name + local linkname = h.linkname + if metadata.verbose then + report("%8s %s => %s","",linkname,filename) + end + metadata.noflinks = metadata.noflinks + 1 + return true + end, + +} + +local skippers = { + + directory = function(t,h) + return true + end, + + file = function(t,h) + local filesize = h.size + local fileoffset = t:getposition() + local position = filesize + fileoffset + local target = position + (512 - position % 512) % 512 + t:setposition(target) + return fileoffset + end, + + link = function(t,h) + return true + end, + +} + +local writers = { + -- nothing here (yet) +} + +local function saveheader(t,h) + local filetype = h.filetype + local reader = readers[filetype] + if reader then + return filetype, reader(t,h) + else + report("no reader for %s",filetype) + end +end + +local function skipheader(t,h) + local filetype = h.filetype + local skipper = skippers[filetype] + if skipper then + return filetype, skipper(t,h) + else + report("no skipper for %s",filetype) + end +end + +local function unpacktar(whatever,filename,verbose) + local t = opentar(whatever,filename) + if t then + local metadata = t.metadata + statistics.starttiming(metadata) + if verbose then + if whatever == "string" then + report("unpacking: %i bytes",#filename) + else + report("unpacking: %s",filename) + end + report("") + metadata.verbose = verbose + end + while true do + local h = readheader(t) + if not h then + break + else + local filetype, saved = saveheader(t,h) + if not saved then + break + end + end + end + statistics.stoptiming(metadata) + metadata.runtime = statistics.elapsed(metadata) + if verbose then + report("") + report("number of paths : %i",metadata.nofpaths) + report("number of files : %i",metadata.noffiles) + report("number of links : %i",metadata.noflinks) + report("number of bytes : %i",metadata.nofbytes) + report("") + report("runtime needed : %s",statistics.elapsedseconds(metadata)) + report("") + end + t.close() + return metadata + end +end + +local function listtar(whatever,filename,onlyfiles) + local t = opentar(whatever,filename) + if t then + local list, n = { }, 0 + while true do + local h = readheader(t) + if not h then + break + else + local filetype, offset = skipheader(t,h) + if not offset then + break + elseif filetype == "file" then + n = n + 1 ; list[n] = { filetype, h.name, h.size } + elseif filetype == "link" then + n = n + 1 ; list[n] = { filetype, h.name, h.linkfile } + elseif not onlyfiles then + n = n + 1 ; list[n] = { filetype, h.name } + end + end + end + t.close() + -- can be an option + table.sort(list,function(a,b) return a[2] < b[2] end) + return list + end +end + +local function hashtar(whatever,filename,strip) + local t = opentar(whatever,filename) + if t then + local list = { } + if strip then + strip = "^" .. escapedpattern(nameonly(nameonly(strip))) .. "/" + end + while true do + local h = readheader(t) + if not h then + break + else + local filetype, offset = skipheader(t,h) + if not offset then + break + else + local name = h.name + if strip then + name = gsub(name,strip,"") + end + if filetype == "file" then + list[name] = { offset, h.size } + elseif filetype == "link" then + list[name] = h.linkname + end + end + end + end + t.close() + return list + end +end + +-- weak table ? + +local function fetchtar(whatever,archive,filename,list) + if not list then + list = hashtar(whatever,archive) + end + if list then + local what = list[filename] + if type(what) == "string" then + what = list[what] -- a link + end + if what then + local t = opentar(whatever,archive) + if t then + t:setposition(what[1]) + return t:readstring(what[2]) + end + end + end +end + +local function packtar(whatever,filename,verbose) + report("packing will be implemented when we need it") +end + +local tar = { + files = { + unpack = function(...) return unpacktar("file", ...) end, + pack = function(...) return packtar ("file", ...) end, + list = function(...) return listtar ("file", ...) end, + hash = function(...) return hashtar ("file", ...) end, + fetch = function(...) return fetchtar ("file", ...) end, + }, + strings = { + unpack = function(...) return unpacktar("string",...) end, + pack = function(...) return packtar ("string",...) end, + list = function(...) return listtar ("string",...) end, + hash = function(...) return hashtar ("string",...) end, + fetch = function(...) return fetchtar ("string",...) end, + }, + streams = { + unpack = function(...) return unpacktar("stream",...) end, + pack = function(...) return packtar ("stream",...) end, + list = function(...) return listtar ("stream",...) end, + hash = function(...) return hashtar ("stream",...) end, + fetch = function(...) return fetchtar ("stream",...) end, + }, +} + +utilities.tar = tar + +-- tar.files .unpack("e:/luatex/luametatex-source.tar",true) +-- tar.streams.unpack("e:/luatex/luametatex-source.tar",true) +-- tar.strings.unpack(io.loaddata("e:/luatex/luametatex-source.tar"),true) + +-- inspect(tar.files .unpack("e:/luatex/luametatex-source.tar")) +-- inspect(tar.streams.unpack("e:/luatex/luametatex-source.tar")) +-- inspect(tar.strings.unpack(io.loaddata("e:/luatex/luametatex-source.tar"))) + +-- inspect(tar.files .list("e:/luatex/luametatex-source.tar",true)) +-- inspect(tar.streams.list("e:/luatex/luametatex-source.tar",true)) +-- inspect(tar.strings.list(io.loaddata("e:/luatex/luametatex-source.tar"),true)) + +-- local c = os.clock() +-- local l = tar.files.hash("e:/luatex/luametatex-source.tar") +-- for i=1,500 do +-- local s = tar.files.fetch("e:/luatex/luametatex-source.tar", "luametatex-source/source/tex/texbuildpage.c", l) +-- local s = tar.files.fetch( "e:/luatex/luametatex-source.tar","luametatex-source/source/lua/lmtlibrary.c", l) +-- end +-- print(os.clock()-c) + +return tar diff --git a/tex/context/base/mkiv/util-zip.lua b/tex/context/base/mkiv/util-zip.lua index e97f3a065..67c1a715f 100644 --- a/tex/context/base/mkiv/util-zip.lua +++ b/tex/context/base/mkiv/util-zip.lua @@ -21,6 +21,14 @@ local ioopen = io.open local loaddata, savedata = io.loaddata, io.savedata local filejoin, isdir, dirname, mkdirs = file.join, lfs.isdir, file.dirname, dir.mkdirs +gzip = gzip or { } -- so in luatex we keep the old ones too + +if not zlib then + zlib = xzip -- in luametatex we shadow the old one +elseif not xzip then + xzip = zlib +end + local files = utilities.files local openfile = files.open local closefile = files.close @@ -497,48 +505,157 @@ if xzip then -- flate then do end -zipfiles.gunzipfile = gzip.load +if not gzip.compress then + + -- todo: compress/decompress that work with offset in string + + -- We only have a few official methods here: + -- + -- local decompressed = gzip.load (filename) + -- local resultsize = gzip.save (filename,compresslevel) + -- local compressed = gzip.compress (str,compresslevel) + -- local decompressed = gzip.decompress (str) + -- local iscompressed = gzip.compressed (str) + -- local suffix, okay = gzip.suffix (filename) + -- + -- In LuaMetaTeX we have only xzip which implements a very few methods: + -- + -- compress (str,level,method,window,memory,strategy) + -- decompress (str,window) + -- adler32 (str,checksum) + -- crc32 (str,checksum) + -- + -- Special window values are: + -- + -- flate : - 15 + -- zlib : 15 + -- gzip : - 15 + + local suffix = file.suffix + local suffixes = file.suffixes + local find = string.find + local concat = table.concat + local openfile = io.open + + local gzipwindow = -15 -- miniz needs this + local gziplevel = 3 + local identifier = "\x1F\x8B" + local pattern = "^\x1F\x8B\x08" + + local compress = zlib.compress + local decompress = zlib.decompress + local crc32 = zlib.crc32 + + local streams = utilities.streams + local openstream = streams.openstring + local closestream = streams.close + local getposition = streams.getposition + local readbyte = streams.readbyte + local readcardinal4 = streams.readcardinal4le + local readcardinal2 = streams.readcardinal2le + local readstring = streams.readstring + local readcstring = streams.readcstring + local skipbytes = streams.skip + + local tocardinal1 = streams.tocardinal1 + local tocardinal4 = streams.tocardinal4le + + local function getdecompressed(str) + local s = openstream(str) + local identifier = readstring(s,2) + local method = readbyte(s,1) + local flags = readbyte(s,1) + local timestamp = readcardinal4(s) + local compression = readbyte(s,1) + local operating = readbyte(s,1) + local isjusttext = (flags & 0x01 ~= 0) and true or false + local extrasize = (flags & 0x04 ~= 0) and readcardinal2(s) or 0 + local filename = (flags & 0x08 ~= 0) and readcstring(s) or "" + local comment = (flags & 0x10 ~= 0) and readcstring(s) or "" + local checksum = (flags & 0x02 ~= 0) and readcardinal2(s) or 0 + local compressed = readstring(s,#str) + local data = decompress(compressed,gzipwindow) -- pass offset + return data + end --- if flate then --- --- local streams = utilities.streams --- local openfile = streams.open --- local closestream = streams.close --- local setposition = streams.setposition --- local getsize = streams.size --- local readcardinal4 = streams.readcardinal4le --- local getstring = streams.getstring --- local decompress = flate.gz_decompress --- --- -- id1=1 id2=1 method=1 flags=1 mtime=4(le) extra=1 os=1 --- -- flags:8 comment=...<nul> flags:4 name=...<nul> flags:2 extra=...<nul> flags:1 crc=2 --- -- data:? --- -- crc=4 size=4 --- --- function zipfiles.gunzipfile(filename) --- local strm = openfile(filename) --- if strm then --- setposition(strm,getsize(strm) - 4 + 1) --- local size = readcardinal4(strm) --- local data = decompress(getstring(strm),size) --- closestream(strm) --- return data --- end --- end --- --- elseif gzip then --- --- local openfile = gzip.open --- --- function zipfiles.gunzipfile(filename) --- local g = openfile(filename,"rb") --- if g then --- local d = g:read("*a") --- d:close() --- return d --- end --- end --- --- end + local function putcompressed(str,level,originalname) + return concat { + identifier, -- 2 identifier + tocardinal1(0x08), -- 1 method + tocardinal1(0x08), -- 1 flags + tocardinal4(os.time()), -- 4 mtime + tocardinal1(0x02), -- 1 compression (2 or 4) + tocardinal1(0xFF), -- 1 operating + (originalname or "unknownname") .. "\0", + compress(str,level,nil,gzipwindow), + tocardinal4(crc32(str)), -- 4 + tocardinal4(#str), -- 4 + } + end + + function gzip.load(filename) + local f = openfile(filename,"rb") + if not f then + -- invalid file + else + local data = f:read("*all") + f:close() + if data and data ~= "" then + if suffix(filename) == "gz" then + data = getdecompressed(data) + end + return data + end + end + end + + function gzip.save(filename,data,level,originalname) + if suffix(filename) ~= "gz" then + filename = filename .. ".gz" + end + local f = openfile(filename,"wb") + if f then + data = putcompressed(data or "",level or gziplevel,originalname) + f:write(data) + f:close() + return #data + end + end + + function gzip.suffix(filename) + local suffix, extra = suffixes(filename) + local gzipped = extra == "gz" + return suffix, gzipped + end + + function gzip.compressed(s) + return s and find(s,identifier) + end + + function gzip.compress(s,level) + if s and not find(s,identifier) then -- the find check might go away + if not level then + level = gziplevel + elseif level <= 0 then + return s + elseif level > 9 then + level = 9 + end + return putcompressed(s,level or gziplevel) or s + end + end + + function gzip.decompress(s) + if s and find(s,identifier) then + return getdecompressed(s) + else + return s + end + end + + +end + +zipfiles.gunzipfile = gzip.load return zipfiles diff --git a/tex/context/base/mkxl/anch-loc.lmt b/tex/context/base/mkxl/anch-loc.lmt index 09c1406ff..054d4dd07 100644 --- a/tex/context/base/mkxl/anch-loc.lmt +++ b/tex/context/base/mkxl/anch-loc.lmt @@ -284,6 +284,7 @@ implement { name = "pushlocalanchors", public = true, protected = true, + untraced = true, actions = pushpositions, } @@ -291,6 +292,7 @@ implement { name = "poplocalanchors", public = true, protected = true, + untraced = true, actions = poppositions, } @@ -299,6 +301,7 @@ implement { arguments = { "integerargument" }, public = true, protected = true, + untraced = true, actions = function(n) analyze(driver,texgetbox(n)) end @@ -309,6 +312,7 @@ implement { arguments = { "integerargument" }, public = true, protected = true, + untraced = true, actions = drivers.converters.resyncbox, } @@ -383,6 +387,7 @@ interfaces.implement { name = "async", arguments = { "argument", "integerargument", "argument" }, protected = true, + untraced = true, public = true, actions = function(name,x,align) local t = positions[name].cnt diff --git a/tex/context/base/mkxl/back-exp-imp-mth.lmt b/tex/context/base/mkxl/back-exp-imp-mth.lmt index 73c09d79e..8751ca89d 100644 --- a/tex/context/base/mkxl/back-exp-imp-mth.lmt +++ b/tex/context/base/mkxl/back-exp-imp-mth.lmt @@ -21,6 +21,10 @@ local extras = backend.extras local checks = backend.checks local finalizers = backend.finalizers +----- bpfactor = number.dimenfactors.bp +----- f_points = string.formatters["%p"] +local f_em = string.formatters["%.6Nem"] + local implement = interfaces.implement do @@ -155,6 +159,7 @@ do mi = true, mo = true, mn = true, + mspace = true, } local function checkmath(root) -- we can provide utf.toentities as an option @@ -394,6 +399,17 @@ do elseif tg == "break" then di.skip = "comment" i = i + 1 + elseif tg == "mspace" then + -- di.empty = true + local s = specifications[di.fulltag] + local e = s and s.emfactor + if e and e ~= 0 then + di.element = "mspace" + di.attributes = { + width = f_em(e), + } + end + i = i + 1 elseif tg == "mtext" then -- this is only needed for unboxed mtexts ... all kind of special -- tex border cases and optimizations ... trial and error @@ -519,6 +535,8 @@ do local tg = di.tg if tg == "mtext" or tg == "ms" then return di + elseif tg == "mspace" then + return di else local data = di.data local ndata = #data @@ -530,38 +548,43 @@ do end if d then local content = d.content - if not content then + if d.tg == "mspace" then + n = n + 1 + data[n] = d + d.data = { } + elseif not content then +-- if not content then n = n + 1 d.__i__ = n data[n] = d - elseif content == " " or content == "" then - if di.tg == "mspace" then - -- we append or prepend a space to a preceding or following mtext - local parent = di.__p__ - local index = di.__i__ -- == i - local data = parent.data - if index > 1 then - local d = data[index-1] - if d.tg == "mtext" then - local dd = d.data - local dn = dd[#dd] - local dc = dn.content - if dc then - dn.content = dc .. content - end - end - elseif index < ndata then - local d = data[index+1] - if d.tg == "mtext" then - local dd = d.data - local dn = dd[1] - local dc = dn.content - if dc then - dn.content = content .. dc - end - end - end - end +-- elseif content == " " or content == "" then +-- if d.tg == "mspace" then +-- -- we append or prepend a space to a preceding or following mtext +-- local parent = di.__p__ +-- local index = di.__i__ -- == i +-- local data = parent.data +-- if index > 1 then +-- local d = data[index-1] +-- if d.tg == "mtext" then +-- local dd = d.data +-- local dn = dd[#dd] +-- local dc = dn.content +-- if dc then +-- dn.content = dc .. content +-- end +-- end +-- elseif index < ndata then +-- local d = data[index+1] +-- if d.tg == "mtext" then +-- local dd = d.data +-- local dn = dd[1] +-- local dc = dn.content +-- if dc then +-- dn.content = content .. dc +-- end +-- end +-- end +-- end else n = n + 1 data[n] = d diff --git a/tex/context/base/mkxl/back-exp.lmt b/tex/context/base/mkxl/back-exp.lmt index f0d8e120e..81a0bf7d5 100644 --- a/tex/context/base/mkxl/back-exp.lmt +++ b/tex/context/base/mkxl/back-exp.lmt @@ -921,7 +921,9 @@ do local element = di.element if not element then -- skip - elseif element == "break" then -- or element == "pagebreak" + elseif element == "break" then -- or element == "pagebreak" -- todo: use empty flag + emptytag(result,element,nature,di) + elseif element == "mspace" then -- todo: use empty flag emptytag(result,element,nature,di) elseif element == "" or di.skip == "ignore" then -- skip @@ -941,6 +943,11 @@ do flushtree(result,di.after,nature) end end + else +-- local element = di.element +-- if element == "mspace" then -- todo: use empty flag +-- emptytag(result,element,nature,di) +-- end end end end @@ -961,8 +968,8 @@ do -- skip elseif di.skip == "ignore" then -- skip (new) -elseif di.tg == "ignore" then - -- skip (new) + elseif di.tg == "ignore" then + -- skip (new) elseif di.content then if di.samepar then prevparnumber = false @@ -1046,12 +1053,22 @@ elseif di.tg == "ignore" then -- also tabulaterow reconstruction .. maybe better as a checker -- i.e cell attribute + local function showtree(data,when,where) + if data then + for i=1,#data do + local d = data[i] + if type(d) == "table" and d.element then + print(when,where,i,d.element,d.parnumber or 0) + end + end + end + end + local function collapsetree(tree) --- for tag, trees in sortedhash(treehash) do + -- showtree(data,"before","collapse") + -- for tag, trees in sortedhash(treehash) do for tag, trees in next, treehash do local d = trees[1].data --- print("!!!!!!!!",tag) --- inspect(trees) if d then local nd = #d if nd > 0 then @@ -1097,30 +1114,22 @@ elseif di.tg == "ignore" then end end end + -- showtree(data,"after","collapse") end local function finalizetree(tree) + -- showtree(data,"before","finalize") for _, finalizer in next, finalizers do finalizer(tree) end + -- showtree(data,"after","finalize") end - -- local function showtree(data,when,where) - -- if data then - -- for i=1,#data do - -- local d = data[i] - -- if type(d) == "table" and d.element then - -- print(when,where,i,d.element,d.parnumber or 0) - -- end - -- end - -- end - -- end - local function indextree(tree) local data = tree.data if data then - local n, new = 0, { } -- showtree(data,"before","index") + local n, new = 0, { } for i=1,#data do local d = data[i] if not d then @@ -1148,9 +1157,12 @@ elseif di.tg == "ignore" then for i=1,#data do local d = data[i] if type(d) == "table" then - local check = checks[d.tg] - if check then - check(d,data,i) + local tg = d.tg + if tg then + local check = checks[tg] + if check then + check(d,data,i) + end end checktree(d) -- so parts can pass twice end @@ -1166,9 +1178,12 @@ elseif di.tg == "ignore" then for i=1,#data do local d = data[i] if type(d) == "table" then - local fix = fixes[d.tg] - if fix then - fix(d,data,i) + local tg = d.tg + if tg then + local fix = fixes[tg] + if fix then + fix(d,data,i) + end end fixtree(d) -- so parts can pass twice end @@ -1406,29 +1421,30 @@ end local collectresults do -- too many locals otherwise - local nodecodes = nodes.nodecodes - local gluecodes = nodes.gluecodes - local listcodes = nodes.listcodes - local whatsitcodes = nodes.whatsitcodes + local nodecodes = nodes.nodecodes + local gluecodes = nodes.gluecodes + local listcodes = nodes.listcodes + local whatsitcodes = nodes.whatsitcodes - local subtypes = nodes.subtypes + local subtypes = nodes.subtypes - local hlist_code = nodecodes.hlist - local vlist_code = nodecodes.vlist - local glyph_code = nodecodes.glyph - local glue_code = nodecodes.glue - local kern_code = nodecodes.kern - local disc_code = nodecodes.disc - local whatsit_code = nodecodes.whatsit - local par_code = nodecodes.par + local hlist_code = nodecodes.hlist + local vlist_code = nodecodes.vlist + local glyph_code = nodecodes.glyph + local glue_code = nodecodes.glue + local kern_code = nodecodes.kern + local disc_code = nodecodes.disc + local whatsit_code = nodecodes.whatsit + local par_code = nodecodes.par - local userskip_code = gluecodes.userskip - local rightskip_code = gluecodes.rightskip - local parfillskip_code = gluecodes.parfillskip - local spaceskip_code = gluecodes.spaceskip - local xspaceskip_code = gluecodes.xspaceskip + local userskip_code = gluecodes.userskip + local rightskip_code = gluecodes.rightskip + local parfillskip_code = gluecodes.parfillskip + local spaceskip_code = gluecodes.spaceskip + local xspaceskip_code = gluecodes.xspaceskip + local intermathskip_code = gluecodes.intermathskip - local linelist_code = listcodes.line + local linelist_code = listcodes.line local userdefinedwhatsit_code = whatsitcodes.userdefined @@ -1654,6 +1670,21 @@ local collectresults do -- too many locals otherwise currentcontent[nofcurrentcontent] = c end elseif subtype == userskip_code then +-- local at = getattr(n,a_tagged) +-- local tl = taglist[at] +-- if tl and structurestags.strip(tl.taglist[#tl.taglist]) == "mspace" then +-- if nofcurrentcontent > 0 then +-- pushcontent() +-- pushentry(currentnesting) -- ?? +-- end +-- -- in the past we'd push a space here ... check mkiv : otherwise no threshold with mspace +-- pushentry(tl) +-- if trace_export then +-- report_export("%w<!-- processing mspace tagged %a",currentdepth,at) +-- end +-- last = nil +-- currentparagraph = nil +-- else if getwidth(n) > threshold then if last and not somespace[currentcontent[nofcurrentcontent]] then local a = getattr(n,a_tagged) or pat @@ -1681,6 +1712,7 @@ local collectresults do -- too many locals otherwise end end end +-- end elseif subtype == spaceskip_code or subtype == xspaceskip_code then if not somespace[currentcontent[nofcurrentcontent]] then local a = getattr(n,a_tagged) or pat @@ -1703,6 +1735,8 @@ local collectresults do -- too many locals otherwise currentattribute = last end end + elseif subtype == intermathskip_code then + -- put this as attribute when it differs, maybe more ... check mathml elseif subtype == rightskip_code then -- a line if nofcurrentcontent > 0 then @@ -1769,49 +1803,50 @@ local collectresults do -- too many locals otherwise elseif id == kern_code then local kern = getkern(n) if kern > 0 then -local a = getattr(n,a_tagged) or pat -local t = taglist[a] -if not t or t.tagname ~= "ignore" then -- maybe earlier on top) - local limit = threshold - if p then - local c, f = isglyph(p) - if c then - limit = fontquads[f] / 4 + local a = getattr(n,a_tagged) or pat + local t = taglist[a] + if not t or t.tagname ~= "ignore" then -- maybe earlier on top) + local limit = threshold + if p then + local c, f = isglyph(p) + if c then + limit = fontquads[f] / 4 + end end - end - if kern > limit then - if last and not somespace[currentcontent[nofcurrentcontent]] then --- local a = getattr(n,a_tagged) or pat - if a == last then - if not somespace[currentcontent[nofcurrentcontent]] then + if kern > limit then + if last and not somespace[currentcontent[nofcurrentcontent]] then + -- local a = getattr(n,a_tagged) or pat + if a == last then + if not somespace[currentcontent[nofcurrentcontent]] then + if trace_export then + report_export("%w<!-- injecting spacing 8 (kern %p) -->",currentdepth,kern) + end + nofcurrentcontent = nofcurrentcontent + 1 + currentcontent[nofcurrentcontent] = " " + end + elseif a then + -- e.g LOGO<space>LOGO if trace_export then - report_export("%w<!-- injecting spacing 8 (kern %p) -->",currentdepth,kern) + report_export("%w<!-- processing kern, threshold %p, tag %s => %s -->",currentdepth,limit,last,a) + end + last = a + pushcontent() + if trace_export then + report_export("%w<!-- injecting spacing 9 (kern %p) -->",currentdepth,kern) end nofcurrentcontent = nofcurrentcontent + 1 currentcontent[nofcurrentcontent] = " " + -- currentnesting = taglist[last] + currentnesting = t + pushentry(currentnesting) + currentattribute = last end - elseif a then - -- e.g LOGO<space>LOGO - if trace_export then - report_export("%w<!-- processing kern, threshold %p, tag %s => %s -->",currentdepth,limit,last,a) - end - last = a - pushcontent() - if trace_export then - report_export("%w<!-- injecting spacing 9 (kern %p) -->",currentdepth,kern) - end - nofcurrentcontent = nofcurrentcontent + 1 - currentcontent[nofcurrentcontent] = " " --- currentnesting = taglist[last] -currentnesting = t - pushentry(currentnesting) - currentattribute = last end end end -end end elseif id == whatsit_code then + -- todo (lmtx) if subtype == userdefinedwhatsit_code then -- similar to images, see above local at = getattr(n,a_tagged) diff --git a/tex/context/base/mkxl/back-pdf.mkxl b/tex/context/base/mkxl/back-pdf.mkxl index 4ec1501a5..5770e6aad 100644 --- a/tex/context/base/mkxl/back-pdf.mkxl +++ b/tex/context/base/mkxl/back-pdf.mkxl @@ -61,35 +61,40 @@ %D Because we do a lot in \LUA\ and don't want interferences, we nil most of the %D \PDFTEX\ primitives. Of course one can always use the \type {\pdfvariable}, %D \type {\pdfextension} and \type {\pdffeedback} primitives but it will probably -%D have bad side effects. +%D have bad side effects. We fake them as primitives which is why they are +%D defined as untraced. -\permanent\protected\def\pdfextension{\clf_pdfextension} -\permanent \def\pdffeedback {\clf_pdffeedback} -\permanent \def\pdfvariable {\clf_pdfvariable} +% \pdfextension % defined in lua +% \pdffeedback % idem +% \pdfvariable % idem +% \pdfliteral % idem +% \pdfobj % idem +% \pdflastobj % idem +% \pdfrefobj % idem -%D For the moment we keep this for tikz but hopefully it will at some point use -%D the proper ones. Consider them obsolete: +\untraced\permanent\protected\def\pdfrestore {\pdfextension restore} +\untraced\permanent\protected\def\pdfsave {\pdfextension save} +\untraced\permanent\protected\def\pdfsetmatrix{\pdfextension setmatrix} -\permanent\protected\def\pdfliteral {\clf_pdfliteral} -\permanent\protected\def\pdfobj {\clf_pdfobj}% -\permanent\protected\def\pdflastobj {\numexpr\clf_pdflastobj\relax} -\permanent\protected\def\pdfrefobj {\clf_pdfrefobj} +\untraced\permanent\def\pdfxform {\saveboxresource} +\untraced\permanent\def\pdflastxform {\lastsavedboxresourceindex} +\untraced\permanent\def\pdfrefxform {\useboxresource} -\permanent\protected\def\pdfrestore {\pdfextension restore} -\permanent\protected\def\pdfsave {\pdfextension save} -\permanent\protected\def\pdfsetmatrix{\pdfextension setmatrix} +%D This is also needed for tikz: -\permanent\let\pdfxform \saveboxresource -\permanent\let\pdflastxform\lastsavedboxresourceindex -\permanent\let\pdfrefxform \useboxresource +\ifdefined\pdfsavepos\else + \untraced\permanent\def\pdfsavepos {\savepos } + \untraced\permanent\def\pdflastxpos{\lastxpos} + \untraced\permanent\def\pdflastypos{\lastypos} +\fi %D Here are quick and dirty compression flippers, mostly used when testing something %D as one can best stick to the defaults that also adapt to specific standards. -\permanent\protected\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} -\permanent\protected\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree} -\permanent\protected\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } -\permanent\protected\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} +\untraced\permanent\protected\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} +\untraced\permanent\protected\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree} +\untraced\permanent\protected\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } +\untraced\permanent\protected\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} %D PDF/X (maybe combine the two lua calls) @@ -119,23 +124,23 @@ %D These are the only official methods to add stuff to the resources. If more is %D needed for third party low level code, it can be added. -\permanent\protected\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog{#1}{#2}} -\permanent\protected\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo{#1}{#2}} -\permanent\protected\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames{#1}{#2}} - -\permanent\protected\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes{#1}{#2}} -\permanent\protected\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes{#1}{#2}} -\permanent\protected\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources{#1}{#2}} - -\permanent\protected\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate{#1}{#2}} -\permanent\protected\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}} -\permanent\protected\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern{#1}{#2}} -\permanent\protected\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade{#1}{#2}} - -\permanent \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources} -\permanent \def\pdfcolor #1{\clf_lpdf_color\numexpr\rawcolorattribute{#1}\relax} - -%D This is a temporary hack mthat will be removed, improved or somehow can become +% \pdfbackendsetcatalog #1#2 % defined in lua +% \pdfbackendsetinfo #1#2 % idem +% \pdfbackendsetname #1#2 % idem +% +% \pdfbackendsetpageattribute #1#2 % idem +% \pdfbackendsetpagesattribute#1#2 % idem +% \pdfbackendsetpageresource #1#2 % idem +% +% \pdfbackendsetextgstate #1#2 % idem +% \pdfbackendsetcolorspace #1#2 % idem +% \pdfbackendsetpattern #1#2 % idem +% \pdfbackendsetshade #1#2 % idem +% +% \pdfbackendcurrentresources % idem, expandable +% \pdfcolor #1 % idem, expandable + +%D This is a temporary hack that will be removed, improved or somehow can become %D default. \permanent\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]} @@ -146,19 +151,11 @@ %D text \pdfbackendactualtext{Meier}{Müller} text %D \stoptyping -\permanent\protected\def\pdfbackendactualtext#1#2% not interfaced +\untraced\permanent\protected\def\pdfbackendactualtext#1#2% not interfaced {\clf_startactualtext{#2}% #1% \clf_stopactualtext} \aliased\let\pdfactualtext\pdfbackendactualtext -%D Bah, this is also needed for tikz: - -\ifdefined\pdfsavepos\else - \permanent\let\pdfsavepos \savepos - \permanent\let\pdflastxpos\lastxpos - \permanent\let\pdflastypos\lastypos -\fi - \protect \endinput diff --git a/tex/context/base/mkxl/back-pdp.lmt b/tex/context/base/mkxl/back-pdp.lmt index 76a6f4b67..5c786d53e 100644 --- a/tex/context/base/mkxl/back-pdp.lmt +++ b/tex/context/base/mkxl/back-pdp.lmt @@ -27,6 +27,12 @@ local scanstring = tokenscanners.string local scaninteger = tokenscanners.integer local scanwhd = tokenscanners.whd +local values = tokens.values +local dimension_value = values.dimension +local cardinal_value = values.cardinal + +local immediate_code = tex.flagcodes.immediate + local trace = false trackers.register("backend", function(v) trace = v end) local report = logs.reporter("backend") @@ -50,14 +56,14 @@ end local lastobjnum = 0 -local function pdf_obj() +local function pdf_obj(prefix) if scankeyword("reserveobjnum") then lastobjnum = pdfreserveobject() if trace then report("\\pdfobj reserveobjnum: object %i",lastobjnum) end else - local immediate = true + local immediate = prefix and (prefix & immediate_code) ~= 0 -- was just "true" local objnum = scankeyword("useobjnum") and scaninteger() or pdfreserveobject() local uncompress = scankeyword("uncompressed") or pdfcompresslevel() == 0 local streamobject = scankeyword("stream") @@ -90,10 +96,14 @@ local function pdf_obj() end local function pdf_lastobj() - context("%i",lastobjnum) if trace then report("\\lastobj: object %i",lastobjnum) end + return cardinal_value, lastobjnum +end + +local function pdf_pagereference() + return cardinal_value, pdfpagereference() end local function pdf_refobj() @@ -218,9 +228,9 @@ end -- lastlink lastobj pageref retval revision version xformname local feedbacks = { - lastobj = pdf_lastobj, - pageref = function() context(pdfpagereference()) end, - xformname = function() context(pdfgetxformname ()) end, + lastobj = pdf_lastobj, + pageref = pdf_pagereference, + xformname = function() context(pdfgetxformname ()) end, } local function pdf_feedback() @@ -262,20 +272,18 @@ local function pdf_variable() end end --- kept: - -implement { name = "pdfextension", actions = pdf_extension } -implement { name = "pdffeedback", actions = pdf_feedback } -implement { name = "pdfvariable", actions = pdf_variable } - --- for the moment (tikz) - -implement { name = "pdfliteral", actions = pdf_literal } -implement { name = "pdfobj", actions = pdf_obj } -implement { name = "pdflastobj", actions = pdf_lastobj } -implement { name = "pdfrefobj", actions = pdf_refobj } ---------- { name = "pdfannot", actions = pdf_annot } ---------- { name = "pdfdest", actions = pdf_dest } ---------- { name = "pdfsave", actions = pdf_save } ---------- { name = "pdfrestore", actions = pdf_restore } ---------- { name = "pdfsetmatrix", actions = pdf_setmatrix } +-- kept (also because tikz needs including the pdftex primitives): + +implement { name = "pdfextension", actions = pdf_extension, public = true, untraced = true, protected = true } +implement { name = "pdffeedback", actions = pdf_feedback, public = true, untraced = true } -- expandable / todo : value +implement { name = "pdfvariable", actions = pdf_variable, public = true, untraced = true } -- expandable / todo : value +implement { name = "pdfliteral", actions = pdf_literal, public = true, untraced = true, protected = true } +implement { name = "pdfobj", actions = pdf_obj, public = true, usage = "value", protected = true } +implement { name = "pdflastobj", actions = pdf_lastobj, public = true, usage = "value", protected = true } +implement { name = "pdfrefobj", actions = pdf_refobj, public = true, untraced = true, protected = true } + +--------- { name = "pdfannot", actions = pdf_annot } +--------- { name = "pdfdest", actions = pdf_dest } +--------- { name = "pdfsave", actions = pdf_save } +--------- { name = "pdfrestore", actions = pdf_restore } +--------- { name = "pdfsetmatrix", actions = pdf_setmatrix } diff --git a/tex/context/base/mkxl/cldf-lmt.lmt b/tex/context/base/mkxl/cldf-lmt.lmt index 0c9da145f..e6c046763 100644 --- a/tex/context/base/mkxl/cldf-lmt.lmt +++ b/tex/context/base/mkxl/cldf-lmt.lmt @@ -187,6 +187,7 @@ implement { name = "newarray", public = true, protected = true, + untraced = true, arguments = { { { "name", "string" }, { "nx", "integer" }, @@ -335,6 +336,7 @@ implement { name = "showarray", public = true, protected = true, + untraced = true, actions = function() local name = scanstring() if name then @@ -358,9 +360,10 @@ end) table.makeweak(cache) implement { - name = "luaexpression", - public = true, - actions = function() + name = "luaexpression", + public = true, + untraced = true, + actions = function() local how = scanword() local code = cache[scanargument()] if code then @@ -544,6 +547,7 @@ end implement { name = "newluatable", protected = true, + untraced = true, arguments = "csname", actions = newluatable, } @@ -551,6 +555,7 @@ implement { implement { name = "useluatable", protected = true, + untraced = true, arguments = { "csname", true }, actions = newluatable, } @@ -558,6 +563,7 @@ implement { implement { name = "disposeluatable", protected = true, + untraced = true, public = true, arguments = "csname", actions = disposeluatable, @@ -566,6 +572,7 @@ implement { implement { name = "inspectluatable", protected = true, + untraced = true, public = true, arguments = "csname", actions = inspectluatable, @@ -574,6 +581,7 @@ implement { implement { name = "showluatables", protected = true, + untraced = true, public = true, actions = showluatables, } @@ -581,6 +589,7 @@ implement { implement { name = "setluatable", protected = true, + untraced = true, public = true, arguments = { "csname", "argument" }, actions = function(name,data) @@ -597,6 +606,7 @@ implement { implement { name = "getfromluatable", protected = false, + untraced = true, public = true, arguments = { "csname", "argument" }, actions = getfromluatable, @@ -605,6 +615,7 @@ implement { implement { name = "idxfromluatable", protected = false, + untraced = true, public = true, arguments = { "csname", "integer" }, actions = idxfromluatable, @@ -628,9 +639,10 @@ local tables = { } local stack = setmetatableindex("table") implement { - name = "droptablegroup", - public = true, - actions = function() + name = "droptablegroup", + public = true, + untraced = true, + actions = function() local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() local s = stack[g] if s then @@ -715,6 +727,7 @@ end implement { name = "newhashedtable", protected = true, + untraced = true, public = true, actions = newtable, } @@ -722,6 +735,7 @@ implement { implement { name = "newindexedtable", protected = true, + untraced = true, public = true, actions = function() newtable(true) end, } @@ -974,6 +988,7 @@ do implement { name = "codedef", public = true, + untraced = true, protected = true, actions = function(what) local name = scancsname(true) diff --git a/tex/context/base/mkxl/colo-ini.mkxl b/tex/context/base/mkxl/colo-ini.mkxl index 07d35089d..2c9c93950 100644 --- a/tex/context/base/mkxl/colo-ini.mkxl +++ b/tex/context/base/mkxl/colo-ini.mkxl @@ -1129,10 +1129,10 @@ \letcsname\??colorsetter \endcsname\empty \letcsname\??colorattribute \endcsname\!!zerocount \letcsname\??transparencysetter\endcsname\empty \letcsname\??transparencyattribute\endcsname\!!zerocount -\def\colo_helpers_inherited_direct_cs#1{\ifcsname\??colorsetter #1\endcsname\lastnamedcs\fi} -\def\colo_helpers_inherited_direct_ca#1{\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\!!zerocount\fi} -\def\colo_helpers_inherited_direct_ts#1{\ifcsname\??transparencysetter #1\endcsname\lastnamedcs\fi} -\def\colo_helpers_inherited_direct_ta#1{\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi} +\def\colo_helpers_inherited_direct_cs#1{\begincsname\??colorsetter #1\endcsname} +\def\colo_helpers_inherited_direct_ca#1{\ifcsname \??colorattribute #1\endcsname\lastnamedcs\else\!!zerocount\fi} +\def\colo_helpers_inherited_direct_ts#1{\begincsname\??transparencysetter #1\endcsname} +\def\colo_helpers_inherited_direct_ta#1{\ifcsname \??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi} \let\colo_defcsname\defcsname \let\colo_endcsname\endcsname diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index da3244da2..caa9a866b 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.06.14 17:06} +\newcontextversion{2021.06.24 18:50} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index d51a92236..17c5ec38d 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2021.06.14 17:06} +\immutable\edef\contextversion{2021.06.24 18:50} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error diff --git a/tex/context/base/mkxl/core-env.mkxl b/tex/context/base/mkxl/core-env.mkxl index 86be40548..f3d0a62ba 100644 --- a/tex/context/base/mkxl/core-env.mkxl +++ b/tex/context/base/mkxl/core-env.mkxl @@ -407,7 +407,7 @@ \permanent\def\autosetups#1{\clf_autosetups{#1}} % todo: public implementor -\permanent\edef\setupwithargument#1% saves a few expansions +\permanent\edef\setupwithargument#1% saves a few expansions and is faster {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#1\endcsname#1\noexpand\else\??empty\noexpand\fi\endcsname} \permanent\edef\setupwithargumentswapped#1#2% saves a few expansions (can be \let) diff --git a/tex/context/base/mkxl/font-chk.lmt b/tex/context/base/mkxl/font-chk.lmt index f14e89aeb..b5a875261 100644 --- a/tex/context/base/mkxl/font-chk.lmt +++ b/tex/context/base/mkxl/font-chk.lmt @@ -168,6 +168,9 @@ function checkers.placeholder(font,char) local scale = units/1000 local rawdata = tfmdata.shared and tfmdata.shared.rawdata local weight = (rawdata and rawdata.metadata and rawdata.metadata.pfmweight or 400)/400 +-- if slant then +-- slant = 0.2 +-- end local specification = { code = "MissingGlyph", scale = scale, diff --git a/tex/context/base/mkxl/font-con.lmt b/tex/context/base/mkxl/font-con.lmt index 25aa9b1bc..a9a04557b 100644 --- a/tex/context/base/mkxl/font-con.lmt +++ b/tex/context/base/mkxl/font-con.lmt @@ -511,6 +511,10 @@ function constructors.scale(tfmdata,specification) targetproperties.oldmath = oldmath target.oldmath = oldmath + local mathcontrol = properties.mathcontrol + targetproperties.mathcontrol = mathcontrol + target.mathcontrol = mathcontrol + else properties.hasmath = false target.nomath = true diff --git a/tex/context/base/mkxl/font-imp-math.lmt b/tex/context/base/mkxl/font-imp-math.lmt index 277190f24..c505d7ddf 100644 --- a/tex/context/base/mkxl/font-imp-math.lmt +++ b/tex/context/base/mkxl/font-imp-math.lmt @@ -99,7 +99,7 @@ function fonts.helpers.mathscriptslots(tfmdata,textcode) end end -local function manipulate(tfmdata,key,value) +local function manipulate(tfmdata,value) if texconditionals["c_font_compact"] then local rawdata = tfmdata.shared.rawdata local rawresources = rawdata and rawdata.resources @@ -140,7 +140,7 @@ local function manipulate(tfmdata,key,value) end end -local function initialize(tfmdata,key,value) +local function initialize(tfmdata,value) if texconditionals["c_font_compact"] then local rawdata = tfmdata.shared.rawdata local rawresources = rawdata and rawdata.resources @@ -199,7 +199,7 @@ registerotffeature(specification) -- end -- end -local function initialize(tfmdata,key,value) +local function initialize(tfmdata,value) if value then local rawdata = tfmdata.shared.rawdata local rawresources = rawdata and rawdata.resources @@ -224,3 +224,27 @@ local specification = { } registerotffeature(specification) + +local function initialize(tfmdata,value) + if type(value) == "string" then + local rawdata = tfmdata.shared.rawdata + local rawresources = rawdata and rawdata.resources + local mathconstants = rawresources.mathconstants + if mathconstants then + local bitmap = tex.stringtocodesbitmap(value,tex.mathcontrolcodes) + -- logs.report("mathfont","setting math control to %08X",bitmap) + tfmdata.properties.mathcontrol = bitmap + end + end +end + +local specification = { + name = "mathcontrol", + description = "control specific old/new math handling", + initializers = { + base = initialize, + node = initialize, + } +} + +registerotffeature(specification) diff --git a/tex/context/base/mkxl/font-ots.lmt b/tex/context/base/mkxl/font-ots.lmt index def09684a..b8fbc9702 100644 --- a/tex/context/base/mkxl/font-ots.lmt +++ b/tex/context/base/mkxl/font-ots.lmt @@ -3824,7 +3824,7 @@ do -- This permits injection, watch the different arguments. Watch out, the arguments passed -- are not frozen as we might extend or change this. Is this used at all apart from some -- experiments? - local h, ok = handler(head,dataset,sequence,initialrl,font,dynamic) -- less arguments now + local h = handler(head,dataset,sequence,initialrl,font,dynamic) -- less arguments now if h and h ~= head then head = h end diff --git a/tex/context/base/mkxl/font-pre.mkxl b/tex/context/base/mkxl/font-pre.mkxl index 0ae90d7cf..52a7dc60f 100644 --- a/tex/context/base/mkxl/font-pre.mkxl +++ b/tex/context/base/mkxl/font-pre.mkxl @@ -501,6 +501,26 @@ % [boldened] % [extend=1.2] +%D Tweaks: +%D +%D \starttyping +%D \setupbodyfont[dejavu] +%D +%D \starttext +%D \startTEXpage[align={tolerant,stretch},offset=1ex] +%D {\addff{camelcasing} \samplefile{tufte}\par} +%D {\addff{uppercasing} \samplefile{tufte}\par} +%D {\addff{lowercasing} \samplefile{tufte}\par} +%D {\addff{primes} 123'345''\par} +%D \stopTEXpage +%D \stoptext +%D \stoptyping + +\definefontfeature[primes] [primes=yes] +\definefontfeature[uppercasing][uppercasing=yes] +\definefontfeature[lowercasing][lowercasing=yes] +\definefontfeature[camelcasing][camelcasing=yes] + %D Neat: % By eye: diff --git a/tex/context/base/mkxl/lang-ini.lmt b/tex/context/base/mkxl/lang-ini.lmt index be1b8f651..2030fb697 100644 --- a/tex/context/base/mkxl/lang-ini.lmt +++ b/tex/context/base/mkxl/lang-ini.lmt @@ -164,11 +164,16 @@ local function sethjcodes(instance,loaded,what,factor) loaded.codehash = h end -- - local function setcode(l) - local u = uccodes[l] + local function setcode(code) + local l = lccodes[code] -- just in case we get a mixture + local u = uccodes[code] -- just in case we get a mixture local s = l + if type(s) ~= "number" then + l = code + s = code + end if hjcounts then - local c = hjcounts[l] + local c = hjcounts[s] if c then c = c.count if not c then @@ -186,10 +191,9 @@ local function sethjcodes(instance,loaded,what,factor) end end sethjcode(instance,l,s) - h[l] = s if u ~= l and type(u) == "number" then sethjcode(instance,u,s) - h[u] = lccodes[l] + h[u] = s end end -- @@ -204,7 +208,7 @@ local function sethjcodes(instance,loaded,what,factor) end else -- hash: { ["chr"] = true, ... } - for k, v in next, c do + for k, v in sortedhash(c) do if v then setcode(utfbyte(k)) end diff --git a/tex/context/base/mkxl/libs-imp-curl.lmt b/tex/context/base/mkxl/libs-imp-curl.lmt index 05b2b8f48..0aa6d0855 100644 --- a/tex/context/base/mkxl/libs-imp-curl.lmt +++ b/tex/context/base/mkxl/libs-imp-curl.lmt @@ -19,6 +19,7 @@ if not curllib then return end local next, type = next, type local lower, gsub = string.lower, string.gsub +local dirname = file.dirname local mapping = { ["acceptencoding"] = 102, @@ -272,6 +273,9 @@ local function fetch(options) o[index] = value end end + -- if o.capath == true then + -- o.capath = libpath + -- end return curl_fetch(o) elseif t == "string" then return curl_fetch { [mapping.url] = options } @@ -288,10 +292,19 @@ local curl = { escape = function (s) return okay() and curl_escape (s) end, unescape = function (s) return okay() and curl_unescape (s) end, fetch = fetch, + libfile = libfile, + libpath = dirname(libfile), } -- inspect(curl.fetch("http://www.pragma-ade.com/index.html")) -- inspect(curl.fetch { url = "http://www.pragma-ade.com/index.html" }) +-- +-- inspect(curl.fetch { +-- url = "https://www.ctan.org/json/2.0/packages", +-- sslverifyhost = 0, +-- sslverifypeer = 0, +-- -- capath = true +-- } ) package.loaded[libname] = curl diff --git a/tex/context/base/mkxl/libs-imp-lzma.lmt b/tex/context/base/mkxl/libs-imp-lzma.lmt new file mode 100644 index 000000000..69762a54c --- /dev/null +++ b/tex/context/base/mkxl/libs-imp-lzma.lmt @@ -0,0 +1,52 @@ +if not modules then modules = { } end modules ['libs-imp-lzma'] = { + version = 1.001, + comment = "companion to luat-lib.mkxl", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- Instead of linking in libs like this we now do them optional. After all, once +-- we start adding more and more stuff statically we en dup with a mess. + +local libname = "lzma" +local libfile = "liblzma" + +local lzmalib = resolvers.libraries.validoptional(libname) + +if not lzmalib then return end + +local lzma_compress = lzmalib.compress +local lzma_decompress = lzmalib.decompress + +local function okay() + if resolvers.libraries.optionalloaded(libname,libfile) then + okay = function() return true end + else + okay = function() return false end + end + return okay() +end + +local lzma = { + compress = function (...) return okay() and lzma_compress (...) end, + decompress = function (...) return okay() and lzma_decompress (...) end, +} + +package.loaded[libname] = lzma + +-- local raw = io.loaddata("e:/luatex/luametatex-source.tar") +-- local old = io.loaddata("e:/luatex/luametatex-source.tar.xz") +-- local new = lzma.decompress(old) +-- local xz1 = lzma.compress(raw,9) +-- local xz2 = lzma.decompress(xz1) + +-- print("raw",raw and #raw) +-- print("old",old and #old) +-- print("new",new and #new) +-- print("chk",new == raw) +-- print("xz1",xz1 and #xz1) +-- print("xz2",xz2 and #xz2) +-- print("chk",xz2 == raw) + +return lzma diff --git a/tex/context/base/mkxl/lpdf-col.lmt b/tex/context/base/mkxl/lpdf-col.lmt index e76471b89..28413fd9a 100644 --- a/tex/context/base/mkxl/lpdf-col.lmt +++ b/tex/context/base/mkxl/lpdf-col.lmt @@ -558,7 +558,9 @@ end lpdf.color = lpdfcolor interfaces.implement { - name = "lpdf_color", + name = "pdfcolor", + public = true, + untraced = true, actions = { lpdfcolor, context }, arguments = "integer" } diff --git a/tex/context/base/mkxl/lpdf-emb.lmt b/tex/context/base/mkxl/lpdf-emb.lmt index fd0f0cf6b..4781b5bad 100644 --- a/tex/context/base/mkxl/lpdf-emb.lmt +++ b/tex/context/base/mkxl/lpdf-emb.lmt @@ -85,6 +85,8 @@ local getmapentry = fonts.mappings.getentry -- needs checking: signed vs unsigned +-- todo: use streams.tocardinal4 etc + local tocardinal1 = char local function tocardinal2(n) diff --git a/tex/context/base/mkxl/lpdf-ini.lmt b/tex/context/base/mkxl/lpdf-ini.lmt index f58727edf..3b2ee17ac 100644 --- a/tex/context/base/mkxl/lpdf-ini.lmt +++ b/tex/context/base/mkxl/lpdf-ini.lmt @@ -1278,19 +1278,20 @@ do end --- interface - -implement { name = "lpdf_collectedresources", actions = { lpdf.collectedresources, context } } -implement { name = "lpdf_addtocatalog", arguments = "2 strings", actions = lpdf.addtocatalog } -implement { name = "lpdf_addtoinfo", arguments = "2 strings", actions = function(a,b,c) lpdf.addtoinfo(a,b,c) end } -- gets adapted -implement { name = "lpdf_addtonames", arguments = "2 strings", actions = lpdf.addtonames } -implement { name = "lpdf_addtopageattributes", arguments = "2 strings", actions = lpdf.addtopageattributes } -implement { name = "lpdf_addtopagesattributes", arguments = "2 strings", actions = lpdf.addtopagesattributes } -implement { name = "lpdf_addtopageresources", arguments = "2 strings", actions = lpdf.addtopageresources } -implement { name = "lpdf_adddocumentextgstate", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentextgstate (a,pdfverbose(b)) end } -implement { name = "lpdf_adddocumentcolorspace", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentcolorspace(a,pdfverbose(b)) end } -implement { name = "lpdf_adddocumentpattern", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentpattern (a,pdfverbose(b)) end } -implement { name = "lpdf_adddocumentshade", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentshade (a,pdfverbose(b)) end } +-- Bah, tikz uses \immediate for some reason which is probably a bug, so the usage +-- will deal with that. However, we will not provide the serialization. + +implement { name = "pdfbackendcurrentresources", public = true, untraced = true, actions = { lpdf.collectedresources, context } } +implement { name = "pdfbackendsetcatalog", usage = "value", public = true, protected = true, arguments = "2 arguments", actions = lpdf.addtocatalog } +implement { name = "pdfbackendsetinfo", usage = "value", public = true, protected = true, arguments = "2 arguments", actions = function(a,b,c) lpdf.addtoinfo(a,b,c) end } -- gets adapted +implement { name = "pdfbackendsetname", usage = "value", public = true, protected = true, arguments = "2 arguments", actions = lpdf.addtonames } +implement { name = "pdfbackendsetpageattribute", usage = "value", public = true, protected = true, arguments = "2 arguments", actions = lpdf.addtopageattributes } +implement { name = "pdfbackendsetpagesattribute", usage = "value", public = true, protected = true, arguments = "2 arguments", actions = lpdf.addtopagesattributes } +implement { name = "pdfbackendsetpageresource", usage = "value", public = true, protected = true, arguments = "2 arguments", actions = lpdf.addtopageresources } +implement { name = "pdfbackendsetextgstate", usage = "value", public = true, protected = true, arguments = "2 arguments", actions = function(a,b) lpdf.adddocumentextgstate (a,pdfverbose(b)) end } +implement { name = "pdfbackendsetcolorspace", usage = "value", public = true, protected = true, arguments = "2 arguments", actions = function(a,b) lpdf.adddocumentcolorspace(a,pdfverbose(b)) end } +implement { name = "pdfbackendsetpattern", usage = "value", public = true, protected = true, arguments = "2 arguments", actions = function(a,b) lpdf.adddocumentpattern (a,pdfverbose(b)) end } +implement { name = "pdfbackendsetshade", usage = "value", public = true, protected = true, arguments = "2 arguments", actions = function(a,b) lpdf.adddocumentshade (a,pdfverbose(b)) end } -- more helpers: copy from lepd to lpdf diff --git a/tex/context/base/mkxl/luat-cnf.lmt b/tex/context/base/mkxl/luat-cnf.lmt index 081f2462f..ea9eb0d89 100644 --- a/tex/context/base/mkxl/luat-cnf.lmt +++ b/tex/context/base/mkxl/luat-cnf.lmt @@ -224,4 +224,4 @@ local function makestub() report() end -lua.registerfinalizer(makestub,"create stub file") +lua.registerinitexfinalizer(makestub,"create stub file") diff --git a/tex/context/base/mkxl/luat-cod.lmt b/tex/context/base/mkxl/luat-cod.lmt index 7047726b5..2e5fa8062 100644 --- a/tex/context/base/mkxl/luat-cod.lmt +++ b/tex/context/base/mkxl/luat-cod.lmt @@ -99,28 +99,6 @@ function lua.registercode(filename,options) end end -local finalizers = { } - -function lua.registerfinalizer(f,comment) - comment = comment or "unknown" - if type(f) == "function" then - finalizers[#finalizers+1] = { action = f, comment = comment } - else - print(format("\nfatal error: invalid finalizer, action: %s\n",comment)) - os.exit() - end -end - -function lua.finalize(logger) - for i=1,#finalizers do - local finalizer = finalizers[i] - finalizer.action() - if logger then - logger("finalize action: %s",finalizer.comment) - end - end -end - -- A first start with environments. This will be overloaded later. environment = environment or { } @@ -175,6 +153,37 @@ environment.jitsupported = JITSUPPORTED environment.initex = INITEXMODE environment.initexmode = INITEXMODE +if INITEXMODE then + + local finalizers = { } + + function lua.registerinitexfinalizer(f,comment) + comment = comment or "unknown" + if type(f) == "function" then + finalizers[#finalizers+1] = { action = f, comment = comment } + else + print(format("\nfatal error: invalid finalizer, action: %s\n",comment)) + os.exit() + end + end + + function lua.finalizeinitex(logger) + for i=1,#finalizers do + local finalizer = finalizers[i] + finalizer.action() + if logger then + logger("finalize action: %s",finalizer.comment) + end + end + end + +else + + function lua.registerinitexfinalizer() end + function lua.finalizeinitex () end + +end + -- if INITEXMODE then -- -- we have about that amount so we preallocate then which gives less -- -- reallocations (we're talking tiny record so no real gain) diff --git a/tex/context/base/mkxl/luat-lib.mkxl b/tex/context/base/mkxl/luat-lib.mkxl index a01e7f86f..d26c90af5 100644 --- a/tex/context/base/mkxl/luat-lib.mkxl +++ b/tex/context/base/mkxl/luat-lib.mkxl @@ -46,6 +46,7 @@ \registerctxluafile{util-soc-imp-tp} {} \registerctxluafile{util-zip}{} +\registerctxluafile{util-tar}{} \registerctxluafile{data-ini}{} \registerctxluafile{data-exp}{} @@ -62,6 +63,8 @@ \registerctxluafile{data-tex}{} % after data-pre \registerctxluafile{data-vir}{} \registerctxluafile{data-zip}{} +\registerctxluafile{data-dec}{} +\registerctxluafile{data-tar}{} %registerctxluafile{data-crl}{} \registerctxluafile{data-sch}{} \registerctxluafile{data-tre}{} @@ -74,7 +77,7 @@ \registerctxluafile{luat-cbk}{autosuffix} \registerctxluafile{luat-run}{autosuffix} \registerctxluafile{luat-fio}{autosuffix} -\registerctxluafile{luat-cnf}{autosuffix} +\registerctxluafile{luat-cnf}{autosuffix,initexonly} \registerctxluafile{luat-lua}{} \registerctxluafile{luat-sto}{} \registerctxluafile{luat-ini}{autosuffix} diff --git a/tex/context/base/mkxl/luat-run.lmt b/tex/context/base/mkxl/luat-run.lmt index 075f5bd62..fa3336d4b 100644 --- a/tex/context/base/mkxl/luat-run.lmt +++ b/tex/context/base/mkxl/luat-run.lmt @@ -102,7 +102,7 @@ local function pre_dump_actions() for i=1,#dumpactions do dumpactions[i]() end - lua.finalize(trace_lua_dump and report_lua or nil) + lua.finalizeinitex(trace_lua_dump and report_lua or nil) end local function wrapup_synctex() diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl index df2bb7ccb..37c48121c 100644 --- a/tex/context/base/mkxl/math-ini.mkxl +++ b/tex/context/base/mkxl/math-ini.mkxl @@ -122,10 +122,16 @@ \definesystemattribute[displaymath] [public] -\mathflattenmode 31 +\mathflattenmode\numexpr + \ordflattencode + +\binflattencode + +\relflattencode + +\punctflattencode + +\innerflattencode +\relax \ifdefined\ordlimits\else - \let\ordlimits\limits + \let\ordlimits\Umathlimits % downward compatible \fi \appendtoks @@ -3003,6 +3009,38 @@ \normalsupmarkmode\plusone % 2 also disable ^[^+] in text mode +\permanent\protected\tolerant\def\supscr[#1]#:#2% + {\ifchkdim#1\or\Umathopenupheight#1\relax\fi + \Usuperscript{#2}} + +\permanent\protected\tolerant\def\subscr[#1]#:#2% + {\ifchkdim#1\or\Umathopenupdepth #1\relax\fi + \Usubscript{#2}} + +\permanent\protected\tolerant\def\supsubscr[#1]#:#2#3% + {\ifchkdim#1\or\Umathopenupheight#1\relax\Umathopenupdepth#1\relax\fi + \Usuperscript{#2}\Usubscript{#3}} + +\permanent\protected\tolerant\def\subsupscr[#1]#:#*#2#3% + {\ifchkdim#1\or\Umathopenupheight#1\relax\Umathopenupdepth#1\relax\fi + \Usubscript{#2}\Usuperscript{#3}} + +\permanent\protected\tolerant\def\supprescr[#1]#:#2% + {\ifchkdim#1\or\Umathopenupheight#1\relax\fi + \Usuperprescript{#2}} + +\permanent\protected\tolerant\def\subprescr[#1]#:#2% + {\ifchkdim#1\or\Umathopenupdepth #1\relax\fi + \Usubprescript{#2}} + +\permanent\protected\tolerant\def\supsubprescr[#1]#:#2#3% + {\ifchkdim#1\or\Umathopenupheight#1\relax\Umathopenupdepth#1\relax\fi + \Usuperprescript{#2}\Usubprescript{#3}} + +\permanent\protected\tolerant\def\subsupprescr[#1]#:#*#2#3% + {\ifchkdim#1\or\Umathopenupheight#1\relax\Umathopenupdepth#1\relax\fi + \Usubprescript{#2}\Usuperprescript{#3}} + \protect \endinput % % not used (yet) diff --git a/tex/context/base/mkxl/math-noa.lmt b/tex/context/base/mkxl/math-noa.lmt index 5ce0702de..09c67b8a1 100644 --- a/tex/context/base/mkxl/math-noa.lmt +++ b/tex/context/base/mkxl/math-noa.lmt @@ -182,20 +182,17 @@ local nodecodes = nodes.nodecodes local noadcodes = nodes.noadcodes local fencecodes = nodes.fencecodes -local ordnoad_code = noadcodes.ord -local opdisplaylimitsnoad_code = noadcodes.opdisplaylimits -local oplimitsnoad_code = noadcodes.oplimits -local opnolimitsnoad_code = noadcodes.opnolimits -local binnoad_code = noadcodes.bin -local relnode_code = noadcodes.rel -local opennoad_code = noadcodes.open -local closenoad_code = noadcodes.close -local punctnoad_code = noadcodes.punct -local innernoad_code = noadcodes.inner -local undernoad_code = noadcodes.under -local overnoad_code = noadcodes.over -local vcenternoad_code = noadcodes.vcenter -local ordlimitsnoad_code = noadcodes.ordlimits or oplimitsnoad_code +local ordnoad_code = noadcodes.ord +local opnoad_code = noadcodes.op +local binnoad_code = noadcodes.bin +local relnode_code = noadcodes.rel +local opennoad_code = noadcodes.open +local closenoad_code = noadcodes.close +local punctnoad_code = noadcodes.punct +local innernoad_code = noadcodes.inner +local undernoad_code = noadcodes.under +local overnoad_code = noadcodes.over +local vcenternoad_code = noadcodes.vcenter local noad_code = nodecodes.noad -- attr nucleus sub sup local accent_code = nodecodes.accent -- attr nucleus sub sup accent @@ -1801,20 +1798,17 @@ do local collapse = { } local mathlists = characters.mathlists local validpair = { - [ordnoad_code] = true, - [opdisplaylimitsnoad_code] = true, - [oplimitsnoad_code] = true, - [opnolimitsnoad_code] = true, - [binnoad_code] = true, -- new - [relnode_code] = true, - [opennoad_code] = true, -- new - [closenoad_code] = true, -- new - [punctnoad_code] = true, -- new - [innernoad_code] = false, - [undernoad_code] = false, - [overnoad_code] = false, - [vcenternoad_code] = false, - [ordlimitsnoad_code] = true, + [ordnoad_code] = true, + [opnoad_code] = true, + [binnoad_code] = true, -- new + [relnode_code] = true, + [opennoad_code] = true, -- new + [closenoad_code] = true, -- new + [punctnoad_code] = true, -- new + [innernoad_code] = false, + [undernoad_code] = false, + [overnoad_code] = false, + [vcenternoad_code] = false, } local reported = setmetatableindex("table") @@ -2099,20 +2093,17 @@ do local classes = { } local colors = { - [relnode_code] = "trace:dr", - [ordnoad_code] = "trace:db", - [binnoad_code] = "trace:dg", - [opennoad_code] = "trace:dm", - [closenoad_code] = "trace:dm", - [punctnoad_code] = "trace:dc", - -- [opdisplaylimitsnoad_code] = "", - -- [oplimitsnoad_code] = "", - -- [opnolimitsnoad_code] = "", - -- [ordlimitsnoad_code] = "", - -- [innernoad_code = "", - -- [undernoad_code] = "", - -- [overnoad_code] = "", - -- [vcenternoad_code] = "", + [relnode_code] = "trace:dr", + [ordnoad_code] = "trace:db", + [binnoad_code] = "trace:dg", + [opennoad_code] = "trace:dm", + [closenoad_code] = "trace:dm", + [punctnoad_code] = "trace:dc", + -- [opnoad_code] = "", + -- [innernoad_code = "", + -- [undernoad_code] = "", + -- [overnoad_code] = "", + -- [vcenternoad_code] = "", } local setcolor = colortracers.set @@ -2325,33 +2316,25 @@ end -- the normal builder -do - - local force_penalties = false - - -- registertracker("math.penalties",function(v) - -- force_penalties = v - -- end) - - function builders.kernel.mlisttohlist(head,style,penalties) - return mlisttohlist(head,style,force_penalties or penalties) - end - - -- function builders.kernel.mlisttohlist(head,style,penalties) - -- local h = mlisttohlist(head,style,force_penalties or penalties) - -- inspect(nodes.totree(h,true,true,true)) - -- return h - -- end - - implement { - name = "setmathpenalties", - arguments = "integer", - actions = function(p) - force_penalties = p > 0 - end, - } +-- do +-- +-- local force_penalties = false +-- +-- function builders.kernel.mlisttohlist(head,style,penalties) +-- return mlisttohlist(head,style,force_penalties or penalties) +-- end +-- +-- implement { +-- name = "setmathpenalties", +-- arguments = "integer", +-- actions = function(p) +-- force_penalties = p > 0 +-- end, +-- } +-- +-- end -end +builders.kernel.mlisttohlist = mlisttohlist local actions = tasks.actions("math") -- head, style, penalties diff --git a/tex/context/base/mkxl/math-stc.mklx b/tex/context/base/mkxl/math-stc.mklx index 944185c23..b819c3ca5 100644 --- a/tex/context/base/mkxl/math-stc.mklx +++ b/tex/context/base/mkxl/math-stc.mklx @@ -116,7 +116,7 @@ % $\Umathaccent 0 0 "2190{x}$ \par $\Umathaccent 0 0 "27F8{x}$\par % $\Udelimiterunder 0 "2190{x}$ \par $\Udelimiterunder 0 "27F8{x}$\par -\setvalue{\??mathextensiblefallbacks}% +\defcsname\??mathextensiblefallbacks\endcsname {\hpack{\vrule\s!width\scratchwidth\s!height.1\mathexheight\s!depth\zeropoint}} % \def\math_stackers_with_fallback#codepoint% @@ -201,12 +201,12 @@ \installcorenamespace {mathstackerslocation} \installcorenamespace {mathstackersalternative} -\letvalue{\??mathstackerslocation\v!top }\plusone % on top of baseline -\letvalue{\??mathstackerslocation\v!high }\plustwo % 25 % down -\letvalue{\??mathstackerslocation\v!middle }\plusthree % centered -\letvalue{\??mathstackerslocation\v!low }\plusfour % 75 % down -\letvalue{\??mathstackerslocation\v!bottom }\plusfive % below baseline -\letvalue{\??mathstackerslocation }\zerocount +\letcsname\??mathstackerslocation\v!top \endcsname\plusone % on top of baseline +\letcsname\??mathstackerslocation\v!high \endcsname\plustwo % 25 % down +\letcsname\??mathstackerslocation\v!middle \endcsname\plusthree % centered +\letcsname\??mathstackerslocation\v!low \endcsname\plusfour % 75 % down +\letcsname\??mathstackerslocation\v!bottom \endcsname\plusfive % below baseline +\letcsname\??mathstackerslocation \endcsname\zerocount %D First we implement the helper that deals with an extensible in the middle and %D top and|/|or bottom texts: @@ -242,8 +242,8 @@ % no checking, we assume sane use -\letvalue{\??mathstackersalternative\v!normal }\math_stackers_content -\letvalue{\??mathstackersalternative\v!default}\math_stackers_content +\letcsname\??mathstackersalternative\v!normal \endcsname\math_stackers_content +\letcsname\??mathstackersalternative\v!default\endcsname\math_stackers_content \setupmathstackers [\c!mp=math:stacker:\number\scratchunicode, @@ -251,7 +251,7 @@ \c!mpdepth=\mathchardp\scratchunicode, \c!mpoffset=.25\mathexheight] -\setvalue{\??mathstackersalternative\v!mp}% +\defcsname\??mathstackersalternative\v!mp\endcsname {\normalexpanded{\math_stackers_mp_box {\the\dimexpr\mathstackersparameter\c!mpheight}% {\the\dimexpr\mathstackersparameter\c!mpdepth}% @@ -526,9 +526,9 @@ \installcorenamespace {mathclasses} -\letvalue{\??mathclasses }\mathord -\letvalue{\??mathclasses rel}\mathrel -\letvalue{\??mathclasses ord}\mathord +\letcsname\??mathclasses \endcsname\mathord +\letcsname\??mathclasses rel\endcsname\mathrel +\letcsname\??mathclasses ord\endcsname\mathord \def\math_class_by_parameter#1% {\normalexpanded{\noexpand\math_class_by_parameter_indeed{#1\c!mathclass}}} diff --git a/tex/context/base/mkxl/math-tag.lmt b/tex/context/base/mkxl/math-tag.lmt index a602870c9..80e78b328 100644 --- a/tex/context/base/mkxl/math-tag.lmt +++ b/tex/context/base/mkxl/math-tag.lmt @@ -555,8 +555,12 @@ process = function(start) -- we cannot use the processor as we have no finalizer processsubsup(start) end elseif id == glue_code then - -- setattr(start,a_tagged,start_tagged("mspace",{ width = getwidth(start) })) - setattr(start,a_tagged,start_tagged("mspace")) + -- before processing, so other intermathglue is not tagged + local em = fonts.hashes.emwidths[nuts.getfont(start)] + local wd = getwidth(start) + if em and wd then + setattr(start,a_tagged,start_tagged("mspace",{ emfactor = wd/em })) + end stop_tagged() else setattr(start,a_tagged,start_tagged("merror", { detail = nodecodes[i] })) diff --git a/tex/context/base/mkxl/mlib-mpf.lmt b/tex/context/base/mkxl/mlib-mpf.lmt index b03c664b8..f60f31076 100644 --- a/tex/context/base/mkxl/mlib-mpf.lmt +++ b/tex/context/base/mkxl/mlib-mpf.lmt @@ -941,6 +941,7 @@ do local scanstring = scan.string local scannumeric = scan.numeric + local scaninteger = scan.integer local skiptoken = skip.token ----- injectstring = inject.string @@ -982,7 +983,7 @@ do registerscript("setglobalmacro", function() setmacro(scanstring(),scanstring(),"global") end) registerscript("setglobaldimen", function() setdimen("global",scanstring(),scannumeric()/bpfactor) end) - registerscript("setglobalcount", function() setcount("global",scanstring(),scannumeric()) end) + registerscript("setglobalcount", function() setcount("global",scanstring(),scaninteger()) end) registerscript("setglobaltoks", function() settoks ("global",scanstring(),scanstring()) end) local utfnum = utf.byte diff --git a/tex/context/base/mkxl/mlib-pps.lmt b/tex/context/base/mkxl/mlib-pps.lmt index 6f38f30ff..cae1bbb5f 100644 --- a/tex/context/base/mkxl/mlib-pps.lmt +++ b/tex/context/base/mkxl/mlib-pps.lmt @@ -1021,7 +1021,7 @@ local tx_reset, tx_process do end end - local fasttrack = true + local fasttrack = false -- we loose colors done with withcolor when true directives.register("metapost.text.fasttrack", function(v) fasttrack = v end) diff --git a/tex/context/base/mkxl/node-ext.lmt b/tex/context/base/mkxl/node-ext.lmt index 9068cd976..896dd8f99 100644 --- a/tex/context/base/mkxl/node-ext.lmt +++ b/tex/context/base/mkxl/node-ext.lmt @@ -51,7 +51,8 @@ local whatsitcodes = allocate { } nodes.whatsitcodes = whatsitcodes local lastwhatsit = 0 -nodes.subtypes.whatsit = whatsitcodes +nodes.subtypes.whatsit = whatsitcodes +nodes.subtypes[whatsit_code] = whatsitcodes local function registerwhatsit(name) lastwhatsit = lastwhatsit + 1 @@ -165,6 +166,7 @@ do name = "latelua", public = true, protected = true, + untraced = true, actions = function() local node = copynut(lateluanode) local name = "latelua" diff --git a/tex/context/base/mkxl/node-fin.lmt b/tex/context/base/mkxl/node-fin.lmt index ae5d0eac5..ffabd25ea 100644 --- a/tex/context/base/mkxl/node-fin.lmt +++ b/tex/context/base/mkxl/node-fin.lmt @@ -198,11 +198,12 @@ local function process(attribute,head,inheritance,default) -- one attribute elseif id == hlist_code or id == vlist_code then -- tricky checking local outer - if subtype == container_code then - check = true - current = 0 - end - if getorientation(stack) then +-- if subtype == container_code then +-- check = true +-- current = 0 +-- end +-- if getorientation(stack) then + if subtype == container_code or getorientation(stack) then outer = getattr(stack,attribute) if outer then if default and outer == inheritance then @@ -321,11 +322,12 @@ local function simple(attribute,head) check = true leader = content elseif id == hlist_code or id == vlist_code then - if subtype == container_code then - check = true -current = 0 - end - if getorientation(stack) then +-- if subtype == container_code then +-- check = true +-- current = 0 +-- end +-- if getorientation(stack) then + if subtype == container_code or getorientation(stack) then local outer = getattr(stack,attribute) if outer then if current ~= outer then @@ -526,13 +528,14 @@ local function selective(attribute,head,inheritance,default) -- two attributes check = true leader = content -- getleader(stack) elseif id == hlist_code or id == vlist_code then - -- tricky checking - if subtype == container_code then - check = true -current = 0 - end local outer, s - if getorientation(stack) then + -- tricky checking +-- if subtype == container_code then +-- check = true +-- current = 0 +-- end +-- if getorientation(stack) then +if subtype == container_code or getorientation(stack) then outer, s = getattrs(stack,attribute,nsselector) if outer then if default and outer == inheritance then diff --git a/tex/context/base/mkxl/node-res.lmt b/tex/context/base/mkxl/node-res.lmt index fbf52ae3b..b1ab7e22b 100644 --- a/tex/context/base/mkxl/node-res.lmt +++ b/tex/context/base/mkxl/node-res.lmt @@ -538,7 +538,7 @@ statistics.register("node memory usage", function() -- comes after cleanup ! end end) -lua.registerfinalizer(cleanup, "cleanup reserved nodes") +lua.registerinitexfinalizer(cleanup, "cleanup reserved nodes") do diff --git a/tex/context/base/mkxl/pack-rul.mkxl b/tex/context/base/mkxl/pack-rul.mkxl index 36266bc98..c4e510623 100644 --- a/tex/context/base/mkxl/pack-rul.mkxl +++ b/tex/context/base/mkxl/pack-rul.mkxl @@ -642,10 +642,48 @@ \box\b_framed_normal \box\b_framed_extra}} +%D A probably unknown feature: +%D +%D \startbuffer +%D \hpack\bgroup +%D \framed[framecolor=MyColor,frame=on] {!!!!!!!!} +%D \framed[framecolor=MyColor,frame=closed]{!!!!!!!!} +%D \framed[framecolor=MyColor,frame=small] {!!!!!!!!} +%D \egroup +%D \stopbuffer +%D +%D \typebuffer \startlinecorrection[blank] \getbuffer \stoplinecorrection + +% \def\pack_framed_stroked_box_normal_opened +% {\setbox\scratchbox\vpack \bgroup +% \csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname +% \nointerlineskip % new (needed for fences) +% \hpack \bgroup +% \csname\??framedleft\p_framed_frame\framedparameter\c!leftframe\endcsname +% \novrule +% \s!width \d_framed_target_wd +% \s!height\d_framed_target_ht +% \s!depth \d_framed_target_dp +% \csname\??framedright\p_framed_frame\framedparameter\c!rightframe\endcsname +% \egroup +% \nointerlineskip % new (needed for fences) +% \csname\??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname +% \egroup +% \wd\scratchbox\d_framed_target_wd +% \ht\scratchbox\d_framed_target_ht +% \dp\scratchbox\d_framed_target_dp +% \box\scratchbox} + +% less logging: + \def\pack_framed_stroked_box_normal_opened {\setbox\scratchbox\vpack \bgroup + % \normaloffinterlineskip % sets baselineskip, lineskip and lineskiplimit + \baselineskip-\thousandpoint + \lineskip \zeropoint + \lineskiplimit\maxdimen \csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname - \nointerlineskip % new (needed for fences) + % \nointerlineskip % new (needed for fences) \hpack \bgroup \csname\??framedleft\p_framed_frame\framedparameter\c!leftframe\endcsname \novrule @@ -654,7 +692,7 @@ \s!depth \d_framed_target_dp \csname\??framedright\p_framed_frame\framedparameter\c!rightframe\endcsname \egroup - \nointerlineskip % new (needed for fences) + % \nointerlineskip % new (needed for fences) \csname\??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname \egroup \wd\scratchbox\d_framed_target_wd @@ -704,10 +742,27 @@ % no overlapping rules -\def\pack_framed_t_rules{\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth} -\def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}} -\def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth} -\def\pack_framed_l_rules{\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth\kern-\d_framed_linewidth} +% \def\pack_framed_t_rules{\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth} +% \def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}} +% \def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth} +% \def\pack_framed_l_rules{\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth\kern-\d_framed_linewidth} +% +% see above, less tracing +% +% \def\pack_framed_t_rules{\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}\kern-\d_framed_linewidth} +% \def\pack_framed_b_rules{\kern-\d_framed_linewidth\hpack{\kern\d_framed_linewidth\vrule\s!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\s!height\d_framed_linewidth}} +% \def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth} +% \def\pack_framed_l_rules{\vrule\s!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\s!depth-\d_framed_linewidth\s!width\d_framed_linewidth\kern-\d_framed_linewidth} +% +% more modern: + +\def\pack_framed_rules_hrule{\hrule\s!height\d_framed_linewidth\s!left\d_framed_linewidth\s!right \d_framed_linewidth} +\def\pack_framed_rules_vrule{\vrule\s!width \d_framed_linewidth\s!top \d_framed_linewidth\s!bottom\d_framed_linewidth\s!yoffset-\d_framed_linewidth} + +\def\pack_framed_t_rules{\pack_framed_rules_hrule\kern-\d_framed_linewidth} +\def\pack_framed_b_rules{\kern-\d_framed_linewidth\pack_framed_rules_hrule} +\def\pack_framed_r_rules{\kern-\d_framed_linewidth\pack_framed_rules_vrule} +\def\pack_framed_l_rules{\pack_framed_rules_vrule\kern-\d_framed_linewidth} \letcsname\??framedtop \v!small\v!small\endcsname\pack_framed_t_rules \letcsname\??framedtop \v!off \v!small\endcsname\pack_framed_t_rules diff --git a/tex/context/base/mkxl/page-ffl.mkxl b/tex/context/base/mkxl/page-ffl.mkxl index 7c0c5af9d..7c04d01e1 100644 --- a/tex/context/base/mkxl/page-ffl.mkxl +++ b/tex/context/base/mkxl/page-ffl.mkxl @@ -51,13 +51,93 @@ %D \startcontent \dorecurse{10}{\samplefile{ward} } \stopcontent %D \stopfacingfloat %D +%D \flushfacingfloats[whatever] +%D %D \dorecurse{10}{\samplefile{sapolsky} } +%D +%D \flushpendingtopcontent +%D %D \stoptyping %D %D The idea is to flush related floats more or less in parallel. \unprotect +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% \starttext +% +% \registertopcontent[3]\vbox{\framed[align=normal,width=\textwidth]{\samplefile{ward}}} +% \registertopcontent[3]\vbox{\framed[align=normal,width=\textwidth]{\samplefile{davis}}} +% \registertopcontent[5]\vbox{\framed[align=normal,width=\textwidth]{\samplefile{ward}}} +% +% \dorecurse{20}{\samplefile{tufte}\par} +% +% \stoptext + +\newdimen\d_page_adapts_preroll +\newcount\c_page_adapts_pushed + +% this assumes a constant textheight and no adaptations otherwise so we +% should block these for already set pages in adaptheight .. or we can +% make these independent (so not use adaptheight) + +\def\page_adapts_layout_preroll#1% + {\begingroup + \global\d_page_adapts_preroll\zeropoint + \def\page_adapts_layout_indeed##1% + {\setupcurrentadaptlayout[\c!top=\zeropoint,##1]% + \global\d_page_adapts_preroll\dimexpr\adaptlayoutparameter\c!top\relax} + \begincsname\??pageadaptations\number#1\endcsname + \endgroup} + +\permanent\protected\def\registertopcontent[#1]% + {\begingroup + \dowithnextbox + {\page_adapts_layout_preroll{#1}% + \scratchdimen\dimexpr + \htdp\nextbox+\d_page_adapts_preroll + \ifzeropt\d_page_adapts_preroll + +\lineheight + \fi + \relax + \putboxincache{\v!page:\number#1}{+}\nextbox + \normalexpanded{\adaptlayout[\number#1][\c!top=\the\scratchdimen]}% + \global\advance\c_page_adapts_pushed\plusone + \endgroup}} + +\def\page_otr_flush_top_content + {\scratchcounter\getboxcountfromcache{\v!page:\number\realpageno}\relax + \ifcase\scratchcounter\else + \dorecurse\scratchcounter + {\directboxfromcache{\v!page:\number\realpageno}\recurselevel + \nointerlineskip + \par}% + \disposeboxesincache{\v!page:\number\realpageno}% + \global\advance\c_page_adapts_pushed\minusone + \nointerlineskip + \fi} + +\permanent\protected\def\flushpendingtopcontent + {\ifcase\c_page_adapts_pushed\else + \null + \page + \expandafter\flushpendingtopcontent + \fi} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% \let\page_check_weird_page\relax + +\def\page_check_weird_page_indeed % for now only when facing floats + {\ifdim\vsize>\zeropoint\else + %\showmessage\m!layouts9{}% + \writestatus\m!layouts{forcing zero height page}% + \emptyhbox\page + \fi} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % width: % % -- fit : do nothing @@ -76,11 +156,17 @@ %\c!color, \c!width=\v!fit] +\newcount\c_defining_facing_float + \appendtoks - \ifempty\currentfacingfloatparent - \normalexpanded{\definefacingfloat[\currentfacingfloat:\v!left ][\currentfacingfloat]}% - \normalexpanded{\definefacingfloat[\currentfacingfloat:\v!right][\currentfacingfloat]}% + \advance\c_defining_facing_float\plusone + \ifcase\c_defining_facing_float\or + \expanded{ + \definefacingfloat[\currentfacingfloat:\v!left ][\currentfacingfloat]% + \definefacingfloat[\currentfacingfloat:\v!right][\currentfacingfloat]% + }% \fi + \advance\c_defining_facing_float\minusone \to \everydefinefacingfloat \newcount\c_strc_floats_facing_saved @@ -91,88 +177,79 @@ \let\m_strc_floats_state\relax -% \permanent\protected\def\strc_floats_facing_flush -% {\ifnum\c_strc_floats_facing_flushed<\c_strc_floats_facing_saved -% \ifodd\c_strc_floats_facing_flushed -% \ifodd\realpageno -% \strc_floats_facing_flush_indeed -% \doifelsependingpagecontent\relax{\kern\zeropoint\page}% -% \fi -% \else -% \ifodd\realpageno\else -% \strc_floats_facing_flush_indeed -% \doifelsependingpagecontent\relax{\kern\zeropoint\page}% -% \fi -% \fi -% \fi} -% -% \permanent\protected\def\strc_floats_facing_flush_indeed -% {\global\advance\c_strc_floats_facing_flushed\plusone -% \floatingpenalty\zerocount -% \page_inserts_inject\namedinsertionnumber\s!topfloat\bgroup -% \forgetall -% \ifconditional\c_page_one_top_of_insert -% \ifconditional\c_page_one_correct_top_insert -% \topskipcorrection % [xx] new: see icare topbleed -% \kern-\lineskip -% \par -% \prevdepth\maxdimen -% \fi -% \fi -% \directboxfromcache{\currentfacingfloat}{\number\c_strc_floats_facing_flushed}% -% \vkern\s_page_one_between_top_insert -% \egroup -% \ifnum\c_strc_floats_facing_saved=\c_strc_floats_facing_flushed -% \global\c_strc_floats_facing_saved \zerocount -% \global\c_strc_floats_facing_flushed\zerocount -% \resetboxesincache{\currentfacingfloat}% -% \fi} -% -% \aliased\let\flushfacingfloats\strc_floats_facing_flush - +\installcorenamespace {facingfloatflusher} -% \let\page_check_weird_page\relax - -\def\page_check_weird_page_indeed % for now only when facing floats - {\ifdim\vsize>\zeropoint\else - %\showmessage\m!layouts9{}% - \writestatus\m!layouts{forcing zero height page}% - \emptyhbox\page +\def\strc_floats_facing_flush_indeed_step#1#2#3% + {\ifnum#2<#3\relax + \advance#2\plusone + \donetrue + \writestatus + {facing} + {page: \the\scratchcounterone, location: #1, blob: \the#2, max: \the#3}% + \registertopcontent + [\scratchcounterone] + \hbox{\directboxfromcache{\currentfacingfloat:#1}{\the#2}}% \fi} -\permanent\protected\def\flushfacingfloats - {\ifnum\c_strc_floats_facing_flushed<\c_strc_floats_facing_saved - \strc_floats_facing_flush_indeed - \fi} - -\permanent\protected\def\strc_floats_facing_flush_indeed +\def\strc_floats_facing_flush_indeed#1% {\begingroup + \edef\currentfacingfloat{#1}% \glet\page_check_weird_page\page_check_weird_page_indeed % for now only when facing floats - \dorecurse\c_strc_floats_facing_saved - {\scratchdimen\getboxhtfromcache{\currentfacingfloat}{\recurselevel}\relax - \advance\scratchdimen\lineheight % this will become configurable, maybe some criterium - \normalexpanded{\adaptlayout[\the\numexpr\realpageno+\recurselevel\relax][\c!top=\the\scratchdimen]}}% - \glet\page_otr_flush_top_content\page_otr_flush_top_content_waiting % not at current page + \scratchcounterone \realpageno + \scratchcounterthree\getboxcountfromcache{\currentfacingfloat:\v!left }\relax + \scratchcounterfour \getboxcountfromcache{\currentfacingfloat:\v!right}\relax + \scratchcounterfive \zerocount + \scratchcountersix \zerocount + % find first empty spread i.e. odd (left) and even (right) empty + \ifdim\pagetotal>\zeropoint + \advance\scratchcounterone\plusone + \fi + \ifodd\scratchcounterone + \advance\scratchcounterone\plusone + \fi + \writestatus + {facing} + {page: \the\scratchcounterone, start checking}% + \doloop{% + \page_adapts_layout_preroll\scratchcounterone + \ifzeropt\d_page_adapts_preroll + % left empty + \advance\scratchcounterone\plusone + \page_adapts_layout_preroll\scratchcounterone + \ifzeropt\d_page_adapts_preroll + % right empty + \advance\scratchcounterone\minusone + \exitloop + \fi + \else + \advance\scratchcounterone\plustwo + \fi + } + \writestatus + {facing} + {page: \the\scratchcounterone, start flushing}% + \doloop{% + \ifodd\scratchcounterone + \strc_floats_facing_flush_indeed_step\v!right\scratchcountersix \scratchcounterfour + \else + \strc_floats_facing_flush_indeed_step\v!left \scratchcounterfive\scratchcounterthree + \fi + \ifnum\scratchcountersix<\scratchcounterfour + % more + \orelse\ifnum\scratchcounterfive<\scratchcounterthree + % more + \else + \exitloop + \fi + \advance\scratchcounterone\plusone + } + \disposeboxesincache{\currentfacingfloat:\v!right}% + \disposeboxesincache{\currentfacingfloat:\v!left}% + \page_check_weird_page_indeed \endgroup} -\let\page_otr_flush_top_content\relax - -\def\page_otr_flush_top_content_waiting - {\glet\page_otr_flush_top_content\page_otr_flush_top_content_inject} % but in next page - -\def\page_otr_flush_top_content_inject - {\ifnum\c_strc_floats_facing_flushed<\c_strc_floats_facing_saved - \global\advance\c_strc_floats_facing_flushed\plusone - \directboxfromcache{\currentfacingfloat}{\number\c_strc_floats_facing_flushed}% - \ifnum\c_strc_floats_facing_saved=\c_strc_floats_facing_flushed - \global\c_strc_floats_facing_saved \zerocount - \global\c_strc_floats_facing_flushed\zerocount - \resetboxesincache{\currentfacingfloat}% - \glet\page_otr_flush_top_content\relax % till we're done - \fi - \nointerlineskip - \par - \fi} +\permanent\protected\tolerant\def\flushfacingfloats[#1]% + {\processcommalist[#1]\strc_floats_facing_flush_indeed} \protected\def\strc_floats_facing_setup {\edef\currentfacingfloat{\currentfacingfloat:\m_strc_floats_state}% @@ -258,6 +335,7 @@ \doloop{% \strc_floats_facing_flush_wrap\b_strc_floats_facing_l\v!left \strc_floats_facing_flush_wrap\b_strc_floats_facing_r\v!right + \global\advance\c_strc_floats_facing_saved\plusone \ifvoid\b_strc_floats_facing_l\relax\ifvoid\b_strc_floats_facing_r\relax \exitloop \fi\fi}} @@ -286,8 +364,7 @@ \else to \textheight{\box\scratchbox\vss}% \fi - \global\advance\c_strc_floats_facing_saved\plusone - \putboxincache{\currentfacingfloat}{\number\c_strc_floats_facing_saved}\scratchbox + \putboxincache{\currentfacingfloat:#2}{+}\scratchbox \endgroup \fi} diff --git a/tex/context/base/mkxl/page-lay.mkxl b/tex/context/base/mkxl/page-lay.mkxl index b4bccd85b..a4f4666e2 100644 --- a/tex/context/base/mkxl/page-lay.mkxl +++ b/tex/context/base/mkxl/page-lay.mkxl @@ -984,6 +984,8 @@ %D \macros %D {adaptlayout} +% this will move to lua + \installcorenamespace{adaptlayout} \installcorenamespace{pageadaptations} diff --git a/tex/context/base/mkxl/spac-ver.mkxl b/tex/context/base/mkxl/spac-ver.mkxl index 413f03d36..42c424e83 100644 --- a/tex/context/base/mkxl/spac-ver.mkxl +++ b/tex/context/base/mkxl/spac-ver.mkxl @@ -1263,7 +1263,7 @@ \pushoverloadmode -\overloaded\permanent\protected\def\offinterlineskip +\overloaded\permanent\protected\def\offinterlineskip % later we will overload this with a push pop {\baselineskip-\thousandpoint \lineskip \zeropoint \lineskiplimit\maxdimen diff --git a/tex/context/base/mkxl/strc-mat.mkxl b/tex/context/base/mkxl/strc-mat.mkxl index e5eaab435..94a273f80 100644 --- a/tex/context/base/mkxl/strc-mat.mkxl +++ b/tex/context/base/mkxl/strc-mat.mkxl @@ -846,12 +846,12 @@ \global\c_strc_math_vertical\zerocount \fi \ifcase\c_strc_math_vertical - % \mathpenaltiesmode \zerocount - \clf_setmathpenalties\zerocount + % \clf_setmathpenalties\zerocount + \mathpenaltiesmode \zerocount \clf_resetmathhang \else - % \mathpenaltiesmode \plusone - \clf_setmathpenalties\plusone + % \clf_setmathpenalties\plusone + \mathpenaltiesmode \plusone \edef\p_hang{\formulaparameter\c!hang}% \ifx\p_hang\v!none \global\setfalse\c_strc_math_indent diff --git a/tex/context/base/mkxl/supp-box.lmt b/tex/context/base/mkxl/supp-box.lmt index a26cb3960..03bb54137 100644 --- a/tex/context/base/mkxl/supp-box.lmt +++ b/tex/context/base/mkxl/supp-box.lmt @@ -164,7 +164,7 @@ implement { arguments = "integer", actions = function(n) -- we just hyphenate (as we pass a hpack) .. a bit too much casting but ... - local l = languages.hyphenators.handler(tonode(checkedlist(n))) + local l = languages.hyphenators.handler(checkedlist(n)) report_hyphenation("show: %s",listtoutf(l,false,true)) end } @@ -496,6 +496,7 @@ do local values = tokens.values local dimension_value = values.dimension + local cardinal_value = values.cardinal local boxes = { } nodes.boxes = boxes @@ -511,6 +512,9 @@ do if trace then report("category %a, name %a, %s (%s)",category,name,"save",b and "content" or "empty") end + if name == "+" then + name = #cache[category] + 1 + end cache[category][name] = b or false end @@ -527,10 +531,19 @@ do return cache[category][name] and true or false end + function boxes.count(category) + return #cache[category] + end + function boxes.direct(category,name,copy) name = tonumber(name) or name local c = cache[category] local b = c[name] +-- if name == "+" then +-- b = remove(c, 1) +-- else +-- b = c[name] +-- end if not b then -- do nothing, maybe trace elseif copy then @@ -604,6 +617,11 @@ do end end + function boxes.dispose(category) + boxes.reset(category) + cache[category] = nil -- or false (for tracing) + end + implement { name = "putboxincache", public = true, @@ -662,9 +680,28 @@ do actions = boxes.reset, } + implement { + name = "disposeboxesincache", + public = true, + protected = true, + arguments = "string", + actions = boxes.dispose, + } + -- we can share this ... implement { + name = "getboxcountfromcache", + public = true, + protected = true, + usage = "value", + arguments = "string", + actions = function(category) + return cardinal_value, #cache[category] + end, + } + + implement { name = "getboxwdfromcache", public = true, protected = true, diff --git a/tex/context/base/mkxl/supp-box.mkxl b/tex/context/base/mkxl/supp-box.mkxl index 113cf7d2d..fc880852b 100644 --- a/tex/context/base/mkxl/supp-box.mkxl +++ b/tex/context/base/mkxl/supp-box.mkxl @@ -2874,6 +2874,17 @@ %D %D setsplitlisthtdp\scratchbox\struthp\strutdp +%D Handy but I'll probably forget it: +%D +%D \starttyping +%D \setbox0\hbox{!!!!!} +%D \permanent\protected\def\showboxhere{\showbox nolevels content online } +%D \showbox 0 +%D \showboxhere 0 % always on console, less clutter +%D \stoptyping + +\permanent\protected\def\showboxhere{\showbox nolevels content online } + \protect \endinput % a bit of test code: diff --git a/tex/context/base/mkxl/syst-ini.mkxl b/tex/context/base/mkxl/syst-ini.mkxl index f6f1d4044..c13e5eaef 100644 --- a/tex/context/base/mkxl/syst-ini.mkxl +++ b/tex/context/base/mkxl/syst-ini.mkxl @@ -156,7 +156,7 @@ function tex.enableprimitives() end % so we kind of protect what's there } -\permanent\let\undefined\undefined +\untraced\permanent\let\undefined\undefined \immutable\def\space{ } \immutable\def\empty{} @@ -1021,8 +1021,7 @@ \lineskip = 1pt \lineskiplimit = 0pt -%D Sometimes kerns make more sense than glue but we need to be in the -%D right mode: +%D Sometimes kerns make more sense than glue but we need to be in the right mode: \permanent\protected\def\vkern {\ifhmode\par \fi\kern} \permanent\protected\def\hkern {\ifvmode\dontleavehmode\fi\kern} @@ -1030,8 +1029,8 @@ \permanent\protected\def\vpenalty{\ifhmode\par \fi\penalty} \permanent\protected\def\hpenalty{\ifvmode\dontleavehmode\fi\penalty} -%D Again a few kind-of-extensions the core. These come from plain \TEX\ but -%D are probably not used in \CONTEXT. +%D Again a few kind-of-extensions the core. These come from plain \TEX\ but are +%D probably not used in \CONTEXT. \newskip \hideskip \hideskip = -1000pt plus 1fill \newskip \centering \centering = 0pt plus 1000pt minus 1000pt @@ -1138,12 +1137,12 @@ \glyphoptions"80 % replaces \glyphdimensionsmode=1 -%D Just in case users use this: +%D Just in case users use this (or some styles still have it): -\aliased\let\immediateassign \immediate -\aliased\let\immediateassigned\localcontrolled +\aliased\let\immediateassignment\immediate +\aliased\let\immediateassigned \localcontrolled -%D Needed: +%D Needed (maybe no longer the multiple next ones): \mutable\let\nexttoken \relax \mutable\let\next \relax diff --git a/tex/context/base/mkxl/syst-lua.lmt b/tex/context/base/mkxl/syst-lua.lmt index 44d2fd2e9..0eef7afd0 100644 --- a/tex/context/base/mkxl/syst-lua.lmt +++ b/tex/context/base/mkxl/syst-lua.lmt @@ -342,10 +342,10 @@ do local l = 0 implement { - name = "openin", - public = true, - usage = "value", - actions = function() + name = "openin", + public = true, + usage = "value", + actions = function() local n = scaninteger() scankeyword("=") local s = scanstring(true) @@ -365,10 +365,10 @@ do } implement { - name = "closein", - public = true, - usage = "value", - actions = function() + name = "closein", + public = true, + usage = "value", + actions = function() local n = scaninteger() local c = channels[n] if c then @@ -388,10 +388,10 @@ do end interfaces.implement { - name = "read", - public = true, - usage = "value", - actions = function(prefix) + name = "read", + public = true, + usage = "value", + actions = function(prefix) local n = scaninteger() local c = channels[n] if scankeyword("line") and c then diff --git a/tex/context/base/mkxl/toks-aux.lmt b/tex/context/base/mkxl/toks-aux.lmt index 86b796b1e..1b640b8ad 100644 --- a/tex/context/base/mkxl/toks-aux.lmt +++ b/tex/context/base/mkxl/toks-aux.lmt @@ -5,9 +5,9 @@ if not modules then modules = { } end modules ['toks-aux'] = { license = "see context related readme files" } -local type, tostring = type, tostring +local type, tostring, next = type, tostring, next local max = math.max -local formatters, gsub, char = string.formatters, string.gsub, string.char +local formatters, gsub, char, gmatch = string.formatters, string.gsub, string.char, string.gmatch local concat = table.concat -- todo : locals from scanners @@ -130,54 +130,53 @@ interfaces.implement { -- For the moment here, will move to initex only (also see node-ini.lua); we need -- to actually store these. -local groupcodes = { } -local glyphoptioncodes = { } -local discoptioncodes = { } -local mathoptioncodes = { } -local hyphenationcodes = { } -local frozenparcodes = { } -local flagcodes = { } -local normalizecodes = { } ------ parcontextcodes = { } ------ parbegincodes = { } - -for k, v in next, tex.getgroupvalues() do groupcodes[k] = gsub(v,"[_ ]","") end -for k, v in next, tex.gethyphenationvalues() do hyphenationcodes[k] = gsub(v,"[_ ]","") end -for k, v in next, tex.getglyphoptionvalues() do glyphoptioncodes[k] = gsub(v,"[_ ]","") end -for k, v in next, tex.getdiscoptionvalues() do discoptioncodes[k] = gsub(v,"[_ ]","") end -for k, v in next, tex.getmathoptionvalues() do mathoptioncodes[k] = gsub(v,"[_ ]","") end -for k, v in next, tex.getfrozenparvalues() do frozenparcodes[k] = gsub(v,"[_ ]","") end -for k, v in next, tex.getflagvalues() do flagcodes[k] = gsub(v,"[_ ]","") end -for k, v in next, tex.getnormalizevalues() do normalizecodes[k] = gsub(v,"[_ ]","") end - -if environment.initex then - - local texintegerdef = tex.integerdef - - for k, v in next, groupcodes do texintegerdef(v .. "groupcode", k,"immutable") end - for k, v in next, glyphoptioncodes do texintegerdef(v .. "code", k,"immutable") end - for k, v in next, discoptioncodes do texintegerdef(v .. "code", k,"immutable") end - for k, v in next, hyphenationcodes do texintegerdef(v .. "hyphenationmodecode",k,"immutable") end - for k, v in next, frozenparcodes do texintegerdef("frozen" .. v .. "code", k,"immutable") end - for k, v in next, flagcodes do texintegerdef(v .. "flagcode", k,"immutable") end - for k, v in next, normalizecodes do texintegerdef(v .. "code", k,"immutable") end - +local function getthem(getter,pre,post) + local codes = { } + if getter then + local texintegerdef = tex.integerdef + for k, v in next, getter() do + codes[k] = gsub(v,"[_ ]","") + end + if post ~= "" and environment.initex then + for k, v in next, codes do + texintegerdef(pre .. v .. post,k,"immutable") + end + end + end + return utilities.storage.allocate(table.swapped(codes,codes)) end -groupcodes = utilities.storage.allocate(table.swapped(groupcodes, groupcodes)) -glyphoptioncodes = utilities.storage.allocate(table.swapped(glyphoptioncodes,glyphoptioncodes)) -discoptioncodes = utilities.storage.allocate(table.swapped(discoptioncodes, discoptioncodes)) -mathoptioncodes = utilities.storage.allocate(table.swapped(mathoptioncodes, mathoptioncodes)) -hyphenationcodes = utilities.storage.allocate(table.swapped(hyphenationcodes,hyphenationcodes)) -frozenparcodes = utilities.storage.allocate(table.swapped(frozenparcodes, frozenparcodes)) -flagcodes = utilities.storage.allocate(table.swapped(flagcodes, flagcodes)) -normalizecodes = utilities.storage.allocate(table.swapped(normalizecodes, normalizecodes)) +tex.groupcodes = getthem(tex.getgroupvalues, "", "groupcode") +tex.glyphoptioncodes = getthem(tex.getglyphoptionvalues, "", "code") +tex.discoptioncodes = getthem(tex.getdiscoptionvalues, "", "code") +tex.mathoptioncodes = getthem(tex.getmathoptionvalues, "", "") +tex.mathcontrolcodes = getthem(tex.getmathcontrolvalues, "", "mathcontrolcode") +tex.mathflattencodes = getthem(tex.getmathflattenvalues, "", "flattencode") +tex.hyphenationcodes = getthem(tex.gethyphenationvalues, "", "hyphenationmodecode") +tex.frozenparcodes = getthem(tex.getfrozenparvalues, "frozen", "code") +tex.flagcodes = getthem(tex.getflagvalues, "", "flagcode" ) +tex.normalizecodes = getthem(tex.getnormalizevalues, "", "code") -tex.groupcodes = groupcodes -tex.glyphoptioncodes = glyphoptioncodes -tex.discoptioncodes = discoptioncodes -tex.mathoptioncodes = mathoptioncodes -tex.hyphenationcodes = hyphenationcodes -tex.frozenparcodes = frozenparcodes -tex.flagcodes = flagcodes -tex.normalizecodes = normalizecodes +function tex.stringtocodesbitmap(str,codes) + local bitmap = 0 + if codes then + if not str or str == "" then + -- zero + elseif str == "all" then + for k in next, codes do + if type(k) == "number" then + bitmap = bitmap | k + end + end + else + str = gsub(str,"[_ ]","") + for s in gmatch(str,"[^%,]+") do + local b = codes[s] + if b then + bitmap = bitmap | b + end + end + end + end + return bitmap +end diff --git a/tex/context/base/mkxl/trac-inf.lmt b/tex/context/base/mkxl/trac-inf.lmt index a2366b611..feef3714f 100644 --- a/tex/context/base/mkxl/trac-inf.lmt +++ b/tex/context/base/mkxl/trac-inf.lmt @@ -265,8 +265,9 @@ status.iocodes = setmetatableindex(tex.getiovalues(), function() return "unknown local report = logs.reporter("system") local list = { - "string", "pool", "hash", "lookup", "node", "token", "extra", "sparse", "buffer", - "input", "file", "nest", "parameter", "save", "font", "language", "mark", "insert", + "string", "pool", "hash", "lookup", "node", "token", + "buffer", "input", "file", "nest", "parameter", "save", "font", "language", "mark", "insert", + -- "extra", "sparse", } local function show(data,fields) diff --git a/tex/context/base/mkxl/trac-vis.lmt b/tex/context/base/mkxl/trac-vis.lmt index d278a40b0..fc136539e 100644 --- a/tex/context/base/mkxl/trac-vis.lmt +++ b/tex/context/base/mkxl/trac-vis.lmt @@ -630,12 +630,13 @@ local dir, par do setattr(info,a_layer,l_dir) d_cache[what] = info end + head, current = insertnodeafter(head,current,copylist(info)) return head, current end dir = function(head,current) local what = getsubtype(current) - if what == cancelcode then + if what == cancel_code then what = "cancel" elseif getdirection(current) == r2l_code then what = "r2l" @@ -650,6 +651,7 @@ local dir, par do setattr(info,a_layer,l_dir) d_cache[what] = info end + head, current = insertnodeafter(head,current,copylist(info)) return head, current end diff --git a/tex/context/base/mkxl/typo-brk.mkxl b/tex/context/base/mkxl/typo-brk.mkxl index 47e5da886..0988e3a6b 100644 --- a/tex/context/base/mkxl/typo-brk.mkxl +++ b/tex/context/base/mkxl/typo-brk.mkxl @@ -53,11 +53,11 @@ \endgroup} \permanent\protected\def\setbreakpoints[#1]% - {\exhyphenchar\minusone % we use a different order than base tex, so we really need this + {%\exhyphenchar\minusone % we now use collapsing so ... \clf_setbreakpoints{#1}} \permanent\protected\def\resetbreakpoints - {\exhyphenchar\hyphenasciicode % 2020.03.05 + {%\exhyphenchar\hyphenasciicode % 2020.03.05 / we now use collapsing so ... \c_attr_breakpoint\attributeunsetvalue} \definebreakpoints[compound] diff --git a/tex/context/base/mkxl/typo-duc.lmt b/tex/context/base/mkxl/typo-duc.lmt index 87190a1ab..00f761c19 100644 --- a/tex/context/base/mkxl/typo-duc.lmt +++ b/tex/context/base/mkxl/typo-duc.lmt @@ -958,30 +958,46 @@ local function apply_to_list(list,size,head,pardir) setdirection(current,pardir) -- is this really needed? elseif id == glue_code then -- Maybe I should also fix dua and dub but on the other hand ... why? - if enddir and getsubtype(current) == parfillskip_code then - -- insert the last enddir before \parfillskip glue - local c = current - local p = getprev(c) - if p and getid(p) == glue_code and getsubtype(p) == parfillleftskip_code then - c = p - p = getprev(c) - end - if p and getid(p) == penalty_code then -- linepenalty - c = p - end - -- there is always a par nodes so head will stay - head = insertnodebefore(head,c,new_direction(enddir,true)) +-- if enddir and getsubtype(current) == parfillskip_code then +-- -- insert the last enddir before \parfillskip glue +-- local c = current +-- local p = getprev(c) +-- if p and getid(p) == glue_code and getsubtype(p) == parfillleftskip_code then +-- c = p +-- p = getprev(c) +-- end +-- while p and getid(p) == glue_code do +-- c = p +-- p = getprev(c) +-- end +-- if p and getid(p) == penalty_code then -- linepenalty +-- c = p +-- end +-- -- there is always a par nodes so head will stay +-- local d = new_direction(enddir,true) +-- setattrlist(d,current) +-- head = insertnodebefore(head,c,d) +-- enddir = false +-- end + if enddir then + local d = new_direction(enddir,true) + setattrlist(d,current) + head = insertnodebefore(head,current,d) enddir = false end elseif begindir then if id == par_code and startofpar(current) then -- par should always be the 1st node - head, current = insertnodeafter(head,current,new_direction(begindir)) + local d = new_direction(begindir) + setattrlist(d,current) + head, current = insertnodeafter(head,current,d) begindir = nil end end if begindir then - head = insertnodebefore(head,current,new_direction(begindir)) + local d = new_direction(begindir) + setattrlist(d,current) + head = insertnodebefore(head,current,d) end local skip = entry.skip if skip and skip > 0 then @@ -996,7 +1012,9 @@ local function apply_to_list(list,size,head,pardir) end end if enddir then - head, current = insertnodeafter(head,current,new_direction(enddir,true)) + local d = new_direction(enddir,true) + setattrlist(d,current) + head, current = insertnodeafter(head,current,d) end if not entry.remove then current = getnext(current) diff --git a/tex/context/base/mkxl/util-fil.lmt b/tex/context/base/mkxl/util-fil.lmt index a3631d043..86200ebe5 100644 --- a/tex/context/base/mkxl/util-fil.lmt +++ b/tex/context/base/mkxl/util-fil.lmt @@ -116,6 +116,9 @@ files.readbytetable = fio.readbytetable files.readcardinaltable = fio.readcardinaltable files.readintegertable = fio.readintegertable +files.readcstring = fio.readcstring +files.readcline = fio.readcline + function files.readchar(f) return f:read(1) end diff --git a/tex/context/base/mkxl/util-sac.lmt b/tex/context/base/mkxl/util-sac.lmt index 60ecb0e33..e0a9f77de 100644 --- a/tex/context/base/mkxl/util-sac.lmt +++ b/tex/context/base/mkxl/util-sac.lmt @@ -126,10 +126,10 @@ end function streams.skipshort(f,n) f[2] = f[2] + 2*(n or 1) end function streams.skiplong (f,n) f[2] = f[2] + 4*(n or 1) end -local readcardinal1 = sio.readcardinal1 -local readcardinal2 = sio.readcardinal2 -local readcardinal3 = sio.readcardinal3 -local readcardinal4 = sio.readcardinal4 +local readcardinal1 = sio.readcardinal1 +local readcardinal2 = sio.readcardinal2 +local readcardinal3 = sio.readcardinal3 +local readcardinal4 = sio.readcardinal4 function streams.readcardinal1(f) local i = f[2] f[2] = i + 1 return readcardinal1(f[1],i) end function streams.readcardinal2(f) local i = f[2] f[2] = i + 2 return readcardinal2(f[1],i) end @@ -146,34 +146,49 @@ function streams.readcardinal2le(f) local i = f[2] f[2] = i + 2 return readcardi function streams.readcardinal3le(f) local i = f[2] f[2] = i + 3 return readcardinal3le(f[1],i) end function streams.readcardinal4le(f) local i = f[2] f[2] = i + 4 return readcardinal4le(f[1],i) end -local readinteger1 = sio.readinteger1 -local readinteger2 = sio.readinteger2 -local readinteger3 = sio.readinteger3 -local readinteger4 = sio.readinteger4 +local readinteger1 = sio.readinteger1 +local readinteger2 = sio.readinteger2 +local readinteger3 = sio.readinteger3 +local readinteger4 = sio.readinteger4 function streams.readinteger1(f) local i = f[2] f[2] = i + 1 return readinteger1(f[1],i) end function streams.readinteger2(f) local i = f[2] f[2] = i + 2 return readinteger2(f[1],i) end function streams.readinteger3(f) local i = f[2] f[2] = i + 3 return readinteger3(f[1],i) end function streams.readinteger4(f) local i = f[2] f[2] = i + 4 return readinteger4(f[1],i) end -local readinteger1le = sio.readinteger1le -local readinteger2le = sio.readinteger2le -local readinteger3le = sio.readinteger3le -local readinteger4le = sio.readinteger4le +local readinteger1le = sio.readinteger1le +local readinteger2le = sio.readinteger2le +local readinteger3le = sio.readinteger3le +local readinteger4le = sio.readinteger4le function streams.readinteger1le(f) local i = f[2] f[2] = i + 1 return readinteger1le(f[1],i) end function streams.readinteger2le(f) local i = f[2] f[2] = i + 2 return readinteger2le(f[1],i) end function streams.readinteger3le(f) local i = f[2] f[2] = i + 3 return readinteger3le(f[1],i) end function streams.readinteger4le(f) local i = f[2] f[2] = i + 4 return readinteger4le(f[1],i) end -local readfixed2 = sio.readfixed2 -local readfixed4 = sio.readfixed4 -local read2dot14 = sio.read2dot14 +local readfixed2 = sio.readfixed2 +local readfixed4 = sio.readfixed4 +local read2dot14 = sio.read2dot14 function streams.readfixed2(f) local i = f[2] f[2] = i + 2 return readfixed2(f[1],i) end function streams.readfixed4(f) local i = f[2] f[2] = i + 4 return readfixed4(f[1],i) end function streams.read2dot14(f) local i = f[2] f[2] = i + 2 return read2dot14(f[1],i) end +local readcstring = sio.readcstring +local readcline = sio.readcline + +function streams.readcstring(f) + local s, p = readcstring(f[1],f[2]) + f[2] = p + return s +end + +function streams.readcline(f,n) + local s, p = readcline(f[1],f[2]) + f[2] = p + return s +end + local readbytes = sio.readbytes local readbytetable = sio.readbytetable @@ -249,10 +264,10 @@ if files then function io.newreader(str,method) local f, m if method == "string" then - f = openstring(str) + f = openstring(str,true) m = streams elseif method == "stream" then - f = openstream(str) + f = openstream(str,true) m = streams else f = openfile(str,"rb") @@ -283,3 +298,13 @@ if files then end end + +streams.tocardinal1 = sio.tocardinal1 +streams.tocardinal2 = sio.tocardinal2 +streams.tocardinal3 = sio.tocardinal3 +streams.tocardinal4 = sio.tocardinal4 + +streams.tocardinal1le = sio.tocardinal1le +streams.tocardinal2le = sio.tocardinal2le +streams.tocardinal3le = sio.tocardinal3le +streams.tocardinal4le = sio.tocardinal4le diff --git a/tex/context/fonts/mkiv/type-imp-newcomputermodern.mkiv b/tex/context/fonts/mkiv/type-imp-newcomputermodern.mkiv index b16d01d3a..6ffb38161 100644 --- a/tex/context/fonts/mkiv/type-imp-newcomputermodern.mkiv +++ b/tex/context/fonts/mkiv/type-imp-newcomputermodern.mkiv @@ -79,8 +79,8 @@ \starttypescript [\s!math][newcomputermodern-book] [\s!name] % \loadfontgoodies[newcomputermodern-math] ,\s!goodies=newcomputermodern-math - \definefontsynonym[\s!MathRoman] [\s!file:newcmmath-book][\s!features={\s!math\mathsizesuffix,mathextra}] - \definefontsynonym[\s!MathRomanBold][\s!file:newcmmath-book][\s!features={\s!math\mathsizesuffix,newcomputermodern-math-bold,mathextra}] + \definefontsynonym[\s!MathRoman] [\s!file:newcmmath-book][\s!features={\s!math\mathsizesuffix,newcm-mathextra,mathextra}] + \definefontsynonym[\s!MathRomanBold][\s!file:newcmmath-book][\s!features={\s!math\mathsizesuffix,newcm-mathextra,newcomputermodern-math-bold,mathextra}] \stoptypescript \starttypescript[newcomputermodern,newcomputermodern-book] diff --git a/tex/context/modules/mkiv/x-mathml.lua b/tex/context/modules/mkiv/x-mathml.lua index c8c773475..9dd2c9851 100644 --- a/tex/context/modules/mkiv/x-mathml.lua +++ b/tex/context/modules/mkiv/x-mathml.lua @@ -872,7 +872,7 @@ function xml.is_element(e,name) return type(e) == "table" and (not name or e.tg == name) end -function mathml.cpolar_a(root) +function mathml.cpolar(root) root = getid(root) local dt = root.dt ctx_mathopnolimits("Polar") diff --git a/tex/context/modules/mkiv/x-mathml.mkiv b/tex/context/modules/mkiv/x-mathml.mkiv index 183125bec..a8b121053 100644 --- a/tex/context/modules/mkiv/x-mathml.mkiv +++ b/tex/context/modules/mkiv/x-mathml.mkiv @@ -670,7 +670,7 @@ \stopxmlsetups \startxmlsetups mml:cn:polar:a - \ctxmodulemathml{cpolar_a("#1")} + \ctxmodulemathml{cpolar("#1")} \stopxmlsetups \startxmlsetups mml:cn:polar:b diff --git a/tex/context/modules/mkxl/x-mathml.lmt b/tex/context/modules/mkxl/x-mathml.lmt index ba05c002e..5d4653268 100644 --- a/tex/context/modules/mkxl/x-mathml.lmt +++ b/tex/context/modules/mkxl/x-mathml.lmt @@ -856,7 +856,7 @@ function xml.is_element(e,name) return type(e) == "table" and (not name or e.tg == name) end -function mathml.cpolar_a(root) +function mathml.cpolar(root) root = getid(root) local dt = root.dt ctx_mathopnolimits("Polar") @@ -905,6 +905,4 @@ install("mathml_mcolumn", mathml.mcolumn) install("mathml_extensible", mathml.extensible) install("mathml_csymbol", mathml.csymbol) -install("mathml_cpolar_a", mathml.cpolar_a) - -install("mathml_cpolar_extensible", mathml.cpolar_extensible) +install("mathml_cpolar", mathml.cpolar) diff --git a/tex/context/modules/mkxl/x-mathml.mkxl b/tex/context/modules/mkxl/x-mathml.mkxl index fbfc17883..11da32126 100644 --- a/tex/context/modules/mkxl/x-mathml.mkxl +++ b/tex/context/modules/mkxl/x-mathml.mkxl @@ -604,7 +604,7 @@ \stopxmlsetups \startxmlsetups mml:cn:polar:a - \mathml_cpolar_a{#1} + \mathml_cpolar{#1} \stopxmlsetups \startxmlsetups mml:cn:polar:b @@ -2358,6 +2358,7 @@ \novrule\s!depth\zeropoint\s!height\scratchheight\s!width\zeropoint \fi \ifdim\scratchwidth=\zeropoint + % maybe we need to do it anyway \orelse\ifx\MMLmspaceoption\v!test \hbox to \scratchwidth{\showstruts\strut\hss\lower2\exheight\hbox{\infofont\xmlattdef{#1}{width}}\hss\strut} \else diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 4c5bc8b00..36893a527 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 2021-06-14 17:06 +-- merge date : 2021-06-24 18:50 do -- begin closure to overcome local limits and interference @@ -4202,20 +4202,20 @@ function files.readinteger4le(f) end end function files.readfixed2(f) - local a,b=byte(f:read(2),1,2) - if a>=0x80 then - tonumber((a-0x100).."."..b) - else - tonumber((a ).."."..b) + local n1,n2=byte(f:read(2),1,2) + if n1>=0x80 then + n1=n1-0x100 end + return n1+n2/0xFF end function files.readfixed4(f) local a,b,c,d=byte(f:read(4),1,4) - if a>=0x80 then - tonumber((0x100*a+b-0x10000).."."..(0x100*c+d)) - else - tonumber((0x100*a+b ).."."..(0x100*c+d)) + local n1=0x100*a+b + local n2=0x100*c+d + if n1>=0x8000 then + n1=n1-0x10000 end + return n1+n2/0xFFFF end if bit32 then local extract=bit32.extract @@ -11762,7 +11762,7 @@ readers.post=function(f,fontdata,specification) local version=readulong(f) fontdata.postscript={ version=version, - italicangle=round(1000*readfixed(f))/1000, + italicangle=readfixed(f), underlineposition=readfword(f), underlinethickness=readfword(f), monospaced=readulong(f), @@ -13339,7 +13339,8 @@ do top=0 end local p_dictionary=( - p_byte+p_positive+p_negative+p_short+p_long+p_nibbles+p_single+p_double+p_unsupported + p_byte+p_positive+p_negative+p_short+p_long+p_nibbles+p_single+p_double ++p_unsupported )^1 parsedictionaries=function(data,dictionaries,version) stack={} @@ -14365,12 +14366,12 @@ do stack[top]=-t*256+64148-tab[i+1] i=i+2 else - local n=0x100*tab[i+1]+tab[i+2] - if n>=0x8000 then - stack[top]=n-0x10000+(0x100*tab[i+3]+tab[i+4])/0xFFFF - else - stack[top]=n+(0x100*tab[i+3]+tab[i+4])/0xFFFF + local n1=0x100*tab[i+1]+tab[i+2] + local n2=0x100*tab[i+3]+tab[i+4] + if n1>=0x8000 then + n1=n1-0x10000 end + stack[top]=n1+n2/0xFFFF i=i+5 end elseif t==28 then @@ -21063,7 +21064,7 @@ local function copytotfm(data,cache_id) local properties=derivetable(data.properties) local descriptions=derivetable(data.descriptions) local goodies=derivetable(data.goodies) - local characters={} + local characters={} local parameters={} local mathparameters={} local resources=data.resources @@ -30398,6 +30399,7 @@ local function validspecification(specification,name) else dataset={ { data=specification.data } } specification.data=nil + specification.coverage=dataset specification.dataset=dataset end local first=dataset[1] @@ -30697,7 +30699,28 @@ local function addfeature(data,feature,specifications) return coverage end local prepare_single=prepare_pair - local function prepare_chain(list,featuretype,sublookups) + local function hassteps(lookups) + if lookups then + for i=1,#lookups do + local l=lookups[i] + if l then + for j=1,#l do + local l=l[j] + if l then + local n=l.nofsteps + if not n then + return true + elseif n>0 then + return true + end + end + end + end + end + end + return false + end + local function prepare_chain(list,featuretype,sublookups,nocheck) local rules=list.rules local coverage={} if rules then @@ -30733,6 +30756,7 @@ local function addfeature(data,feature,specifications) local lookups=rule.lookups or false local subtype=nil if lookups and sublookups then + local l={} for k,v in sortedhash(lookups) do local t=type(v) if t=="table" then @@ -30742,55 +30766,63 @@ local function addfeature(data,feature,specifications) v[i]={ vi } end end + l[k]=v elseif t=="number" then local lookup=sublookups[v] if lookup then - lookups[k]={ lookup } + l[k]={ lookup } if not subtype then subtype=lookup.type end elseif v==0 then - lookups[k]={ { type="gsub_remove" } } + l[k]={ { type="gsub_remove",nosteps=true } } else - lookups[k]=false + l[k]=false end else - lookups[k]=false + l[k]=false end end + if nocheck then + rule.lookups=l + end + lookups=l end if nofsequences>0 then - local hashed={} - for i=1,nofsequences do - local t={} - local s=sequence[i] - for i=1,#s do - local u=tounicode(s[i]) - if u then - t[u]=true + if hassteps(lookups) then + local hashed={} + for i=1,nofsequences do + local t={} + local s=sequence[i] + for i=1,#s do + local u=tounicode(s[i]) + if u then + t[u]=true + end + end + hashed[i]=t + end + sequence=hashed + rulesize=rulesize+1 + rulehash[rulesize]={ + nofrules, + lookuptype, + sequence, + start, + stop, + lookups, + replacements, + subtype, + } + for unic in sortedhash(sequence[start]) do + local cu=coverage[unic] + if not cu then + coverage[unic]=rulehash end end - hashed[i]=t - end - sequence=hashed - rulesize=rulesize+1 - rulehash[rulesize]={ - nofrules, - lookuptype, - sequence, - start, - stop, - lookups, - replacements, - subtype, - } - for unic in sortedhash(sequence[start]) do - local cu=coverage[unic] - if not cu then - coverage[unic]=rulehash - end + sequence.n=nofsequences + else end - sequence.n=nofsequences end end rulehash.n=rulesize @@ -30877,126 +30909,148 @@ local function addfeature(data,feature,specifications) end local askedfeatures=specification.features or everywhere local askedsteps=specification.steps or specification.subtables or { specification.data } or {} - local featuretype=normalized[specification.type or "substitution"] or "substitution" + local featuretype=specification.type or "substitution" + local featureaction=false local featureflags=specification.flags or noflags local nocheck=specification.nocheck + local mapping=specification.mapping local featureorder=specification.order or { feature } local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0 local nofsteps=0 local steps={} local sublookups=specification.lookups local category=nil + local steptype=nil + local sequence=nil + if fonts.handlers.otf.handlers[featuretype] then + featureaction=true + else + featuretype=normalized[specification.type or "substitution"] or "substitution" + end checkflags(specification,resources) - if sublookups then - local s={} - for i=1,#sublookups do - local specification=sublookups[i] - local askedsteps=specification.steps or specification.subtables or { specification.data } or {} - local featuretype=normalized[specification.type or "substitution"] or "substitution" - local featureflags=specification.flags or noflags - local nofsteps=0 - local steps={} - for i=1,#askedsteps do - local list=askedsteps[i] - local coverage=nil - local format=nil - if featuretype=="substitution" then - coverage=prepare_substitution(list,featuretype,nocheck) - elseif featuretype=="ligature" then - coverage=prepare_ligature(list,featuretype,nocheck) - elseif featuretype=="alternate" then - coverage=prepare_alternate(list,featuretype,nocheck) - elseif featuretype=="multiple" then - coverage=prepare_multiple(list,featuretype,nocheck) - elseif featuretype=="kern" or featuretype=="move" then - format=featuretype - coverage=prepare_kern(list,featuretype) - elseif featuretype=="pair" then - format="pair" - coverage=prepare_pair(list,featuretype) - elseif featuretype=="single" then - format="single" - coverage=prepare_single(list,featuretype) - end - if coverage and next(coverage) then - nofsteps=nofsteps+1 - steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) + for k,v in next,askedfeatures do + if v[1] then + askedfeatures[k]=tohash(v) + end + end + if featureflags[1] then featureflags[1]="mark" end + if featureflags[2] then featureflags[2]="ligature" end + if featureflags[3] then featureflags[3]="base" end + if featureaction then + category="gsub" + sequence={ + features={ [feature]=askedfeatures }, + flags=featureflags, + name=feature, + order=featureorder, + type=featuretype, + nofsteps=0, + } + else + if sublookups then + local s={} + for i=1,#sublookups do + local specification=sublookups[i] + local askedsteps=specification.steps or specification.subtables or { specification.data } or {} + local featuretype=normalized[specification.type or "substitution"] or "substitution" + local featureflags=specification.flags or noflags + local nofsteps=0 + local steps={} + for i=1,#askedsteps do + local list=askedsteps[i] + local coverage=nil + local format=nil + if featuretype=="substitution" then + coverage=prepare_substitution(list,featuretype,nocheck) + elseif featuretype=="ligature" then + coverage=prepare_ligature(list,featuretype,nocheck) + elseif featuretype=="alternate" then + coverage=prepare_alternate(list,featuretype,nocheck) + elseif featuretype=="multiple" then + coverage=prepare_multiple(list,featuretype,nocheck) + elseif featuretype=="kern" or featuretype=="move" then + format=featuretype + coverage=prepare_kern(list,featuretype) + elseif featuretype=="pair" then + format="pair" + coverage=prepare_pair(list,featuretype) + elseif featuretype=="single" then + format="single" + coverage=prepare_single(list,featuretype) + end + if coverage and next(coverage) then + nofsteps=nofsteps+1 + steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) + end end + checkmerge(specification) + checksteps(specification) + s[i]={ + [stepkey]=steps, + nofsteps=nofsteps, + flags=featureflags, + type=types[featuretype], + } + end + sublookups=s + end + for i=1,#askedsteps do + local list=askedsteps[i] + local coverage=nil + local format=nil + if featuretype=="substitution" then + category="gsub" + coverage=(mapping and list) or prepare_substitution(list,featuretype,nocheck) + elseif featuretype=="ligature" then + category="gsub" + coverage=prepare_ligature(list,featuretype,nocheck) + elseif featuretype=="alternate" then + category="gsub" + coverage=prepare_alternate(list,featuretype,nocheck) + elseif featuretype=="multiple" then + category="gsub" + coverage=prepare_multiple(list,featuretype,nocheck) + elseif featuretype=="kern" or featuretype=="move" then + category="gpos" + format=featuretype + coverage=prepare_kern(list,featuretype) + elseif featuretype=="pair" then + category="gpos" + format="pair" + coverage=prepare_pair(list,featuretype) + elseif featuretype=="single" then + category="gpos" + format="single" + coverage=prepare_single(list,featuretype) + elseif featuretype=="chainsubstitution" then + category="gsub" + coverage=prepare_chain(list,featuretype,sublookups,nocheck) + elseif featuretype=="chainposition" then + category="gpos" + coverage=prepare_chain(list,featuretype,sublookups,nocheck) + else + report_otf("not registering feature %a, unknown category",feature) + return end - checkmerge(specification) - checksteps(specification) - s[i]={ + if coverage and next(coverage) then + nofsteps=nofsteps+1 + steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) + end + end + if nofsteps>0 then + sequence={ + chain=featurechain, + features={ [feature]=askedfeatures }, + flags=featureflags, + name=feature, + order=featureorder, [stepkey]=steps, nofsteps=nofsteps, - flags=featureflags, type=types[featuretype], } end - sublookups=s - end - for i=1,#askedsteps do - local list=askedsteps[i] - local coverage=nil - local format=nil - if featuretype=="substitution" then - category="gsub" - coverage=prepare_substitution(list,featuretype,nocheck) - elseif featuretype=="ligature" then - category="gsub" - coverage=prepare_ligature(list,featuretype,nocheck) - elseif featuretype=="alternate" then - category="gsub" - coverage=prepare_alternate(list,featuretype,nocheck) - elseif featuretype=="multiple" then - category="gsub" - coverage=prepare_multiple(list,featuretype,nocheck) - elseif featuretype=="kern" or featuretype=="move" then - category="gpos" - format=featuretype - coverage=prepare_kern(list,featuretype) - elseif featuretype=="pair" then - category="gpos" - format="pair" - coverage=prepare_pair(list,featuretype) - elseif featuretype=="single" then - category="gpos" - format="single" - coverage=prepare_single(list,featuretype) - elseif featuretype=="chainsubstitution" then - category="gsub" - coverage=prepare_chain(list,featuretype,sublookups) - elseif featuretype=="chainposition" then - category="gpos" - coverage=prepare_chain(list,featuretype,sublookups) - else - report_otf("not registering feature %a, unknown category",feature) - return - end - if coverage and next(coverage) then - nofsteps=nofsteps+1 - steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources) - end end - if nofsteps>0 then - for k,v in next,askedfeatures do - if v[1] then - askedfeatures[k]=tohash(v) - end - end - if featureflags[1] then featureflags[1]="mark" end - if featureflags[2] then featureflags[2]="ligature" end - if featureflags[3] then featureflags[3]="base" end - local steptype=types[featuretype] - local sequence={ - chain=featurechain, - features={ [feature]=askedfeatures }, - flags=featureflags, - name=feature, - order=featureorder, - [stepkey]=steps, - nofsteps=nofsteps, - type=steptype, - } + if sequence then checkflags(sequence,resources) checkmerge(sequence) checksteps(sequence) @@ -31111,7 +31165,8 @@ local flushnode=nuts.flushnode local copyinjection=nodes.injections.copy local unsetvalue=attributes.unsetvalue local fontdata=fonts.hashes.identifiers -local a_syllabe=attributes.private('syllabe') +local a_syllabe="syllable" +local a_reordered="reordered" local dotted_circle=0x25CC local c_nbsp=0x00A0 local c_zwnj=0x200C @@ -32187,7 +32242,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces) if getchar(base)==c_nbsp then nbspaces=nbspaces-1 if base==stop then - stop=getprev(stop) + stop=getprev(stop) end head=remove_node(head,base) flushnode(base) @@ -32304,7 +32359,7 @@ function handlers.devanagari_reorder_reph(head,start) start=startnext startattr=getprop(start,a_syllabe) break - elseif not c and (vowel_modifier[char] or stress_tone_mark[char] ) then + elseif not c and (vowel_modifier[char] or stress_tone_mark[char]) then c=current end current=getnext(current) @@ -32372,9 +32427,8 @@ function handlers.devanagari_reorder_reph(head,start) end return head,start,true end -local reordered_pre_base_reordering_consonants={} function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) - if reordered_pre_base_reordering_consonants[start] then + if getprop(start,a_reordered) then return head,start,true end local current=start @@ -32396,7 +32450,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) head=remove_node(head,start) setlink(start,next) setlink(current,start) - reordered_pre_base_reordering_consonants[start]=true + setprop(start,"reordered",true) start=startnext return head,start,true end @@ -32419,7 +32473,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start) setlink(getprev(current),start) setlink(start,current) end - reordered_pre_base_reordering_consonants[start]=true + setprop(start,"reordered",true) start=startnext break end @@ -32930,20 +32984,20 @@ local function analyze_next_chars_one(c,font,variant) local already_below_mark local already_post_mark while dependent_vowel[v] do - local vowels=twopart_mark[v] or { v } - for k,v in next,vowels do - if pre_mark[v] and not already_pre_mark then - already_pre_mark=true - elseif above_mark[v] and not already_above_mark then - already_above_mark=true - elseif below_mark[v] and not already_below_mark then - already_below_mark=true - elseif post_mark[v] and not already_post_mark then - already_post_mark=true - else - return c - end - end + local vowels=twopart_mark[v] or { v } + for k,v in next,vowels do + if pre_mark[v] and not already_pre_mark then + already_pre_mark=true + elseif above_mark[v] and not already_above_mark then + already_above_mark=true + elseif below_mark[v] and not already_below_mark then + already_below_mark=true + elseif post_mark[v] and not already_post_mark then + already_post_mark=true + else + return c + end + end c=getnext(c) n=getnext(c) if not n then @@ -33113,21 +33167,21 @@ local function analyze_next_chars_two(c,font) local already_above_mark local already_below_mark local already_post_mark - while dependent_vowel[v] do - local vowels=twopart_mark[v] or { v } - for k,v in next,vowels do - if pre_mark[v] and not already_pre_mark then - already_pre_mark=true - elseif above_mark[v] and not already_above_mark then - already_above_mark=true - elseif below_mark[v] and not already_below_mark then - already_below_mark=true - elseif post_mark[v] and not already_post_mark then - already_post_mark=true - else - return c - end - end + while dependent_vowel[v] do + local vowels=twopart_mark[v] or { v } + for k,v in next,vowels do + if pre_mark[v] and not already_pre_mark then + already_pre_mark=true + elseif above_mark[v] and not already_above_mark then + already_above_mark=true + elseif below_mark[v] and not already_below_mark then + already_below_mark=true + elseif post_mark[v] and not already_post_mark then + already_post_mark=true + else + return c + end + end c=n n=getnext(c) if not n then @@ -33383,15 +33437,15 @@ local function method_one(head,font,attr) while current do local char=ischar(current,font) if char then - if n==0 and not getstate(current) then - setstate(current,s_init) - end - n=n+1 - else - n=0 - end - current=getnext(current) - end + if n==0 and not getstate(current) then + setstate(current,s_init) + end + n=n+1 + else + n=0 + end + current=getnext(current) + end return head,done end local function method_two(head,font,attr) @@ -33478,15 +33532,15 @@ local function method_two(head,font,attr) while current do local char=ischar(current,font) if char then - if n==0 and not getstate(current) then - setstate(current,s_init) - end - n=n+1 - else - n=0 - end - current=getnext(current) - end + if n==0 and not getstate(current) then + setstate(current,s_init) + end + n=n+1 + else + n=0 + end + current=getnext(current) + end return head,done end for i=1,nofscripts do |