diff options
author | Hans Hagen <pragma@wxs.nl> | 2018-05-12 01:19:03 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg42.2a@gmail.com> | 2018-05-12 01:19:03 +0200 |
commit | 77e216e323271fb85d508b7206b13c980540b74b (patch) | |
tree | 5b4053c2bbe5190e28c0dce89653c7b13aea0642 /tex | |
parent | d817aef76ab8b606c02bd0636661b634b43a68a6 (diff) | |
download | context-77e216e323271fb85d508b7206b13c980540b74b.tar.gz |
2018-05-12 00:16:00
Diffstat (limited to 'tex')
150 files changed, 5595 insertions, 3333 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index b00d14298..16b089e82 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{2018.04.19 15:53} +\newcontextversion{2018.05.12 00:07} %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 118a48a35..d37888100 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{2018.04.19 15:53} +\edef\contextversion{2018.05.12 00:07} %D For those who want to use this: diff --git a/tex/context/base/mkiv/anch-pgr.lua b/tex/context/base/mkiv/anch-pgr.lua index ca5a5a8af..7b1746582 100644 --- a/tex/context/base/mkiv/anch-pgr.lua +++ b/tex/context/base/mkiv/anch-pgr.lua @@ -61,8 +61,6 @@ local pdfgetpos = pdf.getpos -- why not a generic name ! local a_textbackground = attributes.private("textbackground") local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode local new_latelua = nuts.pool.latelua local new_rule = nuts.pool.rule @@ -82,7 +80,7 @@ local localpar_code = nodecodes.localpar local insert_before = nuts.insert_before local insert_after = nuts.insert_after -local processranges = nodes.processranges +local processranges = nuts.processranges local unsetvalue = attributes.unsetvalue @@ -213,10 +211,8 @@ end nodes.handlers.textbackgrounds = function(head,where,parent) -- we have hlistdir and local dir -- todo enable action in register - head = tonut(head) index = index + 1 - local head, done = processranges(a_textbackground,flush,head,parent) - return tonode(head), done + return processranges(a_textbackground,flush,head,parent) end interfaces.implement { diff --git a/tex/context/base/mkiv/back-exp.lua b/tex/context/base/mkiv/back-exp.lua index 26efe6aad..fd86217b1 100644 --- a/tex/context/base/mkiv/back-exp.lua +++ b/tex/context/base/mkiv/back-exp.lua @@ -129,9 +129,8 @@ local isglyph = nuts.isglyph local getkern = nuts.getkern local getwidth = nuts.getwidth - -local traverse_id = nuts.traverse_id -local traverse_nodes = nuts.traverse +local nexthlist = nuts.traversers.hlist +local nextnode = nuts.traversers.node local references = structures.references local structurestags = structures.tags @@ -2749,10 +2748,7 @@ end local function collectresults(head,list,pat,pap) -- is last used (we also have currentattribute) local p --- for n in traverse_nodes(head) do --- local c, id = isglyph(n) -- 14: image, 8: literal (mp) --- if c then - for n, id in traverse_nodes(head) do + for n, id in nextnode, head do if id == glyph_code then local c = getchar(n) local at = getattr(n,a_tagged) or pat @@ -3073,12 +3069,12 @@ function nodes.handlers.export(head) -- hooks into the page builder report_export("%w<!-- stop flushing page -->",currentdepth) end stoptiming(treehash) - return head, true + return head end -function builders.paragraphs.tag(head) +function builders.paragraphs.tag(head) -- traverse_list noftextblocks = noftextblocks + 1 - for n in traverse_id(hlist_code,tonut(head)) do + for n in nexthlist, head do local subtype = getsubtype(n) if subtype == line_code then setattr(n,a_textblock,noftextblocks) @@ -3089,6 +3085,22 @@ function builders.paragraphs.tag(head) return false end +if LUATEXVERSION >= 1.090 then + + function builders.paragraphs.tag(head) -- traverse_list + noftextblocks = noftextblocks + 1 + for n, subtype in nexthlist, head do + if subtype == line_code then + setattr(n,a_textblock,noftextblocks) + elseif subtype == glue_code or subtype == kern_code then -- no need to set fontkerns + setattr(n,a_textblock,0) + end + end + return false + end + +end + do local xmlcollected = xml.collected @@ -3795,19 +3807,14 @@ local htmltemplate = [[ stoptiming(treehash) end - local appendaction = nodes.tasks.appendaction local enableaction = nodes.tasks.enableaction function structurestags.initializeexport() if not exporting then report_export("enabling export to xml") - -- not yet known in task-ini - appendaction("shipouts","normalizers", "nodes.handlers.export") - -- enableaction("shipouts","nodes.handlers.export") + enableaction("shipouts","nodes.handlers.export") enableaction("shipouts","nodes.handlers.accessibility") enableaction("math", "noads.handlers.tags") - -- appendaction("finalizers","lists","builders.paragraphs.tag") - -- enableaction("finalizers","builders.paragraphs.tag") luatex.registerstopactions(structurestags.finishexport) exporting = true end diff --git a/tex/context/base/mkiv/buff-ini.lua b/tex/context/base/mkiv/buff-ini.lua index 1c7912773..970042c1b 100644 --- a/tex/context/base/mkiv/buff-ini.lua +++ b/tex/context/base/mkiv/buff-ini.lua @@ -645,7 +645,10 @@ local function gettexbuffer(name) end end -buffers.run = runbuffer +buffers.get = getbuffer +buffers.getmkiv = getbuffermkiv +buffers.gettexbuffer = gettexbuffer +buffers.run = runbuffer implement { name = "getbufferctxlua", actions = loadcontent, arguments = "string" } implement { name = "getbuffer", actions = getbuffer, arguments = "string" } @@ -708,3 +711,18 @@ do end end + +-- moved here: + +function buffers.samplefile(name) + if not buffers.exists(name) then + buffers.assign(name,io.loaddata(resolvers.findfile(name))) + end + buffers.get(name) +end + +implement { + name = "samplefile", -- bad name, maybe rename to injectbuffercontent + actions = buffers.samplefile, + arguments = "string" +} diff --git a/tex/context/base/mkiv/char-act.mkiv b/tex/context/base/mkiv/char-act.mkiv index 6b2ca51e2..ff4dc621f 100644 --- a/tex/context/base/mkiv/char-act.mkiv +++ b/tex/context/base/mkiv/char-act.mkiv @@ -78,12 +78,17 @@ % \unexpanded\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode} % \unexpanded\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode} -\unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\letcharcode\tabasciicode \obeyedtab } -\unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\obeyedline} -\unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\letcharcode\formfeedasciicode \obeyedpage} +\def\_obeyed_space_{\obeyedspace} +\def\_obeyed_tab_ {\obeyedtab} +\def\_obeyed_line_ {\obeyedline} +\def\_obeyed_page_ {\obeyedpage} -\unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\letcharcode\tabasciicode \obeyedspace} -\unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\obeyedspace} +\unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\letcharcode\tabasciicode \_obeyed_tab_ } +\unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\_obeyed_line_} +\unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\letcharcode\formfeedasciicode \_obeyed_page_} + +\unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\letcharcode\tabasciicode \_obeyed_space_} +\unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\_obeyed_space_} \unexpanded\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode} \unexpanded\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode} diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua index 86dec0209..8e4f2e729 100644 --- a/tex/context/base/mkiv/cldf-ini.lua +++ b/tex/context/base/mkiv/cldf-ini.lua @@ -1224,34 +1224,39 @@ do end end -end - --- - -function context.runfile(filename) - local foundname = resolvers.findtexfile(file.addsuffix(filename,"cld")) or "" - if foundname ~= "" then - local ok = dofile(foundname) - if type(ok) == "function" then - if trace_cld then - report_context("begin of file %a (function call)",foundname) - end - ok() - if trace_cld then - report_context("end of file %a (function call)",foundname) + local findtexfile = resolvers.findtexfile + local findfile = resolvers.findfile + + function context.runfile(filename) + local foundname = findtexfile(file.addsuffix(filename,"cld")) or "" + if foundname ~= "" then + local ok = dofile(foundname) + if type(ok) == "function" then + if trace_cld then + report_context("begin of file %a (function call)",foundname) + end + ok() + if trace_cld then + report_context("end of file %a (function call)",foundname) + end + elseif ok then + report_context("file %a is processed and returns true",foundname) + else + report_context("file %a is processed and returns nothing",foundname) end - elseif ok then - report_context("file %a is processed and returns true",foundname) else - report_context("file %a is processed and returns nothing",foundname) + report_context("unknown file %a",filename) end - else - report_context("unknown file %a",filename) end -end -function context.loadfile(filename) - context(stripstring(loaddata(resolvers.findfile(filename)))) + function context.loadfile(filename) + context(stripstring(loaddata(findfile(filename)))) + end + + function context.loadviafile(filename) + viafile(stripstring(loaddata(findfile(filename)))) + end + end -- some functions diff --git a/tex/context/base/mkiv/cldf-ini.mkiv b/tex/context/base/mkiv/cldf-ini.mkiv index 27ce42aa2..0cf3b892c 100644 --- a/tex/context/base/mkiv/cldf-ini.mkiv +++ b/tex/context/base/mkiv/cldf-ini.mkiv @@ -49,6 +49,7 @@ \normalprotected\def\cldprocessfile#1{\directlua{context.runfile("#1")}} \def\cldloadfile #1{\directlua{context.loadfile("#1")}} + \def\cldloadviafile#1{\directlua{context.loadviafile("#1")}} \def\cldcontext #1{\directlua{context(#1)}} \def\cldcommand #1{\directlua{context.#1}} % \def\cldverbatim #1{\directlua{context.verbatim.#1}} % maybe make verbatim global diff --git a/tex/context/base/mkiv/colo-ini.lua b/tex/context/base/mkiv/colo-ini.lua index 921612b0f..f423346b4 100644 --- a/tex/context/base/mkiv/colo-ini.lua +++ b/tex/context/base/mkiv/colo-ini.lua @@ -43,6 +43,7 @@ local texsetattribute = tex.setattribute local texgetattribute = tex.getattribute local texgetcount = tex.getcount local texgettoks = tex.gettoks +local texgetmacro = tokens.getters.macro local a_color = attributes.private('color') local a_transparency = attributes.private('transparency') @@ -698,7 +699,8 @@ local paletnamespace = getnamespace("colorpalet") local function namedcolorattributes(name) local space = texgetattribute(a_colormodel) - local prefix = texgettoks("t_colo_prefix") + ----- prefix = texgettoks("t_colo_prefix") + local prefix = texgetmacro("currentcolorprefix") local color if prefix ~= "" then color = valid[prefix..name] diff --git a/tex/context/base/mkiv/colo-ini.mkiv b/tex/context/base/mkiv/colo-ini.mkiv index daee8ada6..7ecb05d23 100644 --- a/tex/context/base/mkiv/colo-ini.mkiv +++ b/tex/context/base/mkiv/colo-ini.mkiv @@ -592,22 +592,22 @@ % \the\everysetuppalet % \colo_helpers_initialize_maintextcolor} -\newtoks\t_colo_prefix % used in mp interface +% \newtoks\t_colo_prefix % used in mp interface \def\colo_palets_setup[#1]% {\edef\currentcolorpalet{#1}% \ifx\currentcolorpalet\empty % seems to be a reset \let\currentcolorprefix\empty - \t_colo_prefix\emptytoks + %\t_colo_prefix\emptytoks \else\ifcsname\??paletlist\currentcolorpalet\endcsname \edef\currentcolorprefix{#1:}% - \t_colo_prefix\expandafter{\currentcolorprefix}% + %\t_colo_prefix\expandafter{\currentcolorprefix}% \else \colo_helpers_show_message\m!colors7\currentcolorpalet \let\currentcolorpalet\empty \let\currentcolorprefix\empty - \t_colo_prefix\emptytoks + %\t_colo_prefix\emptytoks \fi\fi \the\everysetuppalet \colo_helpers_initialize_maintextcolor} diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 9fa8f68a4..105bd1ccf 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2018.04.19 15:53} +\newcontextversion{2018.05.12 00:07} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 24482906c..1d44fefd0 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -42,7 +42,7 @@ %D has to match \type {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2018.04.19 15:53} +\edef\contextversion{2018.05.12 00:07} \edef\contextkind {beta} %D For those who want to use this: @@ -274,7 +274,6 @@ \loadmarkfile{spac-lin} \loadmarkfile{spac-pag} \loadmarkfile{spac-par} -%loadmarkfile{spac-adj} % no longer needed \loadmarkfile{spac-def} \loadmkvifile{spac-prf} \loadmarkfile{spac-grd} diff --git a/tex/context/base/mkiv/data-res.lua b/tex/context/base/mkiv/data-res.lua index 9fb33f88d..9f5e3a8ac 100644 --- a/tex/context/base/mkiv/data-res.lua +++ b/tex/context/base/mkiv/data-res.lua @@ -1875,7 +1875,7 @@ function resolvers.booleanvariable(str,default) end function resolvers.dowithfilesintree(pattern,handle,before,after) -- will move, can be a nice iterator instead - local hashes = instance.hashes + local hashes = instance.hashes for i=1,#hashes do local hash = hashes[i] local blobtype = hash.type diff --git a/tex/context/base/mkiv/file-job.mkvi b/tex/context/base/mkiv/file-job.mkvi index e1ea405c0..f1f2d126f 100644 --- a/tex/context/base/mkiv/file-job.mkvi +++ b/tex/context/base/mkiv/file-job.mkvi @@ -347,12 +347,15 @@ % Bonus: -\installcorenamespace{samplefile} +% \installcorenamespace{samplefile} +% +% \unexpanded\def\samplefile#1% +% {\ifcsname\??samplefile#1\endcsname \else +% \setxvalue{\??samplefile#1}{\cldloadfile{#1}}% +% \fi +% \lastnamedcs} \unexpanded\def\samplefile#1% - {\ifcsname\??samplefile#1\endcsname \else - \setxvalue{\??samplefile#1}{\cldloadfile{#1}}% - \fi - \lastnamedcs} + {\clf_samplefile{#1}} \protect \endinput diff --git a/tex/context/base/mkiv/font-chk.lua b/tex/context/base/mkiv/font-chk.lua index 4e7bf939b..5bd85fe66 100644 --- a/tex/context/base/mkiv/font-chk.lua +++ b/tex/context/base/mkiv/font-chk.lua @@ -66,14 +66,15 @@ local hpack_node = node.hpack local nuts = nodes.nuts local tonut = nuts.tonut -local tonode = nuts.tonode local getfont = nuts.getfont local getchar = nuts.getchar local setchar = nuts.setchar -local traverse_id = nuts.traverse_id +----- traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph + local remove_node = nuts.remove local insert_node_after = nuts.insert_after @@ -281,7 +282,7 @@ end local function placeholder(font,char) local tfmdata = fontdata[font] - local category = chardata[char].category + local category = chardata[char].category or "unknown" local fakechar = mapping[category] local slot = getprivateslot(font,fakechar) if not slot then @@ -295,15 +296,14 @@ checkers.placeholder = placeholder function checkers.missing(head) local lastfont, characters, found = nil, nil, nil - head = tonut(head) - for n in traverse_id(glyph_code,head) do -- faster than while loop so we delay removal + for n in nextglyph, head do -- faster than while loop so we delay removal local font = getfont(n) local char = getchar(n) if font ~= lastfont then characters = fontcharacters[font] lastfont = font end - if font > 0 and not characters[char] and is_character[chardata[char].category] then + if font > 0 and not characters[char] and is_character[chardata[char].category or "unknown"] then if action == "remove" then onetimemessage(font,char,"missing (will be deleted)") elseif action == "replace" then @@ -340,7 +340,7 @@ function checkers.missing(head) else -- maye write a report to the log end - return tonode(head), false + return head end local relevant = { diff --git a/tex/context/base/mkiv/font-col.lua b/tex/context/base/mkiv/font-col.lua index 8aad4d7d5..e5fd37b1b 100644 --- a/tex/context/base/mkiv/font-col.lua +++ b/tex/context/base/mkiv/font-col.lua @@ -19,15 +19,14 @@ local fastcopy = table.fastcopy local formatters = string.formatters local nuts = nodes.nuts -local tonut = nuts.tonut local getfont = nuts.getfont local getchar = nuts.getchar local setfont = nuts.setfont -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char +----- traverse_char = nuts.traverse_char +local nextchar = nuts.traversers.char local settings_to_hash = utilities.parsers.settings_to_hash @@ -311,8 +310,7 @@ local function monoslot(font,char,parent,factor) end function collections.process(head) -- this way we keep feature processing - local done = false - for n in traverse_char(tonut(head)) do + for n in nextchar, head do local font = getfont(n) local vector = vectors[font] if vector then @@ -329,7 +327,6 @@ function collections.process(head) -- this way we keep feature processing ) end setfont(n,newfont,newchar) - done = true else local fakemono = vector.factor if trace_collecting then @@ -342,11 +339,48 @@ function collections.process(head) -- this way we keep feature processing else setfont(n,vect) end - done = true end end end - return head, done + return head +end + +if LUATEXVERSION >= 1.090 then + + function collections.process(head) -- this way we keep feature processing + for n, char, font in nextchar, head do + local vector = vectors[font] + if vector then + local vect = vector[char] + if not vect then + -- keep it + elseif type(vect) == "table" then + local newfont = vect[1] + local newchar = vect[2] + if trace_collecting then + report_fonts("remapping character %C in font %a to character %C in font %a%s", + char,font,newchar,newfont,not chardata[newfont][newchar] and " (missing)" or "" + ) + end + setfont(n,newfont,newchar) + else + local fakemono = vector.factor + if trace_collecting then + report_fonts("remapping font %a to %a for character %C%s", + font,vect,char,not chardata[vect][char] and " (missing)" or "" + ) + end + if fakemono then + setfont(n,vect,monoslot(vect,char,font,fakemono)) + else + setfont(n,vect) + end + end + end + end + return head + end + end function collections.found(font,char) -- this way we keep feature processing diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua index 73e9ffe22..d6fe55c65 100644 --- a/tex/context/base/mkiv/font-con.lua +++ b/tex/context/base/mkiv/font-con.lua @@ -768,12 +768,15 @@ function constructors.scale(tfmdata,specification) local t = { } for i=1,#vv do local vvi = vv[i] - t[i] = { - ["start"] = (vvi["start"] or 0)*vdelta, - ["end"] = (vvi["end"] or 0)*vdelta, - ["advance"] = (vvi["advance"] or 0)*vdelta, - ["extender"] = vvi["extender"], - ["glyph"] = vvi["glyph"], + local s = vvi["start"] or 0 + local e = vvi["end"] or 0 + local a = vvi["advance"] or 0 + t[i] = { -- zero check nicer for 5.3 + ["start"] = s == 0 and 0 or s * vdelta, + ["end"] = e == 0 and 0 or e * vdelta, + ["advance"] = a == 0 and 0 or a * vdelta, + ["extender"] = vvi["extender"], + ["glyph"] = vvi["glyph"], } end chr.vert_variants = t @@ -783,12 +786,15 @@ function constructors.scale(tfmdata,specification) local t = { } for i=1,#hv do local hvi = hv[i] - t[i] = { - ["start"] = (hvi["start"] or 0)*hdelta, - ["end"] = (hvi["end"] or 0)*hdelta, - ["advance"] = (hvi["advance"] or 0)*hdelta, - ["extender"] = hvi["extender"], - ["glyph"] = hvi["glyph"], + local s = hvi["start"] or 0 + local e = hvi["end"] or 0 + local a = hvi["advance"] or 0 + t[i] = { -- zero check nicer for 5.3 + ["start"] = s == 0 and 0 or s * hdelta, + ["end"] = e == 0 and 0 or e * hdelta, + ["advance"] = a == 0 and 0 or a * hdelta, + ["extender"] = hvi["extender"], + ["glyph"] = hvi["glyph"], } end chr.horiz_variants = t @@ -902,7 +908,7 @@ function constructors.scale(tfmdata,specification) else chr.commands = vc end - chr.index = nil + -- chr.index = nil end end targetcharacters[unicode] = chr @@ -912,7 +918,7 @@ function constructors.scale(tfmdata,specification) -- constructors.aftercopyingcharacters(target,tfmdata) -- - constructors.trytosharefont(target,tfmdata) + constructors.trytosharefont(target,tfmdata) -- -- catch inconsistencies -- diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua index 68191143b..f24686106 100644 --- a/tex/context/base/mkiv/font-ctx.lua +++ b/tex/context/base/mkiv/font-ctx.lua @@ -79,6 +79,9 @@ local aglunicodes = nil -- delayed loading local nuts = nodes.nuts local tonut = nuts.tonut +----- traverse_char = nuts.traverse_char +local nextchar = nuts.traversers.char + local getattr = nuts.getattr local setattr = nuts.setattr local getprop = nuts.getprop @@ -583,12 +586,11 @@ local function presetcontext(name,parent,features) -- will go to con and shared features = { } elseif type(features) == "string" then features = normalize_features(settings_to_hash(features)) - for key, value in next, features do - if type(value) == "string" and find(value,"=") then - local t = settings_to_hash(value) + for key, value in next, features do + if type(value) == "string" and find(value,"[=:]") then + local t = settings_to_hash_colon_too(value) if next(t) then --- features[key] = sequenced(normalize_features(t),",") - features[key] = t -- sequenced(normalize_features(t),",") + features[key] = sequenced(normalize_features(t),",") end end end @@ -2635,8 +2637,6 @@ do local unsetvalue = attributes.unsetvalue - local traverse_char = nuts.traverse_char - local a_color = attributes.private('color') local a_colormodel = attributes.private('colormodel') local a_state = attributes.private('state') @@ -2660,11 +2660,14 @@ do [states.pstf] = "font:5", } + -- todo: traversers + -- todo: check attr_list so that we can use the same .. helper: setcolorattr + local function markstates(head) if head then head = tonut(head) local model = getattr(head,a_colormodel) or 1 - for glyph in traverse_char(head) do + for glyph in nextchar, head do local a = getprop(glyph,a_state) if a then local name = colornames[a] @@ -2715,7 +2718,7 @@ do function methods.nocolor(head,font,attr) - for n in traverse_char(head) do + for n in nextchar, head do if not font or getfont(n) == font then setattr(n,a_color,unsetvalue) end @@ -3247,3 +3250,109 @@ do } end + +-- handy, for now here: + +function fonts.helpers.collectanchors(tfmdata) + + local resources = tfmdata.resources -- todo: use shared + + if not resources or resources.anchors then + return resources.anchors + end + + local anchors = { } + + local function set(unicode,target,class,anchor) + local a = anchors[unicode] + if not a then + anchors[unicode] = { [target] = { anchor } } + return + end + local t = a[target] + if not t then + a[target] = { anchor } + return + end + local x, y = anchor[1], anchor[2] + for k, v in next, t do + if v[1] == x and v[2] == y then + return + end + end + t[#t+1] = anchor + end + + local function getanchors(steps,target) + for i=1,#steps do + local step = steps[i] + local coverage = step.coverage + for unicode, data in next, coverage do + local class = data[1] + local anchor = data[2] + if anchor[1] ~= 0 or anchor[2] ~= 0 then + set(unicode,target,class,anchor) + end + end + end + end + + local function getcursives(steps) + for i=1,#steps do + local step = steps[i] + local coverage = step.coverage + for unicode, data in next, coverage do + local class = data[1] + local en = data[2] + local ex = data[3] + if en then + set(unicode,"entry",class,en) + end + if ex then + set(unicode,"exit", class,ex) + end + end + end + end + + local function collect(list) + if list then + for i=1,#list do + local entry = list[i] + local steps = entry.steps + local kind = entry.type + if kind == "gpos_mark2mark" then + getanchors(steps,"mark") + elseif kind == "gpos_mark2base" then + getanchors(steps,"base") + elseif kind == "gpos_mark2ligature" then + getanchors(steps,"ligature") + elseif kind == "gpos_cursive" then + getcursives(steps) + end + end + end + end + + collect(resources.sequences) + collect(resources.sublookups) + + local function sorter(a,b) + if a[1] == b[1] then + return a[2] < b[2] + else + return a[1] < b[1] + end + end + + for unicode, old in next, anchors do + for target, list in next, old do + sort(list,sorter) + end + end + + resources.anchors = anchors + + return anchors + +end diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua index c896aa711..6279dda89 100644 --- a/tex/context/base/mkiv/font-dsp.lua +++ b/tex/context/base/mkiv/font-dsp.lua @@ -68,12 +68,13 @@ local reversed = table.reversed local sort = table.sort local insert = table.insert local round = math.round -local settings_to_hash_colon_too = table.settings_to_hash_colon_too +local settings_to_hash = utilities.parsers.settings_to_hash_colon_too local setmetatableindex = table.setmetatableindex local formatters = string.formatters local sortedkeys = table.sortedkeys local sortedhash = table.sortedhash +local sequenced = table.sequenced local report = logs.reporter("otf reader") @@ -324,7 +325,7 @@ end) -- wght:400,wdth:100,ital:1 local function axistofactors(str) - local t = settings_to_hash_colon_too(str) + local t = settings_to_hash(str) for k, v in next, t do t[k] = tonumber(v) or v -- this also normalizes numbers itself end @@ -349,10 +350,6 @@ function helpers.normalizedaxis(str) return hash[str] or str end -local function axistofactors(str) - return settings_to_hash_colon_too(str) -end - -- contradicting spec ... (signs) so i'll check it and fix it once we have -- proper fonts diff --git a/tex/context/base/mkiv/font-gbn.lua b/tex/context/base/mkiv/font-gbn.lua index 8f1acac65..e2d245860 100644 --- a/tex/context/base/mkiv/font-gbn.lua +++ b/tex/context/base/mkiv/font-gbn.lua @@ -47,8 +47,8 @@ local setprev = nuts.setprev local n_ligaturing = node.ligaturing local n_kerning = node.kerning -local ligaturing = nuts.ligaturing -local kerning = nuts.kerning +local d_ligaturing = nuts.ligaturing +local d_kerning = nuts.kerning local basemodepass = true @@ -69,15 +69,30 @@ function node.kerning(...) return n_kerning(...) end +function nuts.ligaturing(...) + if basemodepass and l_warning then + l_warning() + end + return d_ligaturing(...) +end + +function nuts.kerning(...) + if basemodepass and k_warning then + k_warning() + end + return d_kerning(...) +end + +-- direct.ligaturing = nuts.ligaturing +-- direct.kerning = nuts.kerning + function nodes.handlers.setbasemodepass(v) basemodepass = v end --------- nodes.handlers.nodepass(head) -function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) +local function nodepass(head,groupcode,size,packtype,direction) local fontdata = fonts.hashes.identifiers if fontdata then - local nuthead = tonut(head) local usedfonts = { } local basefonts = { } local prevfont = nil @@ -85,7 +100,7 @@ function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) local variants = nil local redundant = nil local nofused = 0 - for n in traverse_id(glyph_code,nuthead) do + for n in traverse_id(glyph_code,head) do local font = getfont(n) if font ~= prevfont then if basefont then @@ -147,8 +162,8 @@ function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) for i=1,#redundant do local r = redundant[i] local p, n = getboth(r) - if r == nuthead then - nuthead = n + if r == head then + head = n setprev(n) else setlink(p,n) @@ -167,7 +182,7 @@ function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) flush_node(r) end end - for d in traverse_id(disc_code,nuthead) do + for d in traverse_id(disc_code,head) do local _, _, r = getdisc(d) if r then for n in traverse_id(glyph_code,r) do @@ -205,16 +220,16 @@ function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) local start = range[1] local stop = range[2] if start then - local front = nuthead == start + local front = head == start local prev, next if stop then next = getnext(stop) - start, stop = ligaturing(start,stop) - start, stop = kerning(start,stop) + start, stop = d_ligaturing(start,stop) + start, stop = d_kerning(start,stop) else prev = getprev(start) - start = ligaturing(start) - start = kerning(start) + start = d_ligaturing(start) + start = d_kerning(start) end if prev then setlink(prev,start) @@ -222,41 +237,65 @@ function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) if next then setlink(stop,next) end - if front and nuthead ~= start then - head = tonode(start) + if front and head ~= start then + head = start end end end end - return head, true - else - return head, false end + return head end -function nodes.handlers.basepass(head) +local function basepass(head) if basemodepass then - head = n_ligaturing(head) - head = n_kerning(head) + head = d_ligaturing(head) + head = d_kerning(head) end - return head, true + return head end -local nodepass = nodes.handlers.nodepass -local basepass = nodes.handlers.basepass +local protectpass = node.direct.protect_glyphs local injectpass = nodes.injections.handler -local protectpass = nodes.handlers.protectglyphs + +-- This is the only official public interface and this one can be hooked into a callback (chain) and +-- everything else can change!@ Functione being visibel doesn't mean that it's part of the api. + +function nodes.handlers.nodepass(head,...) + if head then + return tonode(nodepass(tonut(head),...)) + end +end + +function nodes.handlers.basepass(head) + if head then + return tonode(basepass(tonut(head))) + end +end + +function nodes.handlers.injectpass(head) + if head then + return tonode(injectpass(tonut(head))) + end +end + +function nodes.handlers.protectpass(head) + if head then + protectpass(tonut(head)) + return head + end +end function nodes.simple_font_handler(head,groupcode,size,packtype,direction) if head then + head = tonut(head) head = nodepass(head,groupcode,size,packtype,direction) head = injectpass(head) if not basemodepass then head = basepass(head) end protectpass(head) - return head, true - else - return head, false + head = tonode(head) end + return head end diff --git a/tex/context/base/mkiv/font-imp-effects.lua b/tex/context/base/mkiv/font-imp-effects.lua index cb7cf10d3..578c8bc10 100644 --- a/tex/context/base/mkiv/font-imp-effects.lua +++ b/tex/context/base/mkiv/font-imp-effects.lua @@ -22,8 +22,10 @@ local settings_to_hash = utilities.parsers.settings_to_hash_colon_too local helpers = fonts.helpers local prependcommands = helpers.prependcommands local charcommand = helpers.commands.char +local leftcommand = helpers.commands.left local rightcommand = helpers.commands.right local upcommand = helpers.commands.up +local downcommand = helpers.commands.down local dummycommand = helpers.commands.dummy ----- constructors = fonts.constructors @@ -244,7 +246,8 @@ local function setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze local character = characters[0x221A] - if character then + if character and character.next then +-- print("base char",0x221A,table.sequenced(character)) local char = character local next = character.next wdpatch(char) @@ -253,6 +256,7 @@ local function setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze char = characters[next] wdpatch(char) htpatch(char) +-- print("next char",next,table.sequenced(char)) next = char.next end if char then @@ -260,7 +264,9 @@ local function setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze if v then local top = v[#v] if top then - htpatch(characters[top.glyph]) + local char = characters[top.glyph] +-- print("top char",top.glyph,table.sequenced(char)) + htpatch(char) end end end @@ -269,8 +275,9 @@ end -- local show_effect = { "lua", function(f,c) -- report_effect("font id %i, char %C",f,c) +-- inspect(fonts.hashes.characters[f][c]) -- end } --- + -- local show_effect = { "lua", "print('!')" } local function manipulateeffect(tfmdata) @@ -288,7 +295,7 @@ local function manipulateeffect(tfmdata) local ddelta = effect.ddelta * vfactor * multiplier local vshift = effect.vshift * vfactor * multiplier local squeeze = effect.squeeze - local hshift = wdelta -- / 2 + local hshift = wdelta / 2 local dx = multiplier * vfactor local dy = vshift local factor = (1 + effect.factor) * factor @@ -299,7 +306,6 @@ local function manipulateeffect(tfmdata) local oldwidth = character.width local oldheight = character.height local olddepth = character.depth - if oldwidth and oldwidth > 0 then character.width = oldwidth + wdelta local commands = character.commands @@ -335,10 +341,10 @@ local function manipulateeffect(tfmdata) end end if oldheight and oldheight > 0 then - character.height = oldheight + hdelta + character.height = oldheight + hdelta end if olddepth and olddepth > 0 then - character.depth = olddepth + ddelta + character.depth = olddepth + ddelta end end if mathparameters then diff --git a/tex/context/base/mkiv/font-nod.lua b/tex/context/base/mkiv/font-nod.lua index cdceb98a2..b98534f38 100644 --- a/tex/context/base/mkiv/font-nod.lua +++ b/tex/context/base/mkiv/font-nod.lua @@ -32,6 +32,10 @@ nodes.tasks = tasks local handlers = nodes.handlers or { } nodes.handlers = handlers +local nuts = nodes.nuts +local tonut = nuts.tonut +local tonode = nuts.tonode + local injections = nodes.injections or { } nodes.injections = injections @@ -52,10 +56,6 @@ local kern_code = nodecodes.kern local dir_code = nodecodes.dir local localpar_code = nodecodes.localpar -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - local getfield = nuts.getfield local getnext = nuts.getnext local getprev = nuts.getprev @@ -78,9 +78,11 @@ local setsubtype = nuts.setsubtype local copy_node_list = nuts.copy_list local hpack_node_list = nuts.hpack local flush_node_list = nuts.flush_list -local traverse_nodes = nuts.traverse local protect_glyphs = nuts.protect_glyphs +local nextnode = nuts.traversers.node +local nextglyph = nuts.traversers.glyph + local nodepool = nuts.pool local new_glyph = nodepool.glyph @@ -101,7 +103,7 @@ local properties = nodes.properties.data -- direct.set_properties_mode(true,true) -- default local function freeze(h,where) - for n in traverse_nodes(tonut(h)) do -- todo: disc but not traced anyway + for n in nextnode, h do -- todo: disc but not traced anyway local p = properties[n] if p then local i = p.injections if i then p.injections = fastcopy(i) end @@ -114,7 +116,6 @@ local function freeze(h,where) end function char_tracers.collect(head,list,tag,n) - head = tonut(head) n = n or 0 local ok, fn = false, nil while head do @@ -137,17 +138,17 @@ function char_tracers.collect(head,list,tag,n) -- skip -- local pre, post, replace = getdisc(head) -- if replace then - -- for n in traverse_id(glyph_code,replace) do + -- for n in nextglyph, replace do -- l[#l+1] = { c, f } -- end -- end -- if pre then - -- for n in traverse_id(glyph_code,pre) do + -- for n in nextglyph, pre do -- l[#l+1] = { c, f } -- end -- end -- if post then - -- for n in traverse_id(glyph_code,post) do + -- for n in nextglyph, post do -- l[#l+1] = { c, f } -- end -- end @@ -220,12 +221,12 @@ function char_tracers.start() function handlers.characters(head) local n = #list char_tracers.collect(head,list,'before',n) - local h, d = npc(tonode(head)) -- for the moment tonode + head = npc(head) -- for the moment tonode char_tracers.collect(head,list,'after',n) if #list > n then list[#list+1] = { } end - return h, d + return head end function char_tracers.stop() tracers.list['characters'] = list @@ -391,7 +392,7 @@ function step_tracers.codes(i,command,space) if w then context.startcolor(colors[what]) context("%s:",what) - for c, id in traverse_nodes(w) do + for c, id in nextnode, w do if id == glyph_code then showchar(c) else @@ -408,7 +409,7 @@ function step_tracers.codes(i,command,space) if id == glyph_code then showchar(c) elseif id == dir_code or id == localpar_code then - context("[%s]",getdir(c)) + context("[%s]",getdir(c) or "unset") elseif id == disc_code then local pre, post, replace = getdisc(c) if pre or post or replace then @@ -451,13 +452,12 @@ end function step_tracers.check(head) if collecting then step_tracers.reset() - local h = tonut(head) - local n = copy_node_list(h) + local n = copy_node_list(head) freeze(n,"check") - injections.keepcounts(n) -- one-time + injections.keepcounts() -- one-time local l = injections.handler(n,"trace") if l then -- hm, can be false - n = tonut(l) + n = l end protect_glyphs(n) collection[1] = n @@ -468,13 +468,12 @@ function step_tracers.register(head) if collecting then local nc = #collection+1 if messages[nc] then - local h = tonut(head) - local n = copy_node_list(h) + local n = copy_node_list(head) freeze(n,"register") - injections.keepcounts(n) -- one-time + injections.keepcounts() -- one-time local l = injections.handler(n,"trace") if l then -- hm, can be false - n = tonut(l) + n = l end protect_glyphs(n) collection[nc] = n @@ -499,10 +498,7 @@ local threshold = 65536 -- 1pt local function toutf(list,result,nofresult,stopcriterium,nostrip) if list then --- for n in traverse_nodes(tonut(list)) do --- local c, id = isglyph(n) --- if c then - for n, id in traverse_nodes(tonut(list)) do + for n, id in nextnode, tonut(list) do if id == glyph_code then local c = getchar(n) local components = getcomponents(n) diff --git a/tex/context/base/mkiv/font-osd.lua b/tex/context/base/mkiv/font-osd.lua index 51f644ad1..32d791b48 100644 --- a/tex/context/base/mkiv/font-osd.lua +++ b/tex/context/base/mkiv/font-osd.lua @@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['font-osd'] = { -- script devanag license = "see context related readme files" } + +-- we need to check nbsphash (context only) + -- A few remarks: -- -- This code is a partial rewrite of the code that deals with devanagari. The data @@ -96,8 +99,6 @@ local otffeatures = fonts.constructors.features.otf local registerotffeature = otffeatures.register local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut local getnext = nuts.getnext local getprev = nuts.getprev @@ -152,47 +153,27 @@ replace_all_nbsp = function(head) -- delayed definition return replace_all_nbsp(head) end -local xprocesscharacters = nil +local processcharacters = nil if context then - xprocesscharacters = function(head,font) - xprocesscharacters = nodes.handlers.characters - return xprocesscharacters(head,font) + local fontprocesses = fonts.hashes.processes + function processcharacters(head,font) + local processors = fontprocesses[font] + for i=1,#processors do + head = processors[i](head,font,0) + end + return head end else - xprocesscharacters = function(head,font) - xprocesscharacters = nodes.handlers.nodepass -- generic - return xprocesscharacters(head,font) + function processcharacters(head,font) + local processors = fontdata[font].shared.processes + for i=1,#processors do + head = processors[i](head,font,0) + end + return head end end -local function processcharacters(head,font) - return tonut(xprocesscharacters(tonode(head))) -- can be more efficient in context, just direct call -end - --- to be tested: --- --- local processcharacters = nil --- --- if context then --- local fontprocesses = fonts.hashes.processes --- function processcharacters(head,font) --- local processors = fontprocesses[font] --- for i=1,#processors do --- head = processors[i](head,font,0) --- end --- return head, true --- end --- else --- function processcharacters(head,font) --- local processors = fontdata[font].shared.processes --- for i=1,#processors do --- head = processors[i](head,font,0) --- end --- return head, true --- end --- end - -- We can assume that script are not mixed in the source but if that is the case -- we might need to have consonants etc per script and initialize a local table -- pointing to the right one. But not now. @@ -2067,7 +2048,6 @@ end -- a lot. Common code has been synced. local function method_one(head,font,attr) - head = tonut(head) local current = head local start = true local done = false @@ -2262,14 +2242,13 @@ local function method_one(head,font,attr) head = replace_all_nbsp(head) end - return tonode(head), done + return head, done end -- there is a good change that when we run into one with subtype < 256 that the rest is also done -- so maybe we can omit this check (it's pretty hard to get glyphs in the stream out of the blue) local function method_two(head,font,attr) - head = tonut(head) local current = head local start = true local done = false @@ -2358,7 +2337,7 @@ local function method_two(head,font,attr) head = replace_all_nbsp(head) end - return tonode(head), done + return head, done end for i=1,nofscripts do diff --git a/tex/context/base/mkiv/font-ota.lua b/tex/context/base/mkiv/font-ota.lua index de626c120..fd58a6e43 100644 --- a/tex/context/base/mkiv/font-ota.lua +++ b/tex/context/base/mkiv/font-ota.lua @@ -42,7 +42,6 @@ local getsubtype = nuts.getsubtype local getchar = nuts.getchar local ischar = nuts.is_char -local traverse_id = nuts.traverse_id local end_of_math = nuts.end_of_math local nodecodes = nodes.nodecodes diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua index a728163ce..8d1b540be 100644 --- a/tex/context/base/mkiv/font-otj.lua +++ b/tex/context/base/mkiv/font-otj.lua @@ -97,8 +97,11 @@ local setlink = nuts.setlink local setwidth = nuts.setwidth local getwidth = nuts.getwidth -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char +----- traverse_id = nuts.traverse_id +----- traverse_char = nuts.traverse_char +local nextchar = nuts.traversers.char +local nextglue = nuts.traversers.glue + local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after @@ -562,7 +565,7 @@ end local function showsub(n,what,where) report_injections("begin subrun: %s",where) - for n in traverse_char(n) do + for n in nextchar, n do showchar(n,where) show(n,what,where," ") end @@ -632,7 +635,6 @@ end -- +D-replace +D-replace local function inject_kerns_only(head,where) - head = tonut(head) if trace_injections then trace(head,"kerns") end @@ -708,7 +710,7 @@ local function inject_kerns_only(head,where) local done = false if pre then -- left|pre glyphs|right - for n in traverse_char(pre) do + for n in nextchar, pre do local p = rawget(properties,n) if p then local i = p.injections or p.preinjections @@ -724,7 +726,7 @@ local function inject_kerns_only(head,where) end if post then -- left|post glyphs|right - for n in traverse_char(post) do + for n in nextchar, post do local p = rawget(properties,n) if p then local i = p.injections or p.postinjections @@ -740,7 +742,7 @@ local function inject_kerns_only(head,where) end if replace then -- left|replace glyphs|right - for n in traverse_char(replace) do + for n in nextchar, replace do local p = rawget(properties,n) if p then local i = p.injections or p.replaceinjections @@ -775,11 +777,10 @@ local function inject_kerns_only(head,where) if trace_injections then show_result(head) end - return tonode(head), true + return head end local function inject_positions_only(head,where) - head = tonut(head) if trace_injections then trace(head,"positions") end @@ -882,7 +883,7 @@ local function inject_positions_only(head,where) local done = false if pre then -- left|pre glyphs|right - for n in traverse_char(pre) do + for n in nextchar, pre do local p = rawget(properties,n) if p then local i = p.injections or p.preinjections @@ -907,7 +908,7 @@ local function inject_positions_only(head,where) end if post then -- left|post glyphs|right - for n in traverse_char(post) do + for n in nextchar, post do local p = rawget(properties,n) if p then local i = p.injections or p.postinjections @@ -932,7 +933,7 @@ local function inject_positions_only(head,where) end if replace then -- left|replace glyphs|right - for n in traverse_char(replace) do + for n in nextchar, replace do local p = rawget(properties,n) if p then local i = p.injections or p.replaceinjections @@ -1006,7 +1007,7 @@ local function inject_positions_only(head,where) if trace_injections then show_result(head) end - return tonode(head), true + return head end local function showoffset(n,flag) @@ -1017,7 +1018,6 @@ local function showoffset(n,flag) end local function inject_everything(head,where) - head = tonut(head) if trace_injections then trace(head,"everything") end @@ -1348,7 +1348,7 @@ local function inject_everything(head,where) local done = false if pre then -- left|pre glyphs|right - for n in traverse_char(pre) do + for n in nextchar, pre do local p = rawget(properties,n) if p then local i = p.injections or p.preinjections @@ -1379,7 +1379,7 @@ local function inject_everything(head,where) end if post then -- left|post glyphs|right - for n in traverse_char(post) do + for n in nextchar, post do local p = rawget(properties,n) if p then local i = p.injections or p.postinjections @@ -1410,7 +1410,7 @@ local function inject_everything(head,where) end if replace then -- left|replace glyphs|right - for n in traverse_char(replace) do + for n in nextchar, replace do local p = rawget(properties,n) if p then local i = p.injections or p.replaceinjections @@ -1518,7 +1518,7 @@ local function inject_everything(head,where) if trace_injections then show_result(head) end - return tonode(head), true + return head end -- space triggers @@ -1607,7 +1607,7 @@ end local function injectspaces(head) if not triggers then - return head, false + return head end local lastfont = nil local spacekerns = nil @@ -1617,7 +1617,6 @@ local function injectspaces(head) local threshold = 0 local leftkern = false local rightkern = false - local nuthead = tonut(head) local function updatefont(font,trig) leftkerns = trig.left @@ -1627,7 +1626,7 @@ local function injectspaces(head) factor = getthreshold(font) end - for n in traverse_id(glue_code,nuthead) do + for n in nextglue, head do local prev, next = getspaceboth(n) local prevchar = prev and ischar(prev) local nextchar = next and ischar(next) @@ -1665,12 +1664,8 @@ local function injectspaces(head) if trace_spaces then report_spaces("%C [%p + %p + %p] %C",prevchar,lnew,old,rnew,nextchar) end - local h = insert_node_before(nuthead,n,italickern(lnew)) - if h == nuthead then - head = tonode(h) - nuthead = h - end - insert_node_after(nuthead,n,italickern(rnew)) + head = insert_node_before(head,n,italickern(lnew)) + insert_node_after(head,n,italickern(rnew)) else local new = old + (leftkern + rightkern) * factor if trace_spaces then @@ -1685,7 +1680,7 @@ local function injectspaces(head) if trace_spaces then report_spaces("%C [%p + %p]",prevchar,old,new) end - insert_node_after(nuthead,n,italickern(new)) -- tricky with traverse but ok + insert_node_after(head,n,italickern(new)) -- tricky with traverse but ok else local new = old + leftkern * factor if trace_spaces then @@ -1704,7 +1699,7 @@ local function injectspaces(head) if trace_spaces then report_spaces("%C [%p + %p]",nextchar,old,new) end - insert_node_after(nuthead,n,italickern(new)) + insert_node_after(head,n,italickern(new)) else local new = old + rightkern * factor if trace_spaces then @@ -1718,7 +1713,8 @@ local function injectspaces(head) end triggers = false - return head, true + + return head end -- @@ -1744,6 +1740,6 @@ function injections.handler(head,where) end return inject_kerns_only(head,where) else - return head, false + return head end end diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua index ac50ad00e..faee293f6 100644 --- a/tex/context/base/mkiv/font-ots.lua +++ b/tex/context/base/mkiv/font-ots.lua @@ -176,8 +176,6 @@ registertracker("otf.sample", "otf.steps","otf.substitutions","otf.positi registertracker("otf.sample.silent", "otf.steps=silent","otf.substitutions","otf.positions","otf.analyzing") local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut local getfield = nuts.getfield local getnext = nuts.getnext @@ -215,7 +213,7 @@ local find_node_tail = nuts.tail local flush_node_list = nuts.flush_list local flush_node = nuts.flush_node local end_of_math = nuts.end_of_math -local traverse_nodes = nuts.traverse +----- traverse_nodes = nuts.traverse ----- traverse_id = nuts.traverse_id local set_components = nuts.set_components local take_components = nuts.take_components @@ -226,6 +224,8 @@ local copy_only_glyphs = nuts.copy_only_glyphs local setmetatable = setmetatable local setmetatableindex = table.setmetatableindex +local nextnode = nuts.traversers.node + ----- zwnj = 0x200C ----- zwj = 0x200D @@ -3430,7 +3430,7 @@ local function k_run_single(sub,injection,last,font,attr,lookupcache,step,datase a = getattr(sub,0) end if not a or (a == attr) then - for n in traverse_nodes(sub) do -- only gpos + for n in nextnode, sub do -- only gpos if n == last then break end @@ -3595,7 +3595,7 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase a = getattr(sub,0) end if not a or (a == attr) then - for n in traverse_nodes(sub) do -- only gpos + for n in nextnode, sub do -- only gpos if n == last then break end @@ -3843,8 +3843,6 @@ do -- attr = false -- end - local head = tonut(head) - if trace_steps then checkstep(head) end @@ -3852,8 +3850,7 @@ do local initialrl = direction == "TRT" and -1 or 0 -- local initialrl = (direction == 1 or direction == "TRT") and -1 or 0 - local done = false - -- local datasets = otf.dataset(tfmdata,font,attr) + -- local done = false local datasets = otfdataset(tfmdata,font,attr) local dirstack = { } -- could move outside function but we can have local runs sweephead = { } @@ -3883,9 +3880,9 @@ do -- 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,attr) -- less arguments now - if ok then - done = true - end + -- if ok then + -- done = true + -- end if h and h ~= head then head = h end @@ -3918,7 +3915,7 @@ do local ok head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) if ok then - done = true + -- done = true break end end @@ -3961,9 +3958,9 @@ do if a then local ok head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) - if ok then - done = true - end + -- if ok then + -- done = true + -- end if start then start = getnext(start) end @@ -3987,9 +3984,9 @@ do else start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,skiphash,handler) end - if ok then - done = true - end + -- if ok then + -- done = true + -- end else start = getnext(start) end @@ -4033,7 +4030,7 @@ do local ok head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) if ok then - done = true + -- done = true break elseif not start then -- don't ask why ... shouldn't happen @@ -4064,9 +4061,9 @@ do else start, ok = comprun(start,c_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,skiphash,handler) end - if ok then - done = true - end + -- if ok then + -- done = true + -- end else start = getnext(start) end @@ -4090,12 +4087,12 @@ do end nesting = nesting - 1 - head = tonode(head) - return head, done + -- return head, done + return head end - -- This is not an official helpoer and used for tracing experiments. It can be changed as I like + -- This is not an official helper and used for tracing experiments. It can be changed as I like -- at any moment. At some point it might be used in a module that can help font development. function otf.datasetpositionprocessor(head,font,direction,dataset) @@ -4129,7 +4126,6 @@ do local steps = sequence.steps local nofsteps = sequence.nofsteps - local head = tonut(head) local done = false local dirstack = { } -- could move outside function but we can have local runs local start = head @@ -4192,7 +4188,7 @@ do end end - return tonode(head) -- , matches + return head end -- end of experiment diff --git a/tex/context/base/mkiv/font-sol.lua b/tex/context/base/mkiv/font-sol.lua index 8967d88e6..73f7252d1 100644 --- a/tex/context/base/mkiv/font-sol.lua +++ b/tex/context/base/mkiv/font-sol.lua @@ -54,8 +54,6 @@ local settings_to_hash = utilities.parsers.settings_to_hash local tasks = nodes.tasks local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getfield = nuts.getfield local getnext = nuts.getnext @@ -78,13 +76,15 @@ local find_node_tail = nuts.tail local flush_node = nuts.flush_node local flush_node_list = nuts.flush_list local copy_node_list = nuts.copy_list -local traverse_nodes = nuts.traverse -local traverse_ids = nuts.traverse_id local hpack_nodes = nuts.hpack local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after local protect_glyphs = nuts.protect_glyphs +local nextnode = nuts.traversers.next +local nexthlist = nuts.traversers.hlist +local nextwhatsit = nuts.traversers.whatsit + local repack_hlist = nuts.repackhlist local nodes_to_utf = nodes.listtoutf @@ -237,7 +237,6 @@ local function convert(featuresets,name,list) fs = contextsetups[feature] fn = fs and fs.number end --- inspect(fs) if fn then nofnumbers = nofnumbers + 1 numbers[nofnumbers] = fn @@ -345,9 +344,7 @@ directives.register("builders.paragraphs.solutions.splitters.encapsulate", funct end) function splitters.split(head) - -- quite fast - head = tonut(head) - local current, done, rlmode, start, stop, attribute = head, false, false, nil, nil, 0 + local current, rlmode, start, stop, attribute = head, false, nil, nil, 0 cache, max_less, max_more = { }, 0, 0 local function flush() -- we can move this local font = getfont(start) @@ -393,7 +390,7 @@ function splitters.split(head) local m = #solution.more if l > max_less then max_less = l end if m > max_more then max_more = m end - start, stop, done = nil, nil, true + start, stop = nil, nil end while current do -- also ischar local next = getnext(current) @@ -439,14 +436,14 @@ function splitters.split(head) end nofparagraphs = nofparagraphs + 1 nofwords = nofwords + #cache - return tonode(head), done + return head end local function collect_words(list) -- can be made faster for attributes local words, w, word = { }, 0, nil if encapsulate then - for current in traverse_ids(whatsit_code,list) do - if getsubtype(current) == userdefined_code then -- hm + for current, subtype in nextwhatsit, list do + if subtype == userdefined_code then -- hm local user_id = getfield(current,"user_id") if user_id == splitter_one then word = { getfield(current,"value"), current, current } @@ -584,21 +581,20 @@ local function doit(word,list,best,width,badness,line,set,listdir) noftries = noftries + 1 local first = copy_node_list(original) if not trace_colors then - for n in traverse_nodes(first) do -- maybe fast force so no attr needed + for n in nextnode, first do -- maybe fast force so no attr needed setattr(n,0,featurenumber) -- this forces dynamics end elseif set == "less" then - for n in traverse_nodes(first) do + for n in nextnode, first do setnodecolor(n,"font:isol") -- yellow setattr(n,0,featurenumber) end else - for n in traverse_nodes(first) do + for n in nextnode, first do setnodecolor(n,"font:medi") -- green setattr(n,0,featurenumber) end end -first = tonode(first) local font = found.font local setdynamics = setfontdynamics[font] if setdynamics then @@ -610,7 +606,6 @@ first = tonode(first) report_solutions("fatal error, no dynamics for font %a",font) end first = inject_kerns(first) -first = tonut(first) if getid(first) == whatsit_code then local temp = first first = getnext(first) @@ -753,7 +748,7 @@ function splitters.optimize(head) if trace_optimize then report_optimizers("preroll %a, variant %a, criterium %a, cache size %a",preroll,variant,criterium,nc) end - for current in traverse_ids(hlist_code,tonut(head)) do + for current in nexthlist, head do line = line + 1 local sign = getfield(current,"glue_sign") local dir = getdir(current) diff --git a/tex/context/base/mkiv/font-vfc.lua b/tex/context/base/mkiv/font-vfc.lua index cac225de6..3e48422d6 100644 --- a/tex/context/base/mkiv/font-vfc.lua +++ b/tex/context/base/mkiv/font-vfc.lua @@ -50,7 +50,8 @@ end -- todo: maybe indirect so that we can't change them local char = setmetatableindex(function(t,k) - local v = { "char", k } + -- local v = { "char", k } + local v = { "slot", 0, k } t[k] = v return v end) diff --git a/tex/context/base/mkiv/good-ctx.lua b/tex/context/base/mkiv/good-ctx.lua index 00e4ed78d..c4c632ae9 100644 --- a/tex/context/base/mkiv/good-ctx.lua +++ b/tex/context/base/mkiv/good-ctx.lua @@ -29,14 +29,13 @@ local registerotffeature = fonts.handlers.otf.features.register local fontgoodies = fonts.goodies or { } -local glyph_code = nodes.nodecodes.glyph - local nuts = nodes.nuts local tonut = nuts.tonut local getfont = nuts.getfont local getchar = nuts.getchar local getattr = nuts.getattr -local traverse_id = nuts.traverse_id + +local nextglyph = nuts.traversers.glyph -- colorschemes @@ -128,68 +127,9 @@ local function setcolorscheme(tfmdata,scheme) end local fontproperties = fonts.hashes.properties - local a_colorscheme = attributes.private('colorscheme') local setnodecolor = nodes.tracers.colors.set - --- function colorschemes.coloring(head) --- local lastfont, lastscheme --- local done = false --- for n in traverse_id(glyph_code,tonut(head)) do --- local a = getattr(n,a_colorscheme) --- if a then --- local f = getfont(n) --- if f ~= lastfont then --- lastscheme = fontproperties[f].colorscheme --- lastfont = f --- end --- if lastscheme then --- local sc = lastscheme[getchar(n)] --- if sc then --- done = true --- setnodecolor(n,"colorscheme:"..a..":"..sc) -- slow --- end --- end --- end --- end --- return head, done --- end - --- seldom used, mostly in manuals, so non critical .. anyhow, somewhat faster: - --- function colorschemes.coloring(head) --- local lastfont = nil --- local lastattr = nil --- local lastscheme = nil --- local lastprefix = nil --- local done = nil --- for n in traverse_id(glyph_code,tonut(head)) do --- local a = getattr(n,a_colorscheme) --- if a then --- if a ~= lastattr then --- lastattr = a --- lastprefix = "colorscheme:" .. a .. ":" --- end --- local f = getfont(n) --- if f ~= lastfont then --- lastfont = f --- lastscheme = fontproperties[f].colorscheme --- end --- if lastscheme then --- local sc = lastscheme[getchar(n)] --- if sc then --- setnodecolor(n,lastprefix .. sc) -- slow --- done = true --- end --- end --- end --- end --- return head, done --- end - --- ok, in case we have hundreds of pages colored: - -local cache = { } -- this could be a weak table +local cache = { } -- this could be a weak table setmetatableindex(cache,function(t,a) local v = { } @@ -207,8 +147,7 @@ function colorschemes.coloring(head) local lastattr = nil local lastcache = nil local lastscheme = nil - local done = nil - for n in traverse_id(glyph_code,tonut(head)) do + for n in nextglyph, head do local a = getattr(n,a_colorscheme) if a then local f = getfont(n) @@ -224,16 +163,46 @@ function colorschemes.coloring(head) local sc = lastscheme[getchar(n)] if sc then setnodecolor(n,lastcache[sc]) -- we could inline this one - done = true end end end end - return head, done + return head +end + +if LUATEXVERSION >= 1.090 then + + function colorschemes.coloring(head) + local lastfont = nil + local lastattr = nil + local lastcache = nil + local lastscheme = nil + for n, f, char in nextglyph, head do + local a = getattr(n,a_colorscheme) + if a then + if f ~= lastfont then + lastfont = f + lastscheme = fontproperties[f].colorscheme + end + if a ~= lastattr then + lastattr = a + lastcache = cache[a] + end + if lastscheme then + local sc = lastscheme[char] + if sc then + setnodecolor(n,lastcache[sc]) -- we could inline this one + end + end + end + end + return head + end + end function colorschemes.enable() - nodes.tasks.appendaction("processors","fonts","fonts.goodies.colorschemes.coloring") + nodes.tasks.enableaction("processors","fonts.goodies.colorschemes.coloring") function colorschemes.enable() end end diff --git a/tex/context/base/mkiv/grph-epd.lua b/tex/context/base/mkiv/grph-epd.lua index 7855ce891..ae0358b36 100644 --- a/tex/context/base/mkiv/grph-epd.lua +++ b/tex/context/base/mkiv/grph-epd.lua @@ -8,18 +8,18 @@ if not modules then modules = { } end modules ['grph-epd'] = { local variables = interfaces.variables local settings_to_hash = utilities.parsers.settings_to_hash +local codeinjections = backends.pdf.codeinjections --- todo: page, name, file, url +local trace = false trackers.register("figures.merging", function(v) trace = v end) --- I have some experimental code for including comments and fields but it's --- unfinished and not included as it was just a proof of concept to get some idea --- about what is needed and possible. But the placeholders are here already. - -local codeinjections = backends.codeinjections +local report = logs.reporter("backend","merging") local function mergegoodies(optionlist) local options = settings_to_hash(optionlist) local all = options[variables.all] or options[variables.yes] + if next(options) then + report("% t",table.sortedkeys(options)) + end if all or options[variables.reference] then codeinjections.mergereferences() end diff --git a/tex/context/base/mkiv/grph-inc.lua b/tex/context/base/mkiv/grph-inc.lua index f2d7847eb..87afb8683 100644 --- a/tex/context/base/mkiv/grph-inc.lua +++ b/tex/context/base/mkiv/grph-inc.lua @@ -1371,6 +1371,7 @@ function checkers.generic(data) local conversion = dr.conversion local resolution = dr.resolution local arguments = dr.arguments + local scanimage = dr.scanimage or scanimage if not conversion or conversion == "" then conversion = "default" end @@ -1471,6 +1472,8 @@ function includers.generic(data) -- width = dr.width, -- height = dr.height, -- } + local copyimage = dr.copyimage or copyimage + local cloneimage = dr.cloneimage or cloneimage if figure == nil then figure = ds.private if figure then @@ -2038,3 +2041,73 @@ implement { end end } + +-- This is an experiment. The following method uses Lua to handle the embedding +-- using the epdf library. This feature will be used when we make the transition +-- from the pre 1.10 epdf library (using an unsuported low level poppler api) to a +-- new (lightweight, small and statically compiled) library. More on that later. +-- +-- The method implemented below has the same performance as the hard coded inclusion +-- but opens up some possibilities (like merhing fonts) that I will look into some +-- day. + +local function pdf_checker(data) + local request = data.request + local used = data.used + if request and used and not request.scanimage then + local openpdf = lpdf.epdf.image.open + ----- closepdf = lpdf.epdf.image.close + local querypdf = lpdf.epdf.image.query + local copypage = lpdf.epdf.image.copy + request.scanimage = function(t) + local pdfdoc = openpdf(t.filename) + if pdfdoc then + used.pdfdoc = pdfdoc + -- nofpages + end + local info = querypdf(pdfdoc,request.page) + local bbox = info.boundingbox + return { + filename = filename, + -- page = 1, + pages = pdfdoc.nofpages, + width = bbox[3] - bbox[1], + height = bbox[4] - bbox[2], + depth = 0, + colordepth = 0, + xres = 0, + yres = 0, + xsize = 0, + ysize = 0, + rotation = 0, + orientation = 0, + } + end + request.copyimage = function(t) + return copypage(used.pdfdoc,request.page) + end + end + return checkers.generic(data) +end + +directives.register("graphics.pdf.uselua",function(v) + if v then + report("%s Lua based PDF inclusion","enabling") + checkers.pdf = pdf_checker + else + report("%s Lua based PDF inclusion","disabling") + checkers.pdf = nil + end +end) + +-- directives.enable("graphics.pdf.uselua") +-- +-- local filename = "luatex.pdf" +-- +-- for i=1,240 do +-- context(function() +-- context.startTEXpage() +-- context.externalfigure( { filename }, { page = i } ) +-- context.stopTEXpage() +-- end) +-- end diff --git a/tex/context/base/mkiv/grph-pat.lua b/tex/context/base/mkiv/grph-pat.lua index 89b29906d..1b5f1fd29 100644 --- a/tex/context/base/mkiv/grph-pat.lua +++ b/tex/context/base/mkiv/grph-pat.lua @@ -37,7 +37,7 @@ interfaces.implement { if not name or name == "" then return end - nodes.handlers.finalize(box,"object") + nodes.handlers.finalizebox(number) names[name] = lpdf.registerpattern { number = number, width = specification.width or box.width, diff --git a/tex/context/base/mkiv/l-table.lua b/tex/context/base/mkiv/l-table.lua index 788d1511f..04c318792 100644 --- a/tex/context/base/mkiv/l-table.lua +++ b/tex/context/base/mkiv/l-table.lua @@ -1239,13 +1239,20 @@ end local function sequenced(t,sep,simple) if not t then return "" + elseif type(t) == "string" then + return t -- handy fallback end local n = #t local s = { } if n > 0 then -- indexed for i=1,n do - s[i] = tostring(t[i]) + local v = t[i] + if type(v) == "table" then + s[i] = "{" .. sequenced(v,sep,simple) .. "}" + else + s[i] = tostring(t[i]) + end end else -- hashed diff --git a/tex/context/base/mkiv/lang-dis.lua b/tex/context/base/mkiv/lang-dis.lua index 65a53a702..1e46cbd36 100644 --- a/tex/context/base/mkiv/lang-dis.lua +++ b/tex/context/base/mkiv/lang-dis.lua @@ -17,9 +17,6 @@ local nuts = nodes.nuts local enableaction = tasks.enableaction local setaction = tasks.setaction -local tonode = nuts.tonode -local tonut = nuts.tonut - local setfield = nuts.setfield local getnext = nuts.getnext local getprev = nuts.getprev @@ -40,10 +37,11 @@ local isglyph = nuts.isglyph local copy_node = nuts.copy local remove_node = nuts.remove -local traverse_id = nuts.traverse_id local flush_list = nuts.flush_list local flush_node = nuts.flush_node +local nextdisc = nuts.traversers.disc + local new_disc = nuts.pool.disc local nodecodes = nodes.nodecodes @@ -69,7 +67,7 @@ local check_regular = true local setlistcolor = nodes.tracers.colors.setlist function languages.visualizediscretionaries(head) - for d in traverse_id(disc_code,tonut(head)) do + for d in nextdisc, head do if getattr(d,a_visualize) then local pre, post, replace = getdisc(d) if pre then @@ -83,6 +81,7 @@ function languages.visualizediscretionaries(head) end end end + return head end local enabled = false @@ -129,13 +128,9 @@ end local wiped = 0 -local flatten_discretionaries = node.flatten_discretionaries -- todo in nodes +local flatten_discretionaries = nuts.flatten_discretionaries -- todo in nodes -if flatten_discretionaries then - - -- This is not that much faster than the lua variant simply because there is - -- seldom a replace list but it fits in the picture. See luatex-todo.w for the - -- code. +-- if flatten_discretionaries then function languages.flatten(head) local h, n = flatten_discretionaries(head) @@ -143,45 +138,44 @@ if flatten_discretionaries then return h, n > 0 end -else - - local function wipe(head,delayed) - local p, n = getboth(delayed) - local _, _, h, _, _, t = getdisc(delayed,true) - if p or n then - if h then - setlink(p,h) - setlink(t,n) - setfield(delayed,"replace") - else - setlink(p,n) - end - end - if head == delayed then - head = h - end - wiped = wiped + 1 - flush_node(delayed) - return head - end - - function languages.flatten(head) - local nuthead = tonut(head) - local delayed = nil - for d in traverse_id(disc_code,nuthead) do - if delayed then - nuthead = wipe(nuthead,delayed) - end - delayed = d - end - if delayed then - return tonode(wipe(nuthead,delayed)), true - else - return head, false - end - end - -end +-- else +-- +-- local function wipe(head,delayed) +-- local p, n = getboth(delayed) +-- local _, _, h, _, _, t = getdisc(delayed,true) +-- if p or n then +-- if h then +-- setlink(p,h) +-- setlink(t,n) +-- setfield(delayed,"replace") +-- else +-- setlink(p,n) +-- end +-- end +-- if head == delayed then +-- head = h +-- end +-- wiped = wiped + 1 +-- flush_node(delayed) +-- return head +-- end +-- +-- function languages.flatten(head) +-- local delayed = nil +-- for d in nextdisc, head do +-- if delayed then +-- head = wipe(head,delayed) +-- end +-- delayed = d +-- end +-- if delayed then +-- return wipe(head,delayed), true +-- else +-- return head, false +-- end +-- end +-- +-- end function languages.nofflattened() return wiped -- handy for testing @@ -198,7 +192,7 @@ function nodes.handlers.flatten(head,where) if head and (where == "box" or where == "adjusted_hbox") then return flatten(head) end - return true + return head end directives.register("hyphenator.flatten",function(v) diff --git a/tex/context/base/mkiv/lang-exp.lua b/tex/context/base/mkiv/lang-exp.lua index 70fad48b0..e7543c4de 100644 --- a/tex/context/base/mkiv/lang-exp.lua +++ b/tex/context/base/mkiv/lang-exp.lua @@ -172,23 +172,23 @@ languages.expanders = expanders ----- expand_explicit = expanders and expanders[explicit_code] ----- expand_automatic = expanders and expanders[automatic_code] -if LUATEXVERSION < 1.005 then -- not loaded any more - - expanded = function(head) - local done = hyphenate(head) - if done then - for d in traverse_id(disc_code,tonut(head)) do - local s = getsubtype(d) - if s ~= discretionary_code then - expanders[s](d,template) - done = true - end - end - end - return head, done - end - -end +-- if LUATEXVERSION < 1.005 then -- not loaded any more +-- +-- expanded = function(head) +-- local done = hyphenate(head) +-- if done then +-- for d in traverse_id(disc_code,head) do +-- local s = getsubtype(d) +-- if s ~= discretionary_code then +-- expanders[s](d,template) +-- done = true +-- end +-- end +-- end +-- return head, done +-- end +-- +-- end -- if id == disc_code then -- if expanded then diff --git a/tex/context/base/mkiv/lang-hyp.lua b/tex/context/base/mkiv/lang-hyp.lua index e29446b65..d01f8b581 100644 --- a/tex/context/base/mkiv/lang-hyp.lua +++ b/tex/context/base/mkiv/lang-hyp.lua @@ -632,7 +632,6 @@ if context then local regular_code = disccodes.regular local nuts = nodes.nuts - local tonut = nodes.tonut local tonode = nodes.tonode local nodepool = nuts.pool @@ -666,7 +665,9 @@ if context then local remove_node = nuts.remove local end_of_math = nuts.end_of_math local node_tail = nuts.tail - local traverse_id = nuts.traverse_id + + local nexthlist = nuts.traversers.hlist + local nextdisc = nuts.traversers.disc local setcolor = nodes.tracers.colors.set @@ -1028,9 +1029,7 @@ featureset.hyphenonly = hyphenonly == v_yes function traditional.hyphenate(head) - local first = tonut(head) - - + local first = head local tail = nil local last = nil local current = first @@ -1585,7 +1584,7 @@ featureset.hyphenonly = hyphenonly == v_yes stoptiming(traditional) - return head, true + return head end statistics.register("hyphenation",function() @@ -1619,8 +1618,8 @@ featureset.hyphenonly = hyphenonly == v_yes local stack = { } local function original(head) - local done = hyphenate(head) - return head, done + hyphenate(tonode(head)) + return head end local getcount = tex.getcount @@ -1637,13 +1636,13 @@ featureset.hyphenonly = hyphenonly == v_yes forced = false return usedmethod(head) else - return head, false + return head end else return usedmethod(head) end else - return head, false + return head end end @@ -1729,13 +1728,12 @@ featureset.hyphenonly = hyphenonly == v_yes } function nodes.stripdiscretionaries(head) - local h = tonut(head) - for l in traverse_id(hlist_code,h) do - for d in traverse_id(disc_code,getlist(l)) do + for l in nexthlist, head do + for d in nextdisc, getlist(l) do remove_node(h,false,true) end end - return tonode(h) + return head end diff --git a/tex/context/base/mkiv/lang-mis.mkiv b/tex/context/base/mkiv/lang-mis.mkiv index eb7dc7d80..17149b37a 100644 --- a/tex/context/base/mkiv/lang-mis.mkiv +++ b/tex/context/base/mkiv/lang-mis.mkiv @@ -202,8 +202,8 @@ \setnewconstant\discretionarymode\plusone -\unexpanded\def\ignorediscretionaries - {\discretionarymode\zerocount} +\unexpanded\def\ignorediscretionaries{\discretionarymode\zerocount} +\unexpanded\def\obeydiscretionaries {\discretionarymode\plusone} \def\lang_discretionaries_command {% if direct if, we need \relax for lookahead in math mode diff --git a/tex/context/base/mkiv/lang-rep.lua b/tex/context/base/mkiv/lang-rep.lua index a5c4d97c8..93509d82a 100644 --- a/tex/context/base/mkiv/lang-rep.lua +++ b/tex/context/base/mkiv/lang-rep.lua @@ -42,8 +42,6 @@ local report_replacement = logs.reporter("languages","replacements") local glyph_code = nodes.nodecodes.glyph local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev @@ -217,9 +215,7 @@ local function tonodes(list,template) end function replacements.handler(head) - head = tonut(head) local current = head - local done = false local overload = attributes.applyoverloads while current do if getid(current) == glyph_code then @@ -327,14 +323,13 @@ function replacements.handler(head) if overload then overload(final,getnext(precurrent),getprev(current)) end - done = true end end end -- we're one ahead now but we need to because we handle words current = getnext(current) end - return tonode(head), done + return head end local enabled = false diff --git a/tex/context/base/mkiv/lang-url.lua b/tex/context/base/mkiv/lang-url.lua index 95d959206..17ad15cd8 100644 --- a/tex/context/base/mkiv/lang-url.lua +++ b/tex/context/base/mkiv/lang-url.lua @@ -8,7 +8,6 @@ if not modules then modules = { } end modules ['lang-url'] = { local utfcharacters, utfvalues, utfbyte, utfchar = utf.characters, utf.values, utf.byte, utf.char local min, max = math.min, math.max -local concat = table.concat local context = context @@ -77,9 +76,10 @@ urls.righthyphenmin = 3 urls.discretionary = nil urls.packslashes = false -directives.register("hyphenators.urls.packslashes",function(v) - urls.packslashes = v -end) +directives.register("hyphenators.urls.packslashes",function(v) urls.packslashes = v end) + +local trace = false trackers.register("hyphenators.urls",function(v) trace = v end) +local report = logs.reporter("hyphenators","urls") -- local ctx_a = context.a -- local ctx_b = context.b @@ -153,8 +153,10 @@ local function action(hyphenatedurl,str,left,right,disc) local pack = urls.packslashes local length = 0 local list = utf.split(str) + local size = #list + local prev = nil - for i=1,#list do + for i=1,size do local what = nil local dodi = false local char = list[i] @@ -162,7 +164,7 @@ local function action(hyphenatedurl,str,left,right,disc) char = mapping[char] or char if char == disc then dodi = true - elseif pack and char == "/" and list[i+1] == "/" then + elseif pack and char == "/" and (list[i+1] == "/" or prev == "/") then what = "c" else local how = characters[char] @@ -192,9 +194,13 @@ local function action(hyphenatedurl,str,left,right,disc) else list[i] = "\\" .. what .. "{" .. utfbyte(char) .. "}" end + prev = char + end + if trace then + report("old : %s",str) + report("new : %t",list) end - list = concat(list) - context(list) + context("%t",list) end -- urls.action = function(_,...) action(...) end -- sort of obsolete diff --git a/tex/context/base/mkiv/lang-wrd.lua b/tex/context/base/mkiv/lang-wrd.lua index 7363dbb31..9fbced2ce 100644 --- a/tex/context/base/mkiv/lang-wrd.lua +++ b/tex/context/base/mkiv/lang-wrd.lua @@ -31,7 +31,6 @@ local numbers = languages.numbers local registered = languages.registered local nuts = nodes.nuts -local tonut = nuts.tonut ----- getfield = nuts.getfield local getnext = nuts.getnext @@ -43,8 +42,8 @@ local setattr = nuts.setattr local getlang = nuts.getlang local ischar = nuts.ischar -local traverse_nodes = nuts.traverse ------ traverse_ids = nuts.traverse_id +local nextnode = nuts.traversers.node +----- nextglyph = nuts.traversers.glyph local wordsdata = words.data local chardata = characters.data @@ -145,14 +144,13 @@ end -- there is an n=1 problem somewhere in nested boxes local function mark_words(head,whenfound) -- can be optimized and shared - local current, language, done = tonut(head), nil, nil, 0, false + local current, language = head, nil, nil, 0 local str, s, nds, n = { }, 0, { }, 0 -- n could also be a table, saves calls local function action() if s > 0 then local word = concat(str,"",1,s) local mark = whenfound(language,word) if mark then - done = true for i=1,n do mark(nds[i]) end @@ -198,7 +196,7 @@ local function mark_words(head,whenfound) -- can be optimized and shared -- n = n + 1 -- nds[n] = current -- -- - -- for current in traverse_ids(glyph_code,r) do + -- for current in nextglyph, r do -- local code = getchar(current) -- n = n + 1 -- nds[n] = current @@ -217,7 +215,7 @@ local function mark_words(head,whenfound) -- can be optimized and shared if s > 0 then action() end - return head, done + return head end local methods = { } @@ -285,7 +283,7 @@ local function sweep(language,str) end methods[1] = function(head) - for n in traverse_nodes(head) do + for n in nextnode, head do setattr(n,a_color,unsetvalue) -- hm, not that selective (reset color) end return mark_words(head,sweep) @@ -380,7 +378,7 @@ local function sweep(language,str) end methods[3] = function(head) - for n in traverse_nodes(head) do + for n in nextnode, head do setattr(n,a_color,unsetvalue) end return mark_words(head,sweep) diff --git a/tex/context/base/mkiv/lpdf-ano.lua b/tex/context/base/mkiv/lpdf-ano.lua index 3a86b22ca..9fdb0913c 100644 --- a/tex/context/base/mkiv/lpdf-ano.lua +++ b/tex/context/base/mkiv/lpdf-ano.lua @@ -253,6 +253,9 @@ end) local function pdfnametree(destinations) local slices = { } checkautoprefixes(destinations) + if not next(destinations) then + return + end local sorted = table.sortedkeys(destinations) local size = #sorted @@ -285,18 +288,22 @@ local function pdfnametree(destinations) } end local function collectkids(slices,first,last) - local k = pdfarray() - local d = pdfdictionary { - Kids = k, - Limits = pdfarray { - slices[first].limits[1], - slices[last ].limits[2], - }, - } - for i=first,last do - k[#k+1] = slices[i].reference + local f = slices[first] + local l = slices[last] + if f and l then + local k = pdfarray() + local d = pdfdictionary { + Kids = k, + Limits = pdfarray { + f.limits[1], + l.limits[2], + }, + } + for i=first,last do + k[#k+1] = slices[i].reference + end + return d end - return d end if #slices == 1 then return slices[1].reference @@ -307,14 +314,24 @@ local function pdfnametree(destinations) local size = #slices for i=1,size,maxslice do local kids = collectkids(slices,i,min(i+maxslice-1,size)) - temp[#temp+1] = { - reference = pdfreference(pdfflushobject(kids)), - limits = kids.Limits, - } + if kids then + temp[#temp+1] = { + reference = pdfreference(pdfflushobject(kids)), + limits = kids.Limits, + } + else + -- error + end end slices = temp else - return pdfreference(pdfflushobject(collectkids(slices,1,#slices))) + local kids = collectkids(slices,1,#slices) + if kids then + return pdfreference(pdfflushobject(kids)) + else + -- error + return + end end end end @@ -323,7 +340,9 @@ end local function pdfdestinationspecification() if next(destinations) then -- safeguard local r = pdfnametree(destinations) - pdfaddtonames("Dests",r) + if r then + pdfaddtonames("Dests",r) + end if not log_destinations then destinations = nil end @@ -786,7 +805,9 @@ pdfregisterannotation = lpdf.registerannotation function lpdf.annotationspecification() if annotations then local r = pdfdelayedobject(tostring(annotations)) -- delayed so okay in latelua - pdfaddtopageattributes("Annots",pdfreference(r)) + if r then + pdfaddtopageattributes("Annots",pdfreference(r)) + end annotations = nil end end @@ -1179,11 +1200,12 @@ local function build(levels,start,parent,method,nested) local variant = "unknown" if reftype == "table" then -- we're okay - variant = "list" - block = reference.block + variant = "list" + block = reference.block + realpage = reference.realpage elseif reftype == "string" then local resolved = references.identify("",reference) - local realpage = resolved and structures.references.setreferencerealpage(resolved) or 0 + realpage = resolved and structures.references.setreferencerealpage(resolved) or 0 if realpage > 0 then variant = "realpage" realpage = realpage @@ -1284,7 +1306,6 @@ end function codeinjections.addbookmarks(levels,method) if levels and #levels > 0 then --- inspect(levels) local parent = pdfreserveobject() local _, m, first, last = build(levels,1,pdfreference(parent),method or "internal",false) local dict = pdfdictionary { diff --git a/tex/context/base/mkiv/lpdf-epa.lua b/tex/context/base/mkiv/lpdf-epa.lua index 89b2c6e0e..ee3b6d43d 100644 --- a/tex/context/base/mkiv/lpdf-epa.lua +++ b/tex/context/base/mkiv/lpdf-epa.lua @@ -6,47 +6,72 @@ if not modules then modules = { } end modules ['lpdf-epa'] = { license = "see context related readme files" } --- This is a rather experimental feature and the code will probably change. +-- Links can also have quadpoint -local type, tonumber = type, tonumber -local format, gsub, lower = string.format, string.gsub, string.lower +local type, tonumber, next = type, tonumber, next +local format, gsub, lower, find = string.format, string.gsub, string.lower, string.find local formatters = string.formatters +local concat, merged = table.concat, table.merged local abs = math.abs local expandname = file.expandname local allocate = utilities.storage.allocate +local bor, band = bit32.bor, bit32.band local isfile = lfs.isfile ------ lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns +local trace_links = false trackers.register("figures.links", function(v) trace_links = v end) +local trace_comments = false trackers.register("figures.comments", function(v) trace_comments = v end) +local trace_fields = false trackers.register("figures.fields", function(v) trace_fields = v end) +local trace_outlines = false trackers.register("figures.outlines", function(v) trace_outlines = v end) -local trace_links = false trackers.register("figures.links", function(v) trace_links = v end) -local trace_outlines = false trackers.register("figures.outliness", function(v) trace_outlines = v end) +local report_link = logs.reporter("backend","link") +local report_comment = logs.reporter("backend","comment") +local report_field = logs.reporter("backend","field") +local report_outline = logs.reporter("backend","outline") -local report_link = logs.reporter("backend","link") -local report_comment = logs.reporter("backend","comment") -local report_field = logs.reporter("backend","field") -local report_outline = logs.reporter("backend","outline") +local nodeinjections = backends.pdf.nodeinjections -local epdf = epdf -local backends = backends -local lpdf = lpdf -local context = context +local pdfarray = lpdf.array +local pdfdictionary = lpdf.dictionary +local pdfconstant = lpdf.constant +local pdfreserveobject = lpdf.reserveobject +local pdfreference = lpdf.reference -local loadpdffile = lpdf.epdf.load +local pdfcopyboolean = lpdf.copyboolean +local pdfcopyunicode = lpdf.copyunicode +local pdfcopyarray = lpdf.copyarray +local pdfcopydictionary = lpdf.copydictionary +local pdfcopynumber = lpdf.copynumber +local pdfcopyinteger = lpdf.copyinteger +local pdfcopystring = lpdf.copystring +local pdfcopyconstant = lpdf.copyconstant -local nameonly = file.nameonly +local pdfgetpos = lpdf.getpos -local variables = interfaces.variables -local codeinjections = backends.pdf.codeinjections ------ urlescaper = lpegpatterns.urlescaper ------ utftohigh = lpegpatterns.utftohigh -local escapetex = characters.filters.utf.private.escape +local hpack_node = nodes.hpack -local bookmarks = structures.bookmarks +local epdf = epdf +local backends = backends +local lpdf = lpdf +local context = context -local maxdimen = 0x3FFFFFFF -- 2^30-1 +local loadpdffile = lpdf.epdf.load + +local nameonly = file.nameonly + +local variables = interfaces.variables +local codeinjections = backends.pdf.codeinjections +----- urlescaper = lpegpatterns.urlescaper +----- utftohigh = lpegpatterns.utftohigh +local escapetex = characters.filters.utf.private.escape + +local bookmarks = structures.bookmarks + +local maxdimen = 0x3FFFFFFF -- 2^30-1 + +local bpfactor = number.dimenfactors.bp local layerspec = { -- predefining saves time - "epdflinks" + "epdfcontent" } local collected = allocate() @@ -66,6 +91,68 @@ end job.register('job.embedded.collected',tobesaved,initializer) +local function validdocument(specification) + if figures and not specification then + specification = figures and figures.current() + specification = specification and specification.status + end + if specification then + local fullname = specification.fullname + local expanded = lower(expandname(fullname)) + -- we could add a check for duplicate page insertion + tobesaved[expanded] = true + --- but that is messy anyway so we forget about it + return specification, fullname, loadpdffile(fullname) -- costs time + end +end + +local function getmediasize(specification,pagedata) + local xscale = specification.xscale or 1 + local yscale = specification.yscale or 1 + ----- size = specification.size or "crop" -- todo + local mediabox = pagedata.MediaBox + local llx = mediabox[1] + local lly = mediabox[2] + local urx = mediabox[3] + local ury = mediabox[4] + local width = xscale * (urx - llx) -- \\overlaywidth, \\overlayheight + local height = yscale * (ury - lly) -- \\overlaywidth, \\overlayheight + return llx, lly, urx, ury, width, height, xscale, yscale +end + +local function getdimensions(annotation,llx,lly,xscale,yscale,width,height,report) + local rectangle = annotation.Rect + local a_llx = rectangle[1] + local a_lly = rectangle[2] + local a_urx = rectangle[3] + local a_ury = rectangle[4] + local x = xscale * (a_llx - llx) + local y = yscale * (a_lly - lly) + local w = xscale * (a_urx - a_llx) + local h = yscale * (a_ury - a_lly) + if w > width or h > height or w < 0 or h < 0 or abs(x) > (maxdimen/2) or abs(y) > (maxdimen/2) then + report("broken rectangle [%.6F %.6F %.6F %.6F] (max: %.6F)",a_llx,a_lly,a_urx,a_ury,maxdimen/2) + return + end + return x, y, w, h, a_llx, a_lly, a_urx, a_ury +end + +local layerused = false + +local function initializelayer(height,width) + if not layerused then + context.definelayer(layerspec, { height = height .. "bp", width = width .. "bp" }) + layerused = true + end +end + +function codeinjections.flushmergelayer() + if layerused then + context.flushlayer(layerspec) + layerused = false + end +end + local f_namespace = formatters["lpdf-epa-%s-"] local function makenamespace(filename) @@ -182,79 +269,48 @@ local function link_file(x,y,w,h,document,annotation) end end +-- maybe handler per subtype and then one loop but then what about order ... + function codeinjections.mergereferences(specification) - if figures and not specification then - specification = figures and figures.current() - specification = specification and specification.status - end - if not specification then - return "" - end - local fullname = specification.fullname - local expanded = lower(expandname(fullname)) - -- we could add a check for duplicate page insertion - tobesaved[expanded] = true - --- but that is messy anyway so we forget about it - local document = loadpdffile(fullname) -- costs time + local specification, fullname, document = validdocument(specification) if not document then return "" end - local pagenumber = specification.page or 1 - local xscale = specification.yscale or 1 - local yscale = specification.yscale or 1 - local size = specification.size or "crop" -- todo + local pagenumber = specification.page or 1 local pagedata = document.pages[pagenumber] local annotations = pagedata and pagedata.Annots local namespace = makenamespace(fullname) local reference = namespace .. pagenumber if annotations and annotations.n > 0 then - local mediabox = pagedata.MediaBox - local llx = mediabox[1] - local lly = mediabox[2] - local urx = mediabox[3] - local ury = mediabox[4] - local width = xscale * (urx - llx) -- \\overlaywidth, \\overlayheight - local height = yscale * (ury - lly) -- \\overlaywidth, \\overlayheight - context.definelayer( { "epdflinks" }, { height = height.."bp" , width = width.."bp" }) + local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale) + initializelayer(height,width) for i=1,annotations.n do local annotation = annotations[i] if annotation then - local subtype = annotation.Subtype - local rectangle = annotation.Rect - local a_llx = rectangle[1] - local a_lly = rectangle[2] - local a_urx = rectangle[3] - local a_ury = rectangle[4] - local x = xscale * (a_llx - llx) - local y = yscale * (a_lly - lly) - local w = xscale * (a_urx - a_llx) - local h = yscale * (a_ury - a_lly) - if subtype == "Link" then + if annotation.Subtype == "Link" then local a = annotation.A if not a then report_link("missing link annotation") - elseif w > width or h > height or w < 0 or h < 0 or abs(x) > (maxdimen/2) or abs(y) > (maxdimen/2) then - report_link("broken link rectangle [%.6F %.6F %.6F %.6F] (max: %.6F)",a_llx,a_lly,a_urx,a_ury,maxdimen/2) else - local linktype = a.S - if linktype == "GoTo" then - link_goto(x,y,w,h,document,annotation,pagedata,namespace) - elseif linktype == "GoToR" then - link_file(x,y,w,h,document,annotation) - elseif linktype == "URI" then - link_uri(x,y,w,h,document,annotation) - elseif trace_links then - report_link("unsupported link annotation %a",linktype) + local x, y, w, h = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_link) + if x then + local linktype = a.S + if linktype == "GoTo" then + link_goto(x,y,w,h,document,annotation,pagedata,namespace) + elseif linktype == "GoToR" then + link_file(x,y,w,h,document,annotation) + elseif linktype == "URI" then + link_uri(x,y,w,h,document,annotation) + elseif trace_links then + report_link("unsupported link annotation %a",linktype) + end end end - elseif trace_links then - report_link("unsupported annotation %a",subtype) end elseif trace_links then report_link("broken annotation, index %a",i) end end - context.flushlayer { "epdflinks" } end -- moved outside previous test context.setgvalue("figurereference",reference) -- global @@ -270,43 +326,520 @@ function codeinjections.mergeviewerlayers(specification) if true then return end - if not specification then - specification = figures and figures.current() - specification = specification and specification.status + local specification, fullname, document = validdocument(specification) + if not document then + return "" end - if specification then - local fullname = specification.fullname - local document = loadpdffile(fullname) - if document then - local namespace = makenamespace(fullname) - local layers = document.layers - if layers then - for i=1,layers.n do - local layer = layers[i] - if layer then - local tag = namespace .. gsub(layer," ",":") - local title = tag - if trace_links then - report_link("using layer %a",tag) - end - attributes.viewerlayers.define { -- also does some cleaning - tag = tag, -- todo: #3A or so - title = title, - visible = variables.start, - editable = variables.yes, - printable = variables.yes, - } - codeinjections.useviewerlayer(tag) - elseif trace_links then - report_link("broken layer, index %a",i) - end + local namespace = makenamespace(fullname) + local layers = document.layers + if layers then + for i=1,layers.n do + local layer = layers[i] + if layer then + local tag = namespace .. gsub(layer," ",":") + local title = tag + if trace_links then + report_link("using layer %a",tag) end + attributes.viewerlayers.define { -- also does some cleaning + tag = tag, -- todo: #3A or so + title = title, + visible = variables.start, + editable = variables.yes, + printable = variables.yes, + } + codeinjections.useviewerlayer(tag) + elseif trace_links then + report_link("broken layer, index %a",i) end end end end --- new: for taco +-- It took a bit of puzzling and playing around to come to the following +-- implementation. In the end it looks simple but as usual it takes a while +-- to see what the specification (and implementation) boils down to. Lots of +-- shared properties and such. The scaling took some trial and error as +-- viewers differ. I had to extend some low level helpers to make it more +-- comfortable. Hm, the specification is somewhat incomplete as some fields +-- are permitted even if not mentioned so in the end we can share more code. +-- +-- If all works ok, we can get rid of some copies which saves time and space. + +local commentlike = { + Text = "text", + FreeText = "freetext", + Line = "line", + Square = "shape", + Circle = "shape", + Polygon = "poly", + PolyLine = "poly", + Highlight = "markup", + Underline = "markup", + Squiggly = "markup", + StrikeOut = "markup", + Caret = "text", + Stamp = "stamp", + Ink = "ink", + Popup = "popup", +} + +local function copyBS(v) -- dict can be shared + if v then + -- return pdfdictionary { + -- Type = copypdfconstant(V.Type), + -- W = copypdfnumber (V.W), + -- S = copypdfstring (V.S), + -- D = copypdfarray (V.D), + -- } + return copypdfdictionary(v) + end +end + +local function copyBE(v) -- dict can be shared + if v then + -- return pdfdictionary { + -- S = copypdfstring(V.S), + -- I = copypdfnumber(V.I), + -- } + return copypdfdictionary(v) + end +end + +local function copyBorder(v) -- dict can be shared + if v then + -- todo + return copypdfarray(v) + end +end + +local function copyPopup(v,references) + if v then + local p = references[v] + if p then + return pdfreference(p) + end + end +end + +local function copyParent(v,references) + if v then + local p = references[v] + if p then + return pdfreference(p) + end + end +end + +local function copyIRT(v,references) + if v then + local p = references[v] + if p then + return pdfreference(p) + end + end +end + +local function copyC(v) + if v then + -- todo: check color space + return pdfcopyarray(v) + end +end + +local function finalizer(d,xscale,yscale,a_llx,a_ury) + local q = d.QuadPoints or d.Vertices or d.CL + if q then + return function() + local h, v = pdfgetpos() -- already scaled + for i=1,#q,2 do + q[i] = xscale * q[i] + (h*bpfactor - xscale * a_llx) + q[i+1] = yscale * q[i+1] + (v*bpfactor - yscale * a_ury) + end + return d() + end + end + q = d.InkList or d.Path + if q then + return function() + local h, v = pdfgetpos() -- already scaled + for i=1,#q do + local q = q[i] + for i=1,#q,2 do + q[i] = xscale * q[i] + (h*bpfactor - xscale * a_llx) + q[i+1] = yscale * q[i+1] + (v*bpfactor - yscale * a_ury) + end + end + return d() + end + end + return d() +end + +local validstamps = { + Approved = true, + Experimental = true, + NotApproved = true, + AsIs = true, + Expired = true, + NotForPublicRelease = true, + Confidential = true, + Final = true, + Sold = true, + Departmental = true, + ForComment = true, + TopSecret = true, + Draft = true, + ForPublicRelease = true, +} + +local function validStamp(v) + local name = "Stamped" -- fallback + if v then + local ok = validstamps[v] + if ok then + name = ok + else + for k in next, validstamps do + if find(v,k.."$") then + name = k + validstamps[v] = k + break + end + end + end + end + -- we temporary return to \TEX: + context.predefinesymbol { name } + context.step() + -- beware, an error is not reported + return pdfconstant(name), codeinjections.analyzenormalsymbol(name) +end + +local annotationflags = lpdf.flags.annotations + +local function copyF(v,lock) -- todo: bxor 24 + if lock then + v = bor(v or 0,annotationflags.ReadOnly + annotationflags.Locked + annotationflags.LockedContents) + end + if v then + return pdfcopyinteger(v) + end +end + +-- Speed is not really an issue so we don't optimize this code too much. In the end (after +-- testing we end up with less code that we started with. + +function codeinjections.mergecomments(specification) + -- local specification, fullname, document = validdocument(specification) + -- if not document then + -- return "" + -- end + -- local pagenumber = specification.page or 1 + -- local pagedata = document.pages[pagenumber] + -- local annotations = pagedata and pagedata.Annots + -- if annotations and annotations.n > 0 then + -- local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale) + -- initializelayer(height,width) + -- -- + -- local lockflags = specification.lock -- todo: proper parameter + -- local references = { } + -- local usedpopups = { } + -- for i=1,annotations.n do + -- local annotation = annotations[i] + -- if annotation then + -- local subtype = annotation.Subtype + -- if commentlike[subtype] then + -- references[annotation] = pdfreserveobject() + -- local p = annotation.Popup + -- if p then + -- usedpopups[p] = true + -- end + -- end + -- end + -- end + -- -- + -- for i=1,annotations.n do + -- -- we keep the order + -- local annotation = annotations[i] + -- if annotation then + -- local reference = references[annotation] + -- if reference then + -- local subtype = annotation.Subtype + -- local kind = commentlike[subtype] + -- if kind ~= "popup" or usedpopups[annotation] then + -- local x, y, w, h, a_llx, a_lly, a_urx, a_ury = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_comment) + -- if x then + -- local voffset = h + -- local dictionary = pdfdictionary { + -- Subtype = pdfconstant (subtype), + -- -- common (skipped: P AP AS OC AF BM StructParent) + -- Contents = pdfcopyunicode(annotation.Contents), + -- NM = pdfcopystring (annotation.NM), + -- M = pdfcopystring (annotation.M), + -- F = copyF (annotation.F,lockflags), + -- C = copyC (annotation.C), + -- ca = pdfcopynumber (annotation.ca), + -- CA = pdfcopynumber (annotation.CA), + -- Lang = pdfcopystring (annotation.Lang), + -- -- also common + -- CreationDate = pdfcopystring (annotation.CreationDate), + -- T = pdfcopyunicode(annotation.T), + -- Subj = pdfcopyunicode(annotation.Subj), + -- -- border + -- Border = pdfcopyarray (annotation.Border), + -- BS = copyBS (annotation.BS), + -- BE = copyBE (annotation.BE), + -- -- sort of common + -- Popup = copyPopup (annotation.Popup,references), + -- RC = pdfcopyunicode(annotation.RC) -- string or stream + -- } + -- if kind == "markup" then + -- dictionary.IRT = copyIRT (annotation.IRT,references) + -- dictionary.RT = pdfconstant (annotation.RT) + -- dictionary.IT = pdfcopyconstant (annotation.IT) + -- dictionary.QuadPoints = pdfcopyarray (annotation.QuadPoints) + -- -- dictionary.RD = pdfcopyarray (annotation.RD) + -- elseif kind == "text" then + -- -- somehow F fails to view : /F 24 : bit4=nozoom bit5=norotate + -- dictionary.F = nil + -- dictionary.Open = pdfcopyboolean (annotation.Open) + -- dictionary.Name = pdfcopyunicode (annotation.Name) + -- dictionary.State = pdfcopystring (annotation.State) + -- dictionary.StateModel = pdfcopystring (annotation.StateModel) + -- dictionary.IT = pdfcopyconstant (annotation.IT) + -- dictionary.QuadPoints = pdfcopyarray (annotation.QuadPoints) + -- dictionary.RD = pdfcopyarray (annotation.RD) -- caret + -- dictionary.Sy = pdfcopyconstant (annotation.Sy) -- caret + -- voffset = 0 + -- elseif kind == "freetext" then + -- dictionary.DA = pdfcopystring (annotation.DA) + -- dictionary.Q = pdfcopyinteger (annotation.Q) + -- dictionary.DS = pdfcopystring (annotation.DS) + -- dictionary.CL = pdfcopyarray (annotation.CL) + -- dictionary.IT = pdfcopyconstant (annotation.IT) + -- dictionary.LE = pdfcopyconstant (annotation.LE) + -- -- dictionary.RC = pdfcopystring (annotation.RC) + -- elseif kind == "line" then + -- dictionary.LE = pdfcopyarray (annotation.LE) + -- dictionary.IC = pdfcopyarray (annotation.IC) + -- dictionary.LL = pdfcopynumber (annotation.LL) + -- dictionary.LLE = pdfcopynumber (annotation.LLE) + -- dictionary.Cap = pdfcopyboolean (annotation.Cap) + -- dictionary.IT = pdfcopyconstant (annotation.IT) + -- dictionary.LLO = pdfcopynumber (annotation.LLO) + -- dictionary.CP = pdfcopyconstant (annotation.CP) + -- dictionary.Measure = pdfcopydictionary(annotation.Measure) -- names + -- dictionary.CO = pdfcopyarray (annotation.CO) + -- voffset = 0 + -- elseif kind == "shape" then + -- dictionary.IC = pdfcopyarray (annotation.IC) + -- -- dictionary.RD = pdfcopyarray (annotation.RD) + -- voffset = 0 + -- elseif kind == "stamp" then + -- local name, appearance = validStamp(annotation.Name) + -- dictionary.Name = name + -- dictionary.AP = appearance + -- voffset = 0 + -- elseif kind == "ink" then + -- dictionary.InkList = pdfcopyarray (annotation.InkList) + -- elseif kind == "poly" then + -- dictionary.Vertices = pdfcopyarray (annotation.Vertices) + -- -- dictionary.LE = pdfcopyarray (annotation.LE) -- todo: names in array + -- dictionary.IC = pdfcopyarray (annotation.IC) + -- dictionary.IT = pdfcopyconstant (annotation.IT) + -- dictionary.Measure = pdfcopydictionary(annotation.Measure) + -- dictionary.Path = pdfcopyarray (annotation.Path) + -- -- dictionary.RD = pdfcopyarray (annotation.RD) + -- elseif kind == "popup" then + -- dictionary.Open = pdfcopyboolean (annotation.Open) + -- dictionary.Parent = copyParent (annotation.Parent,references) + -- voffset = 0 + -- end + -- if dictionary then + -- local locationspec = { + -- x = x .. "bp", + -- y = y .. "bp", + -- voffset = voffset .. "bp", + -- preset = "leftbottom", + -- } + -- local finalize = finalizer(dictionary,xscale,yscale,a_llx,a_ury) + -- context.setlayer(layerspec,locationspec,function() + -- context(hpack_node(nodeinjections.annotation(w/bpfactor,h/bpfactor,0,finalize,reference))) + -- end) + -- end + -- end + -- else + -- -- report_comment("skipping annotation, index %a",i) + -- end + -- end + -- elseif trace_comments then + -- report_comment("broken annotation, index %a",i) + -- end + -- end + -- end + -- return namespace +end + +local widgetflags = lpdf.flags.widgets + +local function flagstoset(flag,flags) + local t = { } + if flags then + for k, v in next, flags do + if band(flag,v) ~= 0 then + t[k] = true + end + end + end + return t +end + +-- BS : border style dict +-- R : rotation 0 90 180 270 +-- BG : background array +-- CA : caption string +-- RC : roll over caption +-- AC : down caption +-- I/RI/IX : icon streams +-- IF : fit dictionary +-- TP : text position number + +-- Opt : array of texts +-- TI : top index + +-- V : value +-- DV : default value +-- DS : default string +-- RV : rich +-- Q : quadding (0=left 1=middle 2=right) + +function codeinjections.mergefields(specification) + -- local specification, fullname, document = validdocument(specification) + -- if not document then + -- return "" + -- end + -- local pagenumber = specification.page or 1 + -- local pagedata = document.pages[pagenumber] + -- local annotations = pagedata and pagedata.Annots + -- if annotations and annotations.n > 0 then + -- local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale) + -- initializelayer(height,width) + -- -- + -- for i=1,annotations.n do + -- -- we keep the order + -- local annotation = annotations[i] + -- if annotation then + -- local subtype = annotation.Subtype + -- if subtype == "Widget" then + -- local parent = annotation.Parent or { } + -- local name = annotation.T or parent.T + -- local what = annotation.FT or parent.FT + -- if name and what then + -- local x, y, w, h, a_llx, a_lly, a_urx, a_ury = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_field) + -- if x then + -- x = x .. "bp" + -- y = y .. "bp" + -- local W, H = w, h + -- w = w .. "bp" + -- h = h .. "bp" + -- if trace_fields then + -- report_field("field %a, type %a, dx %s, dy %s, wd %s, ht %s",name,what,x,y,w,h) + -- end + -- local locationspec = { + -- x = x, + -- y = y, + -- preset = "leftbottom", + -- } + -- -- + -- local aflags = flagstoset(annotation.F or parent.F, annotationflags) + -- local wflags = flagstoset(annotation.Ff or parent.Ff, widgetflags) + -- if what == "Tx" then + -- -- DA DV F FT MaxLen MK Q T V | AA OC + -- if wflags.MultiLine then + -- wflags.MultiLine = nil + -- what = "text" + -- else + -- what = "line" + -- end + -- -- via context + -- local fieldspec = { + -- width = w, + -- height = h, + -- offset = variables.overlay, + -- frame = trace_links and variables.on or variables.off, + -- n = annotation.MaxLen or (parent and parent.MaxLen), + -- type = what, + -- option = concat(merged(aflags,wflags),","), + -- } + -- context.setlayer (layerspec,locationspec,function() + -- context.definefieldbody ( { name } , fieldspec ) + -- context.fieldbody ( { name } ) + -- end) + -- -- + -- elseif what == "Btn" then + -- if wflags.Radio or wflags.RadiosInUnison then + -- -- AP AS DA F Ff FT H MK T V | AA OC + -- wflags.Radio = nil + -- wflags.RadiosInUnison = nil + -- what = "radio" + -- elseif wflags.PushButton then + -- -- AP DA F Ff FT H MK T | AA OC + -- -- + -- -- Push buttons only have an appearance and some associated + -- -- actions so they are not worth copying. + -- -- + -- wflags.PushButton = nil + -- what = "push" + -- else + -- -- AP AS DA F Ff FT H MK T V | OC AA + -- what = "check" + -- -- direct + -- local AP = annotation.AP or (parent and parent.AP) + -- if AP then + -- local im = img.new { filename = fullname } + -- AP = img.immediatewriteobject(im,document.__xrefs__[AP]) + -- end + -- local dictionary = pdfdictionary { + -- Subtype = pdfconstant("Widget"), + -- FT = pdfconstant("Btn"), + -- T = pdfcopyunicode(annotation.T or parent.T), + -- F = pdfcopyinteger(annotation.F or parent.F), + -- Ff = pdfcopyinteger(annotation.Ff or parent.Ff), + -- AS = pdfcopyconstant(annotation.AS or (parent and parent.AS)), + -- AP = AP and pdfreference(AP), + -- } + -- local finalize = dictionary() + -- context.setlayer(layerspec,locationspec,function() + -- context(hpack_node(nodeinjections.annotation(W/bpfactor,H/bpfactor,0,finalize))) + -- end) + -- -- + -- end + -- elseif what == "Ch" then + -- -- F Ff FT Opt T | AA OC (rest follows) + -- if wflags.PopUp then + -- wflags.PopUp = nil + -- if wflags.Edit then + -- wflags.Edit = nil + -- what = "combo" + -- else + -- what = "popup" + -- end + -- else + -- what = "choice" + -- end + -- elseif what == "Sig" then + -- what = "signature" + -- else + -- what = nil + -- end + -- end + -- end + -- end + -- end + -- end + -- end +end -- Beware, bookmarks can be in pdfdoc encoding or in unicode. However, in mkiv we -- write out the strings in unicode (hex). When we read them in, we check for a bom @@ -471,16 +1004,6 @@ function codeinjections.mergebookmarks(specification) end end --- placeholders: - -function codeinjections.mergecomments(specification) - report_comment("unfinished experimental code, not used yet") -end - -function codeinjections.mergefields(specification) - report_field("unfinished experimental code, not used yet") -end - -- A bit more than a placeholder but in the same perspective as -- inclusion of comments and fields: -- diff --git a/tex/context/base/mkiv/lpdf-epd.lua b/tex/context/base/mkiv/lpdf-epd.lua index cf02b5a22..7bfdf57bc 100644 --- a/tex/context/base/mkiv/lpdf-epd.lua +++ b/tex/context/base/mkiv/lpdf-epd.lua @@ -32,7 +32,7 @@ if not modules then modules = { } end modules ['lpdf-epd'] = { -- already was unicode). local setmetatable, rawset, rawget, type, next = setmetatable, rawset, rawget, type, next -local tostring, tonumber = tostring, tonumber +local tostring, tonumber, unpack = tostring, tonumber, unpack local lower, match, char, byte, find = string.lower, string.match, string.char, string.byte, string.find local abs = math.abs local concat = table.concat @@ -67,13 +67,27 @@ local xref = registry["epdf.XRef"] local catalog = registry["epdf.Catalog"] local pdfdoc = registry["epdf.PDFDoc"] +if not (object and dictionary and array and xref and catalog and pdfdoc) then + logs.report("fatal error","invalid pdf inclusion library (%s)",1) + os.exit() +end + local openPDF = epdf.open +local getMajorVersion = pdfdoc.getPDFMajorVersion +local getMinorVersion = pdfdoc.getPDFMinorVersion +local getXRef = pdfdoc.getXRef +local getRawCatalog = pdfdoc.getCatalog + +if not (openPDF and getMajorVersion and getMinorVersion and getXRef and getRawCatalog) then + logs.report("fatal error","invalid pdf inclusion library (%s)",2) + os.exit() +end + local getDict = object.getDict local getArray = object.getArray local getReal = object.getReal local getInt = object.getInt -local getNum = object.getNum local getString = object.getString local getBool = object.getBool local getName = object.getName @@ -81,38 +95,60 @@ local getRef = object.getRef local getRefNum = object.getRefNum local getType = object.getType -local getTypeName = object.getTypeName + +if not (getDict and getArray and getReal and getInt and getString and getBool and getName and getRef and getRefNum and getType) then + logs.report("fatal error","invalid pdf inclusion library (%s)",3) + os.exit() +end local streamReset = object.streamReset local streamGetDict = object.streamGetDict local streamGetChar = object.streamGetChar +local streamGetAll = object.streamGetAll + +if not (streamReset and streamGetDict and streamGetChar) then + logs.report("fatal error","invalid pdf inclusion library (%s)",3) + os.exit() +end local dictGetLength = dictionary.getLength local dictGetVal = dictionary.getVal local dictGetValNF = dictionary.getValNF local dictGetKey = dictionary.getKey +if not (dictGetLength and dictGetVal and dictGetValNF and dictGetKey) then + logs.report("fatal error","invalid pdf inclusion library (%s)",4) + os.exit() +end + local arrayGetLength = array.getLength local arrayGetNF = array.getNF local arrayGet = array.get +if not (arrayGetLength and arrayGetNF and arrayGet) then + logs.report("fatal error","invalid pdf inclusion library (%s)",5) + os.exit() +end + -- these are kind of weird as they can't be accessed by (root) object local getNumPages = catalog.getNumPages local getPageRef = catalog.getPageRef -local getXRef = pdfdoc.getXRef -local getRawCatalog = pdfdoc.getCatalog - local fetch = xref.fetch local getCatalog = xref.getCatalog local getDocInfo = xref.getDocInfo +if not (getNumPages and getPageRef and fetch and getCatalog and getDocInfo) then + logs.report("fatal error","invalid pdf inclusion library (%s)",6) + os.exit() +end + -- we're done with library shortcuts local report_epdf = logs.reporter("epdf") -local typenames = { [0] = +local typenames = { [0] = "boolean", "integer", "real", @@ -208,30 +244,28 @@ local function prepare(document,d,t,n,k,mt,flags) local kind = getType(v) if kind == null_code then -- ignore - else + elseif kind then local key = dictGetKey(d,i) - if kind then - if r and getType(r) == ref_code then - local objnum = getRefNum(r) - local cached = document.__cache__[objnum] - if not cached then - cached = checked_access[kind](v,document,objnum,mt) - if cached then - document.__cache__[objnum] = cached - document.__xrefs__[cached] = objnum - end - end - t[key] = cached - else - local v, flag = checked_access[kind](v,document) - t[key] = v - if flag and flags then - flags[key] = flag -- flags + if r and getType(r) == ref_code then + local objnum = getRefNum(r) + local cached = document.__cache__[objnum] + if not cached then + cached = checked_access[kind](v,document,objnum,mt) + if cached then + document.__cache__[objnum] = cached + document.__xrefs__[cached] = objnum end end + t[key] = cached else - report_epdf("warning: nil value for key %a in dictionary",key) + local v, flag = checked_access[kind](v,document) + t[key] = v + if flag and flags then + flags[key] = flag -- flags + end end + else + report_epdf("warning: nil value for key %a in dictionary",key) end else fatal_error("error: invalid value at index %a in dictionary of %a",i,document.filename) @@ -245,6 +279,42 @@ local function prepare(document,d,t,n,k,mt,flags) return t[k] end +-- local function prepare(document,d,t,n,k,mt,flags) +-- for i=1,n do +-- local v = dictGetValNF(d,i) +-- if v then +-- local key = dictGetKey(d,i) +-- local kind = getType(v) +-- if kind == ref_code then +-- local objnum = getRefNum(v) +-- local cached = document.__cache__[objnum] +-- if not cached then +-- local v = dictGetVal(d,i) +-- local kind = getType(v) +-- cached = checked_access[kind](v,document,objnum,mt) +-- if cached then +-- document.__cache__[objnum] = cached +-- document.__xrefs__[cached] = objnum +-- end +-- end +-- t[key] = cached +-- else +-- local v, flag = checked_access[kind](v,document) +-- t[key] = v +-- if flag and flags then +-- flags[key] = flag -- flags +-- end +-- end +-- end +-- end +-- if mt then +-- setmetatable(t,mt) +-- else +-- getmetatable(t).__index = nil +-- end +-- return t[k] +-- end + local function some_dictionary(d,document) local n = d and dictGetLength(d) or 0 if n > 0 then @@ -326,6 +396,37 @@ local function prepare(document,a,t,n,k) end end +-- local function prepare(document,a,t,n,k) +-- for i=1,n do +-- local v = arrayGetNF(a,i) +-- if v then +-- local kind = getType(v) +-- if kind == ref_code then +-- local objnum = getRefNum(v) +-- local cached = document.__cache__[objnum] +-- if not cached then +-- local v = arrayGet(a,i) +-- local kind = getType(v) +-- cached = checked_access[kind](v,document,objnum) +-- document.__cache__[objnum] = cached +-- document.__xrefs__[cached] = objnum +-- end +-- t[i] = cached +-- else +-- t[i] = checked_access[kind](v,document) +-- end +-- end +-- end +-- local m = getmetatable(t) +-- if m then +-- m.__index = nil +-- m.__len = nil +-- end +-- if k then +-- return t[k] +-- end +-- end + local function some_array(a,document) local n = a and arrayGetLength(a) or 0 if n > 0 then @@ -376,23 +477,53 @@ end -- todo: collect chunks -local function streamaccess(s,_,what) - if not what or what == "all" or what == "*all" then - local t, n = { }, 0 - streamReset(s) +-- local function streamaccess(s,_,what) +-- if not what or what == "all" or what == "*all" then +-- local t, n = { }, 0 +-- streamReset(s) +-- while true do +-- local c = streamGetChar(s) +-- if c < 0 then +-- break +-- else +-- n = n + 1 +-- t[n] = char(c) +-- end +-- end +-- return concat(t,"",1,n) +-- end +-- end + +local function getstream(s) + streamReset(s) + if streamGetAll then + return streamGetAll(s) + else + local t, b, n = { }, { }, 0 while true do local c = streamGetChar(s) if c < 0 then break else n = n + 1 - t[n] = char(c) + b[n] = c + end + if n == 2000 then + t[#t+1] = char(unpack(b,1,n)) + n = 1 end end + t[#t+1] = char(unpack(b,1,n)) return concat(t) end end +local function streamaccess(s,_,what) + if not what or what == "all" or what == "*all" then + return getstream(s) + end +end + local function get_stream(d,document) if d then streamReset(d) @@ -562,16 +693,19 @@ end -- with but it won't win a beauty contest. local function getpages(document,Catalog) - local __data__ = document.__data__ - local __xrefs__ = document.__xrefs__ - local __cache__ = document.__cache__ - local __xref__ = document.__xref__ + local __data__ = document.__data__ + local __xrefs__ = document.__xrefs__ + local __cache__ = document.__cache__ + local __xref__ = document.__xref__ + -- + local rawcatalog = getRawCatalog(__data__) + local nofpages = getNumPages(rawcatalog) -- - local rawcatalog = getRawCatalog(__data__) - local nofpages = getNumPages(rawcatalog) + local majorversion = getMajorVersion(__data__) + local minorversion = getMinorVersion(__data__) -- - local pages = { } - local metatable = { __index = Catalog.Pages } -- somewhat empty + local pages = { } + local metatable = { __index = Catalog.Pages } -- somewhat empty -- for pagenumber=1,nofpages do local pagereference = getPageRef(rawcatalog,pagenumber).num @@ -580,6 +714,7 @@ local function getpages(document,Catalog) if pagedata then -- rawset(pagedata,"number",pagenumber) pagedata.number = pagenumber + pagedata.object = pageobject pages[pagenumber] = pagedata __xrefs__[pagedata] = pagereference __cache__[pagereference] = pagedata @@ -590,7 +725,10 @@ local function getpages(document,Catalog) -- pages.n = nofpages -- - document.pages = pages + document.pages = pages + document.majorversion = majorversion + document.minorversion = minorversion + -- return pages end @@ -637,6 +775,8 @@ function lpdf_epdf.load(filename) document.Catalog = some_dictionary(getDict(getCatalog(__xref__)),document) document.Info = some_dictionary(getDict(getDocInfo(__xref__)),document) setmetatableindex(document,resolve) + -- + document.nofpages = getNumPages(getRawCatalog(__data__)) else document = false end @@ -735,14 +875,14 @@ local fromunicode = ( P(1) )^1 * Carg(1) -local function analyzefonts(document,resources) -- unfinished +local function analyzefonts(document,resources) -- unfinished, see mtx-pdf for better code local fonts = document.__fonts__ if resources then local fontlist = resources.Font if fontlist then for id, data in expanded(fontlist) do if not fonts[id] then - -- a quck hack ... I will look into it more detail if I find a real + -- a quick hack ... I will look into it more detail if I find a real -- -application for it local tounicode = data.ToUnicode() if tounicode then @@ -836,7 +976,7 @@ function lpdf_epdf.getpagecontent(document,pagenumber) end --- This is also an experiment. When I really neet it I can improve it, fo rinstance +-- This is also an experiment. When I really need it I can improve it, for instance -- with proper position calculating. It might be usefull for some search or so. local softhyphen = utfchar(0xAD) .. "$" @@ -925,3 +1065,247 @@ end -- local destination = document.__data__:findDest(name) -- return destination and destination.number -- end + +-- This is experimental code that we need for testing the transition from +-- poppler to a new lightweight library. Don't rely on this code to remain +-- as it is now. Interesting is that performance of this variant is the same +-- as the natural page includer. + +if img then do + + local copydictionary = nil + local copyarray = nil + + local ref_code = typenumbers.ref + local boolean_code = typenumbers.boolean + local integer_code = typenumbers.integer + local real_code = typenumbers.real + local string_code = typenumbers.string + local name_code = typenumbers.name + local null_code = typenumbers.null + local array_code = typenumbers.array + local dictionary_code = typenumbers.dictionary + local stream_code = typenumbers.stream + local cmd_code = typenumbers.cmd + + local pdfreserveobject = lpdf.reserveobject + local pdfflushobject = lpdf.flushobject + local pdfflushstreamobject = lpdf.flushstreamobject + local pdfreference = lpdf.reference + local pdfconstant = lpdf.constant + local pdfarray = lpdf.array + local pdfdictionary = lpdf.dictionary + local pdfunicode = lpdf.unicode + local pdfstring = lpdf.string + local pdfnull = lpdf.null + + local report = logs.reporter("backend","xobjects") + + local factor = 65536 / (7200/7227) -- 1/number.dimenfactors.bp + + local newimage = img.new + + local function scaledbbox(b) + return { b[1]*factor, b[2]*factor, b[3]*factor, b[4]*factor } + end + + local function copyobject(xref,copied,kind,r,v) + if kind == null_code then + return pdfnull() + elseif r and getType(r) == ref_code then + local objnum = getRefNum(r) + local r = copied[objnum] + if r then + -- report("%s object %i is reused",kind,objnum) + else + local o + r = pdfreserveobject() + copied[objnum] = r + if kind == array_code then + local a = copyarray(xref,copied,fetch(xref,objnum,0)) + pdfflushobject(r,tostring(a)) + elseif kind == dictionary_code then + local d = copydictionary(xref,copied,fetch(xref,objnum,0)) + pdfflushobject(r,tostring(d)) + elseif kind == stream_code then + local f = fetch(xref,objnum,0) + local d = copydictionary(xref,copied,false,streamGetDict(f)) + local s = getstream(f) + -- + d.Filter = nil + d.Length = nil + d.DecodeParms = nil + d.DL = nil + -- + pdfflushstreamobject(s,d,true,r) + else + report("reference not done: %s", kind) + end + end + return pdfreference(r) + elseif kind == array_code then + return copyarray(xref,copied,v) + elseif kind == dictionary_code then + return copydictionary(xref,copied,v) + elseif kind == integer_code then + return getInt(v) + elseif kind == real_code then + return getReal(v) + elseif kind == name_code then + return pdfconstant(getName(v)) + elseif kind == string_code then + local s = getString(v) + if not s or s == "" then + return "" + end + local u = lpegmatch(u_pattern,s) + if u then + return pdfunicode(s) + end + return pdfstring(s) + elseif kind == boolean_code then + return getBool(v) + elseif kind == stream_code then + -- hm ... + return getStream(v) + else + report("object not done: %s", kind) + end + end + + copyarray = function (xref,copied,object) + local a = getArray(object) + local n = a and arrayGetLength(a) or 0 + if n > 0 then + local target = pdfarray() + for i=1,n do + local v = arrayGet(a,i) + if v then + local kind = getType(v) + local r = arrayGetNF(a,i) + target[i] = copyobject(xref,copied,kind,r,v) + end + end + return target + end + end + + copydictionary = function (xref,copied,object,d) + local d = d or getDict(object) + local n = d and dictGetLength(d) or 0 + if n > 0 then + local target = pdfdictionary() + for i=1,n do + local v = dictGetVal(d,i) + if v then + local kind = getType(v) + local key = dictGetKey(d,i) + local r = dictGetValNF(d,i) + target[key] = copyobject(xref,copied,kind,r,v) + end + end + return target + end + end + + local function copy_resources(pdfdoc,xref,copied,pagedata) + local object = pagedata.object + if object then + local d = getDict(object) + local n = d and dictGetLength(d) or 0 + for i=1,n do + local k = dictGetKey(d,i) + if v and k == "Resources" then + local v = dictGetVal(d,i) + local kind = getType(v) + local r = dictGetValNF(d,i) + return copyobject(xref,copied,kind,r,v) + end + end + end + end + + local function openpdf(filename) + local pdfdoc = lpdf_epdf.load(filename) + if pdfdoc then + pdfdoc.__copied__ = pdfdoc.__copied__ or { } + pdfdoc.filename = filename + return pdfdoc + end + end + + local function closepdf(pdfdoc) + if pdfdoc then + lpdf_epdf.unload(pdfdoc.filename) + end + end + + local function querypdf(pdfdoc,pagenumber) + if pdfdoc then + if not pagenumber then + pagenumber = 1 + end + local root = pdfdoc.Catalog + local page = pdfdoc.pages[pagenumber] + if page then + local mediabox = page.MediaBox or { 0, 0, 0, 0 } + local cropbox = page.CropBox or mediabox + return { + filename = pdfdoc.filename, + pagenumber = pagenumber, + nofpages = pdfdoc.nofpages, + boundingbox = scaledbbox(cropbox), + cropbox = cropbox, + mediabox = mediabox, + bleedbox = page.BleedBox or cropbox, + trimbox = page.TrimBox or cropbox, + artbox = page.ArtBox or cropbox, + } + end + end + end + + local function copypage(pdfdoc,pagenumber,attributes) + if pdfdoc then + local root = pdfdoc.Catalog + local page = pdfdoc.pages[pagenumber or 1] + local pageinfo = querypdf(pdfdoc,pagenumber) + local contents = page.Contents + local xref = pdfdoc.__xref__ + local copied = pdfdoc.__copied__ + -- + local xobject = pdfdictionary { + Type = pdfconstant("XObject"), + Subtype = pdfconstant("Form"), + -- image attributes + FormType = 1, + BBox = pageinfo.cropbox, + -- MetaData = copy(xref,copied,root,"MetaData"), + -- Group = copy(xref,copied,page,"Group"), + -- LastModified = copy(xref,copied,page,"LastModified"), + -- Metadata = copy(xref,copied,page,"Metadata"), + -- PieceInfo = copy(xref,copied,page,"PieceInfo"), + Resources = copy_resources(pdfdoc,xref,copied,page), + -- SeparationInfo = copy(xref,copied,page,"SeparationInfo"), + } + if attributes then + for k, v in next, expand(attributes) do + page[k] = v -- maybe nested + end + end + return newimage { + bbox = pageinfo.boundingbox, + stream = contents(), + attr = xobject(), + } + end + end + + lpdf_epdf.image = { + open = openpdf, + close = closepdf, + query = querypdf, + copy = copypage, + } + +end end diff --git a/tex/context/base/mkiv/lpdf-ini.lua b/tex/context/base/mkiv/lpdf-ini.lua index 8af1fb409..89b87ed11 100644 --- a/tex/context/base/mkiv/lpdf-ini.lua +++ b/tex/context/base/mkiv/lpdf-ini.lua @@ -362,8 +362,10 @@ local f_key_dictionary = formatters["/%s << % t >>"] local f_dictionary = formatters["<< % t >>"] local f_key_array = formatters["/%s [ % t ]"] local f_array = formatters["[ % t ]"] -local f_key_number = formatters["/%s %F"] -local f_tonumber = formatters["%F"] +----- f_key_number = formatters["/%s %F"] +local f_key_number = formatters["/%s %n"] +----- f_tonumber = formatters["%F"] +local f_tonumber = formatters["%n"] local tostring_a, tostring_d @@ -734,12 +736,13 @@ function lpdf.flushobject(name,data) end -function lpdf.flushstreamobject(data,dict,compressed) -- default compressed +function lpdf.flushstreamobject(data,dict,compressed,objnum) -- default compressed if trace_objects then report_objects("flushing stream object of %s bytes",#data) end local dtype = type(dict) return pdfdeferredobject { + objnum = objnum, immediate = true, compresslevel = compressed == false and 0 or nil, type = "stream", @@ -748,12 +751,13 @@ function lpdf.flushstreamobject(data,dict,compressed) -- default compressed } end -function lpdf.flushstreamfileobject(filename,dict,compressed) -- default compressed +function lpdf.flushstreamfileobject(filename,dict,compressed,objnum) -- default compressed if trace_objects then report_objects("flushing stream file object %a",filename) end local dtype = type(dict) return pdfdeferredobject { + objnum = objnum, immediate = true, compresslevel = compressed == false and 0 or nil, type = "stream", @@ -905,13 +909,12 @@ if not callbacks.register("finish_pdfpage", lpdf.finalizepage) then return head, true end - nodes.tasks.appendaction("shipouts","normalizers","backends.pdf.nodeinjections.finalizepage") + nodes.tasks.enableaction("shipouts","backends.pdf.nodeinjections.finalizepage") end callbacks.register("finish_pdffile", lpdf.finalizedocument) - do -- some minimal tracing, handy for checking the order @@ -1127,12 +1130,12 @@ do return Y and format("D:%s%s%s%s%s%s%s%s'%s'",Y,M,D,h,m,s,Zs,Zh,Zm) end - function lpdf.id(nodate) + function lpdf.id(date) local banner = environment.jobname or tex.jobname or "unknown" - if nodate then + if not date then return banner else - return format("%s.%s",banner,timestamp) + return format("%s | %s",banner,timestamp) end end diff --git a/tex/context/base/mkiv/lpdf-nod.lua b/tex/context/base/mkiv/lpdf-nod.lua index e3c1778f2..d41aa0bee 100644 --- a/tex/context/base/mkiv/lpdf-nod.lua +++ b/tex/context/base/mkiv/lpdf-nod.lua @@ -10,6 +10,9 @@ local type = type local formatters = string.formatters +local nodecodes = nodes.nodecodes +local whatsit_code = nodecodes.whatsit + local whatsitcodes = nodes.whatsitcodes local nodeinjections = backends.nodeinjections @@ -26,16 +29,16 @@ local register = nodepool.register local literalvalues = nodes.literalvalues -local pdforiginliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdforiginliteral,"mode",literalvalues.origin) -local pdfpageliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfpageliteral, "mode",literalvalues.page) -local pdfdirectliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfdirectliteral,"mode",literalvalues.direct) -local pdfrawliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfrawliteral, "mode",literalvalues.raw) +local pdforiginliteral = register(new_node(whatsit_code, whatsitcodes.pdfliteral)) setfield(pdforiginliteral,"mode",literalvalues.origin) +local pdfpageliteral = register(new_node(whatsit_code, whatsitcodes.pdfliteral)) setfield(pdfpageliteral, "mode",literalvalues.page) +local pdfdirectliteral = register(new_node(whatsit_code, whatsitcodes.pdfliteral)) setfield(pdfdirectliteral,"mode",literalvalues.direct) +local pdfrawliteral = register(new_node(whatsit_code, whatsitcodes.pdfliteral)) setfield(pdfrawliteral, "mode",literalvalues.raw) -local pdfsave = register(new_node("whatsit", whatsitcodes.pdfsave)) -local pdfrestore = register(new_node("whatsit", whatsitcodes.pdfrestore)) -local pdfsetmatrix = register(new_node("whatsit", whatsitcodes.pdfsetmatrix)) ------ pdfdest = register(new_node("whatsit", whatsitcodes.pdfdest)) setfield(pdfdest,"named_id",1) -- xyz_zoom untouched ------ pdfannot = register(new_node("whatsit", whatsitcodes.pdfannot)) +local pdfsave = register(new_node(whatsit_code, whatsitcodes.pdfsave)) +local pdfrestore = register(new_node(whatsit_code, whatsitcodes.pdfrestore)) +local pdfsetmatrix = register(new_node(whatsit_code, whatsitcodes.pdfsetmatrix)) +----- pdfdest = register(new_node(whatsit_code, whatsitcodes.pdfdest)) setfield(pdfdest,"named_id",1) -- xyz_zoom untouched +----- pdfannot = register(new_node(whatsit_code, whatsitcodes.pdfannot)) local variables = interfaces.variables diff --git a/tex/context/base/mkiv/lpdf-tag.lua b/tex/context/base/mkiv/lpdf-tag.lua index dc7d038fe..b3d117c4b 100644 --- a/tex/context/base/mkiv/lpdf-tag.lua +++ b/tex/context/base/mkiv/lpdf-tag.lua @@ -51,8 +51,6 @@ local a_tagged = attributes.private('tagged') local a_image = attributes.private('image') local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local nodepool = nuts.pool local pdfpageliteral = nodepool.pdfpageliteral @@ -68,9 +66,10 @@ local setlink = nuts.setlink local setlist = nuts.setlist local copy_node = nuts.copy -local traverse_nodes = nuts.traverse local tosequence = nuts.tosequence +local nextnode = nuts.traversers.node + local structure_stack = { } local structure_kids = pdfarray() local structure_ref = pdfreserveobject() @@ -324,10 +323,9 @@ function nodeinjections.addtags(head) local last = nil local ranges = { } local range = nil - local head = tonut(head) local function collectranges(head,list) - for n, id in traverse_nodes(head) do + for n, id in nextnode, head do if id == glyph_code then -- maybe also disc local at = getattr(n,a_tagged) @@ -441,17 +439,17 @@ function nodeinjections.addtags(head) setlink(stop,literal) end --- if literal then --- if list and getlist(list) == start then --- setlink(literal,start) --- setlist(list,literal) --- else --- setlink(getprev(start),literal,start) --- end --- -- use insert instead: --- local literal = copy_node(EMCliteral) --- setlink(stop,literal,getnext(stop)) --- end + -- if literal then + -- if list and getlist(list) == start then + -- setlink(literal,start) + -- setlist(list,literal) + -- else + -- setlink(getprev(start),literal,start) + -- end + -- -- use insert instead: + -- local literal = copy_node(EMCliteral) + -- setlink(stop,literal,getnext(stop)) + -- end top = taglist noftop = noftags @@ -459,8 +457,7 @@ function nodeinjections.addtags(head) finishpage() - head = tonode(head) - return head, true + return head end @@ -471,7 +468,7 @@ end -- local last, ranges, range = nil, { }, nil -- -- local function collectranges(head,list) --- for n, id in traverse_nodes(head) do +-- for n, id in nextnode, head do -- if id == glyph_code then -- local at = getattr(n,a_tagged) -- if not at then @@ -503,7 +500,6 @@ end -- -- initializepage() -- --- head = tonut(head) -- collectranges(head) -- -- if trace_tags then @@ -610,8 +606,7 @@ end -- -- finishpage() -- --- head = tonode(head) --- return head, true +-- return head -- -- end diff --git a/tex/context/base/mkiv/math-act.lua b/tex/context/base/mkiv/math-act.lua index 77a355b22..a847b78c6 100644 --- a/tex/context/base/mkiv/math-act.lua +++ b/tex/context/base/mkiv/math-act.lua @@ -23,6 +23,12 @@ local mathematics = mathematics local texsetdimen = tex.setdimen local abs = math.abs +local helpers = fonts.helpers +local upcommand = helpers.commands.up +local rightcommand = helpers.commands.right +local charcommand = helpers.commands.char +local prependcommands = helpers.prependcommands + local sequencers = utilities.sequencers local appendgroup = sequencers.appendgroup local appendaction = sequencers.appendaction @@ -237,7 +243,6 @@ function mathematics.overloaddimensions(target,original,set) local factor = parameters.factor local hfactor = parameters.hfactor local vfactor = parameters.vfactor - local addprivate = fonts.helpers.addprivate -- to be sure target.type = "virtual" target.properties.virtualized = true @@ -257,7 +262,8 @@ function mathematics.overloaddimensions(target,original,set) local height = data.height local depth = data.depth if trace_defining and (width or height or depth) then - report_math("overloading dimensions of %C, width %a, height %a, depth %a",unicode,width,height,depth) + report_math("overloading dimensions of %C, width %p, height %p, depth %p", + unicode,width or 0,height or 0,depth or 0) end if width then character.width = width * hfactor end if height then character.height = height * vfactor end @@ -270,25 +276,26 @@ function mathematics.overloaddimensions(target,original,set) if d then xoffset = - d.boundingbox[1] * hfactor character.width = character.width + xoffset - xoffset = { "right", xoffset } + xoffset = rightcommand[xoffset] + else + xoffset = nil end - elseif xoffset then - xoffset = { "right", xoffset * hfactor } + elseif xoffset and xoffset ~= 0 then + xoffset = rightcommand[xoffset * hfactor] + else + xoffset = nil end - if yoffset then - yoffset = { "down", -yoffset * vfactor } + if yoffset and yoffset ~= 0 then + yoffset = upcommand[yoffset * vfactor] + else + yoffset = nil end if xoffset or yoffset then - if character.commands then - if yoffset then - insert(character.commands,1,yoffset) - end - if xoffset then - insert(character.commands,1,xoffset) - end + local commands = characters.commands + if commands then + prependcommands(commands,yoffset,xoffset) else - -- local slot = { "slot", 1, addprivate(target,nil,fastcopy(character)) } - local slot = { "slot", 0, addprivate(target,nil,fastcopy(character)) } + local slot = charcommand[unicode] if xoffset and yoffset then character.commands = { xoffset, yoffset, slot } elseif xoffset then @@ -297,7 +304,6 @@ function mathematics.overloaddimensions(target,original,set) character.commands = { yoffset, slot } end end - character.index = nil end elseif trace_defining then report_math("no overloading dimensions of %C, not in font",unicode) diff --git a/tex/context/base/mkiv/math-dir.lua b/tex/context/base/mkiv/math-dir.lua index 759f1e797..0543937f5 100644 --- a/tex/context/base/mkiv/math-dir.lua +++ b/tex/context/base/mkiv/math-dir.lua @@ -60,7 +60,6 @@ local a_mathbidi = attributes.private('mathbidi') local function processmath(head) local current = head - local done = false local start = nil local stop = nil local function capsulate() @@ -69,7 +68,6 @@ local function processmath(head) if trace_directions then report_directions("reversed: %s",nodes.listtoutf(start,false,false,stop)) end - done = true start = false stop = nil end @@ -100,7 +98,6 @@ local function processmath(head) if trace_directions then report_directions("mirrored: %C to %C",char,mirror) end - done = true end end end @@ -108,11 +105,8 @@ local function processmath(head) elseif not start then -- nothing if id == hlist_code or id == vlist_code then - local list, d = processmath(getlist(current)) + local list = processmath(getlist(current)) setlist(current,list) - if d then - done = true - end end elseif start == stop then start = nil @@ -121,11 +115,8 @@ local function processmath(head) -- math can pack things into hlists .. we need to make sure we don't process -- too often: needs checking if id == hlist_code or id == vlist_code then - local list, d = processmath(getlist(current)) + local list = processmath(getlist(current)) setlist(current,list) - if d then - done = true - end end end current = getnext(current) @@ -137,21 +128,18 @@ local function processmath(head) else capsulate() end - return head, done + return head end local enabled = false function directions.processmath(head) -- style, penalties if enabled then - local h = tonut(head) - local a = getattr(h,a_mathbidi) + local a = getattr(head,a_mathbidi) if a and a > 0 then - local head, done = processmath(h) - return tonode(head), done + return processmath(head) end end - return head, false end function directions.setmath(n) diff --git a/tex/context/base/mkiv/math-fen.mkiv b/tex/context/base/mkiv/math-fen.mkiv index a32ea410e..3a32f9fb8 100644 --- a/tex/context/base/mkiv/math-fen.mkiv +++ b/tex/context/base/mkiv/math-fen.mkiv @@ -65,14 +65,19 @@ % we need the direct use of \Udelimiter because of { etc -\newconditional\c_math_fenced_mirror \settrue\c_math_fenced_mirror +\newconditional\c_math_fenced_mirror \settrue \c_math_fenced_mirror +\newconditional\c_math_fenced_sized \setfalse\c_math_fenced_sized \unexpanded\def\math_fenced_inject#1#2#3#4% {\ifx#1\empty #2.% \else \edef\p_mathclass{\mathfenceparameter\c!mathclass}% - \edef\p_factor{\mathfenceparameter\c!factor}% + \ifconditional\c_math_fenced_sized + \let\p_factor\v!fixed + \else + \edef\p_factor{\mathfenceparameter\c!factor}% + \fi \ifx\p_factor\empty \ifx\p_mathclass\empty #2% @@ -97,7 +102,11 @@ \s!axis % #2% \else - \scratchdimen\dimexpr\p_factor\bodyfontsize/2\relax + \ifx\p_factor\v!fixed + \scratchdimen\scaledpoint + \else + \scratchdimen\dimexpr\p_factor\bodyfontsize/2\relax + \fi #3% \s!height\scratchdimen \s!depth\scratchdimen @@ -121,16 +130,14 @@ \mathfenceparameter\c!left \fi}% \math_fenced_color_push - % \normalleft\ifx\p_left\empty.\else\Udelimiter\plusfour\fam\p_left\relax\fi \math_fenced_inject\p_left\normalleft\Uleft\plusfour \math_fenced_color_pop} \def\math_fenced_middle {\edef\p_middle - {\mathfenceparameter\c!middle}% + {\mathfenceparameter\c!middle}% \mskip\thinmuskip \math_fenced_color_push - % \normalmiddle\ifx\p_middle\empty.\else\Udelimiter\plusfour\fam\p_middle\relax\fi \math_fenced_inject\p_middle\normalmiddle\Umiddle\plusfour \math_fenced_color_pop \mskip\thinmuskip} @@ -147,7 +154,6 @@ \mathfenceparameter\c!right \fi}% \math_fenced_color_push - % \normalright \ifx\p_right\empty.\else\Udelimiter\plusfive\fam\p_right\relax\fi \math_fenced_inject\p_right\normalright\Uright\plusfive \math_fenced_color_pop} @@ -194,16 +200,60 @@ \edef\currentmathfence{#1}% \dosingleempty\math_fenced_fenced_indeed} -\unexpanded\def\math_fenced_fenced_indeed[#1]#2% +\def\math_fenced_force_size#1#2% + {\attribute\mathsizeattribute\numexpr#1*\plushundred+#2\relax} + +% \unexpanded\def\math_fenced_fenced_indeed[#1]#2% +% {\iffirstargument\setupcurrentmathfence[#1]\fi +% \math_fenced_fenced_common +% \edef\p_size{\mathfenceparameter\c!size}% +% \ifx\p_size\empty +% \setfalse\c_math_fenced_sized +% \else +% \settrue\c_math_fenced_sized +% \math_fenced_force_size\bigmathdelimitervariant\p_size +% \fi +% \math_fenced_left +% #2% +% \math_fenced_right +% \stopusemathstyleparameter +% \endgroup +% \advance\c_math_fenced_nesting\minusone} + +\unexpanded\def\math_fenced_fenced_indeed[#1]% {\iffirstargument\setupcurrentmathfence[#1]\fi \math_fenced_fenced_common - \math_fenced_left - #2% - \math_fenced_right - \stopusemathstyleparameter + \edef\p_size{\mathfenceparameter\c!size}% + \ifx\p_size\empty + \expandafter\math_fenced_fenced_indeed_adapt + \else + \expandafter\math_fenced_fenced_indeed_fixed + \fi} + +\unexpanded\def\math_fenced_fenced_indeed_finish + {\stopusemathstyleparameter \endgroup \advance\c_math_fenced_nesting\minusone} +\unexpanded\def\math_fenced_fenced_indeed_fixed#1% + {\math_fenced_force_size\bigmathdelimitervariant\p_size + \settrue\c_math_fenced_sized + \math_fenced_left + \setfalse\c_math_fenced_sized + #1% + \settrue\c_math_fenced_sized + \math_fenced_right + \setfalse\c_math_fenced_sized + \math_fenced_fenced_indeed_finish} + +\unexpanded\def\math_fenced_fenced_indeed_adapt#1% + {\setfalse\c_math_fenced_sized + \math_fenced_left + #1% + \setfalse\c_math_fenced_sized + \math_fenced_right + \math_fenced_fenced_indeed_finish} + \appendtoks \let\fenced\math_fenced_fenced \to \everymathematics @@ -591,7 +641,7 @@ \ifcase\bigmathdelimitermethod \math_fenced_step#2\relax \or - \attribute\mathsizeattribute\numexpr\bigmathdelimitervariant*\plushundred+#1\relax + \math_fenced_force_size\bigmathdelimitervariant{#1}\relax \math_fenced_step#2\relax \else \math_fenced_step#2{\vpack to\csname\??mathbig\number#1\endcsname\bodyfontsize{}}% @@ -621,7 +671,7 @@ \unexpanded\def\mathdelimiterstep#1#2% {\begingroup - \attribute\mathsizeattribute\numexpr\plushundred+#1\relax + \math_fenced_force_size\plusone{#1}% \math_fenced_step#2\relax \endgroup} diff --git a/tex/context/base/mkiv/math-ini.lua b/tex/context/base/mkiv/math-ini.lua index b79ef8c8c..d301b0065 100644 --- a/tex/context/base/mkiv/math-ini.lua +++ b/tex/context/base/mkiv/math-ini.lua @@ -641,7 +641,7 @@ function mathematics.big(tfmdata,unicode,n,method) end end end - else + elseif method == 3 then local size = 1.33^n if method == 4 then size = tfmdata.parameters.size * size diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua index 20f77411e..bb0817d9a 100644 --- a/tex/context/base/mkiv/math-noa.lua +++ b/tex/context/base/mkiv/math-noa.lua @@ -88,7 +88,6 @@ local a_exportstatus = privateattribute("exportstatus") local nuts = nodes.nuts local nodepool = nuts.pool local tonut = nuts.tonut -local tonode = nuts.tonode local nutstring = nuts.tostring local setfield = nuts.setfield @@ -102,6 +101,8 @@ local setsubtype = nuts.setsubtype local setattr = nuts.setattr local setattrlist = nuts.setattrlist local setwidth = nuts.setwidth +local setheight = nuts.setheight +local setdepth = nuts.setdepth local getfield = nuts.getfield local getnext = nuts.getnext @@ -114,6 +115,9 @@ local getfont = nuts.getfont local getfam = nuts.getfam local getattr = nuts.getattr local getlist = nuts.getlist +local getwidth = nuts.getwidth +local getheight = nuts.getheight +local getdepth = nuts.getdepth local getnucleus = nuts.getnucleus local getsub = nuts.getsub @@ -299,7 +303,7 @@ local function process(start,what,n,parent) start = getnext(start) end if not parent then - return initial, true -- only first level -- for now + return initial -- only first level -- for now end end @@ -376,15 +380,14 @@ local function processstep(current,process,n,id) end local function processnoads(head,actions,banner) - local h, d if trace_processing then report_processing("start %a",banner) - h, d = process(tonut(head),actions) + head = process(head,actions) report_processing("stop %a",banner) else - h, d = process(tonut(head),actions) + head = process(head,actions) end - return h and tonode(h) or head, d == nil and true or d + return head end noads.process = processnoads @@ -776,40 +779,38 @@ do local method, size = div(a,100), a % 100 setattr(pointer,a_mathsize,0) local delimiter = getfield(pointer,"delim") - local chr = getfield(delimiter,"small_char") + local chr = getchar(delimiter) if chr > 0 then - local fam = getfield(delimiter,"small_fam") + local fam = getfam(delimiter) local id = font_of_family(fam) if id > 0 then - setfield(delimiter,"small_char",mathematics.big(fontdata[id],chr,size,method)) + local data = fontdata[id] + local char = mathematics.big(data,chr,size,method) + local ht = getfield(pointer,"height") + -- local ht = getheight(pointer) -- LUATEXVERSION >= 1.090 + local dp = getfield(pointer,"depth") + -- local dp = getdepth(pointer) -- LUATEXVERSION >= 1.090 + if ht == 1 or dp == 1 then -- 1 scaled point is a signal + local chardata = data.characters[char] + if ht == 1 then + setfield(pointer,"height",chardata.height) + -- setheight(pointer,chardata.height) -- LUATEXVERSION >= 1.090 + end + if dp == 1 then + setfield(pointer,"depth",chardata.depth) + -- setdepth(pointer,chardata.depth) -- LUATEXVERSION >= 1.090 + end + end + if trace_fences then + report_fences("replacing %C by %C using method %a and size %a",chr,char,method,size) + end + setchar(delimiter,char) end end end end end - -- will become: - - -- resize[math_fence] = function(pointer) - -- local subtype = getsubtype(pointer) - -- if subtype == left_fence_code or subtype == right_fence_code then - -- local a = getattr(pointer,a_mathsize) - -- if a and a > 0 then - -- local method, size = div(a,100), a % 100 - -- setattr(pointer,a_mathsize,0) - -- local delimiter = getfield(pointer,"delim") - -- local chr = getchar(delimiter) - -- if chr > 0 then - -- local fam = getfam(delimiter) - -- local id = font_of_family(fam) - -- if id > 0 then - -- setchar(delimiter,mathematics.big(fontdata[id],chr,size,method)) - -- end - -- end - -- end - -- end - -- end - function handlers.resize(head,style,penalties) processnoads(head,resize,"resize") return true @@ -1038,7 +1039,7 @@ do function handlers.autofences(head,style,penalties) if enabled then -- tex.modes.c_math_fences_auto -- inspect(nodes.totree(head)) - processfences(tonut(head),1) + processfences(head,1) -- inspect(nodes.totree(head)) end end @@ -1136,7 +1137,6 @@ do function handlers.unscript(head,style,penalties) processnoads(head,unscript,"unscript") - -- processnoads(head,checkers,"checkers") return true end @@ -2177,7 +2177,7 @@ end -- just for me function handlers.showtree(head,style,penalties) - inspect(nodes.totree(head)) + inspect(nodes.totree(tonut(head))) end registertracker("math.showtree",function(v) @@ -2192,7 +2192,7 @@ do local visual = false function handlers.makeup(head) - applyvisuals(tonut(head),visual) + applyvisuals(head,visual) end registertracker("math.makeup",function(v) @@ -2213,7 +2213,7 @@ do -- end) function builders.kernel.mlist_to_hlist(head,style,penalties) - return mlist_to_hlist(head,style,force_penalties or penalties), true + return mlist_to_hlist(head,style,force_penalties or penalties) end implement { @@ -2226,41 +2226,15 @@ do end --- function builders.kernel.mlist_to_hlist(head,style,penalties) --- print("!!!!!!! BEFORE",penalties) --- for n in node.traverse(head) do print(n) end --- print("!!!!!!!") --- head = mlist_to_hlist(head,style,penalties) --- print("!!!!!!! AFTER") --- for n in node.traverse(head) do print(n) end --- print("!!!!!!!") --- return head, true --- end - -tasks.new { - name = "math", - arguments = 2, - processor = utilities.sequencers.nodeprocessor, - sequence = { - "before", - "normalizers", - "builders", - "after", - }, -} - -tasks.freezegroup("math", "normalizers") -- experimental -tasks.freezegroup("math", "builders") -- experimental - local actions = tasks.actions("math") -- head, style, penalties local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming function processors.mlist_to_hlist(head,style,penalties) starttiming(noads) - local head, done = actions(head,style,penalties) + head = actions(head,style,penalties) stoptiming(noads) - return head, done + return head end callbacks.register('mlist_to_hlist',processors.mlist_to_hlist,"preprocessing math list") diff --git a/tex/context/base/mkiv/math-spa.lua b/tex/context/base/mkiv/math-spa.lua index 92ee662b9..69f70ded5 100644 --- a/tex/context/base/mkiv/math-spa.lua +++ b/tex/context/base/mkiv/math-spa.lua @@ -8,22 +8,22 @@ if not modules then modules = { } end modules ['math-spa'] = { -- for the moment (when testing) we use a penalty 1 -local penalty_code = nodes.nodecodes.penalty -local glue_code = nodes.nodecodes.glue +local penalty_code = nodes.nodecodes.penalty +local glue_code = nodes.nodecodes.glue -local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode -local getid = nuts.getid -local getnext = nuts.getnext -local getwidth = nuts.getwidth -local setglue = nuts.setglue -local getpenalty = nuts.getpenalty -local setpenalty = nuts.setpenalty +local nuts = nodes.nuts +local tonut = nodes.tonut +local tonode = nodes.tonode +local getid = nuts.getid +local getnext = nuts.getnext +local getwidth = nuts.getwidth +local setglue = nuts.setglue +local getpenalty = nuts.getpenalty +local setpenalty = nuts.setpenalty -local traverse_id = nuts.traverse_id local get_dimensions = nuts.dimensions +local nextglue = nuts.traversers.glue local texsetdimen = tex.setdimen @@ -33,9 +33,8 @@ local v_auto = interfaces.variables.auto local method = v_none local distance = 0 -function noads.handlers.align(l) +function noads.handlers.align(h) if method ~= v_none then - local h = tonut(l) if method == v_auto then local s = h while s do @@ -56,13 +55,12 @@ function noads.handlers.align(l) else texsetdimen("global","d_strc_math_indent",distance) end - for n in traverse_id(glue_code,h) do + for n in nextglue, h do setglue(n,getwidth(n),0,0) end else -- texsetdimen("global","d_strc_math_indent",0) end - return l, true end interfaces.implement { diff --git a/tex/context/base/mkiv/math-tag.lua b/tex/context/base/mkiv/math-tag.lua index 9837dec35..868c2b661 100644 --- a/tex/context/base/mkiv/math-tag.lua +++ b/tex/context/base/mkiv/math-tag.lua @@ -38,7 +38,8 @@ local getsub = nuts.getsub local getsup = nuts.getsup local set_attributes = nuts.setattributes -local traverse_nodes = nuts.traverse + +local nextnode = nuts.traversers.node local nodecodes = nodes.nodecodes @@ -248,101 +249,101 @@ process = function(start) -- we cannot use the processor as we have no finalizer elseif id == math_box_code or id == hlist_code or id == vlist_code then -- keep an eye on math_box_code and see what ends up in there local attr = getattr(start,a_tagged) -if not attr then - -- just skip -else - local specification = taglist[attr] - if specification then - local tag = specification.tagname - if tag == "formulacaption" then - -- skip - elseif tag == "mstacker" then - local list = getlist(start) - if list then - process(list) - end - else - if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then - tag = "mtext" - end - local text = start_tagged(tag) - setattr(start,a_tagged,text) - local list = getlist(start) - if not list then - -- empty list - elseif not attr then - -- box comes from strange place - set_attributes(list,a_tagged,text) -- only the first node ? + if not attr then + -- just skip + else + local specification = taglist[attr] + if specification then + local tag = specification.tagname + if tag == "formulacaption" then + -- skip + elseif tag == "mstacker" then + local list = getlist(start) + if list then + process(list) + end else - -- Beware, the first node in list is the actual list so we definitely - -- need to nest. This approach is a hack, maybe I'll make a proper - -- nesting feature to deal with this at another level. Here we just - -- fake structure by enforcing the inner one. - -- - -- todo: have a local list with local tags that then get appended - -- - local tagdata = specification.taglist - local common = #tagdata + 1 - local function runner(list,depth) -- quite inefficient - local cache = { } -- we can have nested unboxed mess so best local to runner - local keep = nil - -- local keep = { } -- win case we might need to move keep outside - for n, id in traverse_nodes(list) do - local mth = id == math_code and getsubtype(n) - if mth == 0 then - -- insert(keep,text) - keep = text - text = start_tagged("mrow") - common = common + 1 - end - local aa = getattr(n,a_tagged) - if aa then - local ac = cache[aa] - if not ac then - local tagdata = taglist[aa].taglist - local extra = #tagdata - if common <= extra then - for i=common,extra do - ac = restart_tagged(tagdata[i]) -- can be made faster - end - for i=common,extra do - stop_tagged() -- can be made faster + if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then + tag = "mtext" + end + local text = start_tagged(tag) + setattr(start,a_tagged,text) + local list = getlist(start) + if not list then + -- empty list + elseif not attr then + -- box comes from strange place + set_attributes(list,a_tagged,text) -- only the first node ? + else + -- Beware, the first node in list is the actual list so we definitely + -- need to nest. This approach is a hack, maybe I'll make a proper + -- nesting feature to deal with this at another level. Here we just + -- fake structure by enforcing the inner one. + -- + -- todo: have a local list with local tags that then get appended + -- + local tagdata = specification.taglist + local common = #tagdata + 1 + local function runner(list,depth) -- quite inefficient + local cache = { } -- we can have nested unboxed mess so best local to runner + local keep = nil + -- local keep = { } -- win case we might need to move keep outside + for n, id, subtype in nextnode, list do + local mth = id == math_code and subtype + if mth == 0 then -- hm left_code + -- insert(keep,text) + keep = text + text = start_tagged("mrow") + common = common + 1 + end + local aa = getattr(n,a_tagged) + if aa then + local ac = cache[aa] + if not ac then + local tagdata = taglist[aa].taglist + local extra = #tagdata + if common <= extra then + for i=common,extra do + ac = restart_tagged(tagdata[i]) -- can be made faster + end + for i=common,extra do + stop_tagged() -- can be made faster + end + else + ac = text end - else - ac = text + cache[aa] = ac end - cache[aa] = ac + setattr(n,a_tagged,ac) + else + setattr(n,a_tagged,text) end - setattr(n,a_tagged,ac) - else - setattr(n,a_tagged,text) - end - if id == hlist_code or id == vlist_code then - runner(getlist(n),depth+1) - elseif id == glyph_code then - -- this should not be needed (todo: use tounicode info) - runner(getcomponents(n),depth+1) - elseif id == disc_code then - local pre, post, replace = getdisc(n) - runner(pre,depth+1) -- idem - runner(post,depth+1) -- idem - runner(replace,depth+1) -- idem - end - if mth == 1 then - stop_tagged() - -- text = remove(keep) - text = keep - common = common - 1 + if id == hlist_code or id == vlist_code then + runner(getlist(n),depth+1) + elseif id == glyph_code then + -- this should not be needed (todo: use tounicode info) + runner(getcomponents(n),depth+1) + elseif id == disc_code then + local pre, post, replace = getdisc(n) + runner(pre,depth+1) -- idem + runner(post,depth+1) -- idem + runner(replace,depth+1) -- idem + end + if mth == 1 then + stop_tagged() + -- text = remove(keep) + text = keep + common = common - 1 + end end end + runner(list,0) end - runner(list,0) + stop_tagged() end - stop_tagged() end end -end elseif id == math_sub_code then -- normally a hbox local list = getlist(start) if list then @@ -551,12 +552,10 @@ end end function noads.handlers.tags(head,style,penalties) - head = tonut(head) local v_mode = getattr(head,a_mathmode) local v_math = start_tagged("math", { mode = v_mode == 1 and "display" or "inline" }) setattr(head,a_tagged,start_tagged("mrow")) process(head) stop_tagged() stop_tagged() - return true end diff --git a/tex/context/base/mkiv/mlib-lua.lua b/tex/context/base/mkiv/mlib-lua.lua index 189f207c7..60ad9477b 100644 --- a/tex/context/base/mkiv/mlib-lua.lua +++ b/tex/context/base/mkiv/mlib-lua.lua @@ -60,7 +60,7 @@ function mp._f_() end end -local f_code = formatters["%s return mp._f_()"] +local f_code = formatters["%s return mp._f_()"] local f_numeric = formatters["%.16f"] local f_integer = formatters["%i"] @@ -128,6 +128,8 @@ local function mpvprint(...) -- variable print end end +mp.cleaned = function(s) return lpegmatch(p,s) or s end + mp.print = mpprint mp.vprint = mpvprint diff --git a/tex/context/base/mkiv/mult-aux.mkiv b/tex/context/base/mkiv/mult-aux.mkiv index a1aecc354..9ba09af41 100644 --- a/tex/context/base/mkiv/mult-aux.mkiv +++ b/tex/context/base/mkiv/mult-aux.mkiv @@ -180,6 +180,10 @@ \def\mult_check_for_assignment_indeed#1=#2#3\_end_ {\if#2@\assignmentfalse\else\assignmenttrue\fi} +\def\mult_check_for_assignment_indeed_begin_#1=#2#3\_end_ + {\if#2@} + + \def\mult_check_for_assignment#1% {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=@@\_end_} @@ -389,6 +393,43 @@ \the#7% \let#4#9}} +% \unexpanded\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones +% {\ifx#4\relax\let#4\empty\fi % see \defineregister +% \unexpanded\def#2{\dotripleempty#5}% +% \newtoks#6% +% \newtoks#7% +% \unexpanded\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child] +% {\let#9#4% +% \edef#4{##1}% +% \ifthirdargument +% \the#6% predefine +% \edef#8{##2}% +% \mult_check_for_parent{#1}{#3}#4#8% +% \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% +% \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% +% \mult_interfaces_get_parameters{#1#4:}[##3]% +% \else\ifsecondargument +% \the#6% predefine +% \ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##2}=@@\_end_ +% \edef#8{##2}% +% \mult_check_for_parent{#1}{#3}#4#8% +% \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% +% \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% +% \else +% \let#8\empty +% \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}% +% \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% +% \mult_interfaces_get_parameters{#1#4:}[##2]% +% \fi +% \else +% \the#6% predefine +% \let#8\empty +% \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}% +% \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% +% \fi\fi +% \the#7% +% \let#4#9}} + \unexpanded\def\installdefinehandler#1#2#3% {\normalexpanded {\mult_interfaces_install_define_handler @@ -466,7 +507,7 @@ \let#3#7% \else\iffirstargument % \mult_check_for_assignment{##1}% - \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_ + \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_ \ifassignment % \setuplayout[key=value] \let#7#3% @@ -496,6 +537,54 @@ #2\zerocount % mode is always zero at the end \the#9}} +% \unexpanded\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9% +% {\newtoks#5% +% \newconstant#2% +% \newtoks#8% +% \newtoks#9% +% \ifx#6\relax\let#6\empty\fi +% \unexpanded\def#4[##1][##2]% maybe helper +% {\ifsecondargument % no commalist here +% % \setuplayout[whatever][key=value] +% \let#7#3% +% \let#6#3% +% \edef#3{##1}% +% #2\doingrootsetupnamed +% \mult_interfaces_get_parameters{#1#3:}[##2]% +% \the#5% +% \ifx#3#6\the#8\fi % only switchsetups if previous == current +% \let#3#7% +% \else\iffirstargument +% % \mult_check_for_assignment{##1}% +% \ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=@@\_end_ +% % \setuplayout[whatever] +% \let#6#3% % previous becomes current +% \edef#3{##1}% this will catch reset so one needs to test for it +% #2\doingrootsetnamed +% \the#5% % we can check for previous vs current +% \the#8% switchsetups +% \else +% % \setuplayout[key=value] +% \let#7#3% +% \let#6#3% +% \let#3\empty +% #2\doingrootsetuproot +% \mult_interfaces_get_parameters{#1:}[##1]% +% \the#5% +% \the#8% switchsetups +% \let#3#7% +% \fi +% \else +% % \setuplayout +% \let#6#3% % previous becomes current +% \let#3\empty % current becomes empty +% #2\doingrootsetroot +% \the#5% +% \the#8% switchsetups +% \fi\fi +% #2\zerocount % mode is always zero at the end +% \the#9}} + \unexpanded\def\installswitchsetuphandler#1#2% {\normalexpanded {\mult_interfaces_install_switch_setup_handler_a diff --git a/tex/context/base/mkiv/mult-fun.lua b/tex/context/base/mkiv/mult-fun.lua index 9b7062605..1ee593be4 100644 --- a/tex/context/base/mkiv/mult-fun.lua +++ b/tex/context/base/mkiv/mult-fun.lua @@ -53,7 +53,7 @@ return { "shadedinto", "withshadecolors", "withshadedomain", "withshademethod", "withshadefactor", "withshadevector", "withshadecenter", "withshadedirection", "withshaderadius", "withshadetransform", - "withshadestep", "withshadefraction", + "withshadestep", "withshadefraction", "withshadeorigin", "shownshadevector", "shownshadeorigin", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", diff --git a/tex/context/base/mkiv/mult-ini.mkiv b/tex/context/base/mkiv/mult-ini.mkiv index ef9dcd249..117ac768c 100644 --- a/tex/context/base/mkiv/mult-ini.mkiv +++ b/tex/context/base/mkiv/mult-ini.mkiv @@ -343,17 +343,17 @@ %D These will become obsolete: \unexpanded\def\startmessages #1 library: #2 % - {\bgroup + {\begingroup \ifcsname\m!prefix!#2\endcsname\else\setgvalue{\m!prefix!#2}{#2}\fi - \catcode\endoflineasciicode\activecatcode + \catcode\endoflineasciicode\othercatcode \doifelseinset{#1}{\currentresponses,all}\mult_messages_start_yes\mult_messages_start_nop{#2}} \def\mult_messages_start_yes#1#2\stopmessages {\clf_setinterfacemessages{#1}{#2}% - \egroup} + \endgroup} \def\mult_messages_start_nop#1#2\stopmessages - {\egroup} + {\endgroup} \let\stopmessages\relax diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua index e10a8e6fa..f425f3a32 100644 --- a/tex/context/base/mkiv/mult-low.lua +++ b/tex/context/base/mkiv/mult-low.lua @@ -410,7 +410,7 @@ return { "installctxscanner", "installctxscannercall", "resetctxscanner", "installprotectedctxscanner", "installprotectedctxscannercall", - "cldprocessfile", "cldloadfile", "cldcontext", "cldcommand", + "cldprocessfile", "cldloadfile", "cldloadviafile", "cldcontext", "cldcommand", -- "carryoverpar", "lastlinewidth", diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua index 6351df180..1bf5bb526 100644 --- a/tex/context/base/mkiv/mult-prm.lua +++ b/tex/context/base/mkiv/mult-prm.lua @@ -261,6 +261,8 @@ return { "ifincsname", "ifprimitive", "ignoreligaturesinfont", + "immediateassignment", + "immediateassigned", "initcatcodetable", "insertht", "lastnamedcs", @@ -826,4 +828,4 @@ return { ["xetex"]={ "XeTeXversion", }, -}
\ No newline at end of file +} diff --git a/tex/context/base/mkiv/node-acc.lua b/tex/context/base/mkiv/node-acc.lua index 03f6d7476..8d9acaf9b 100644 --- a/tex/context/base/mkiv/node-acc.lua +++ b/tex/context/base/mkiv/node-acc.lua @@ -28,8 +28,9 @@ local setsubtype = nuts.setsubtype local getwidth = nuts.getwidth local setwidth = nuts.setwidth ------ traverse_nodes = nuts.traverse -local traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph +local nextnode = nuts.traversers.node + ----- copy_node = nuts.copy local insert_after = nuts.insert_after local copy_no_components = nuts.copy_no_components @@ -77,12 +78,11 @@ local function injectspaces(head) p = n n = getnext(n) end - return head, true -- always done anyway + return head end nodes.handlers.accessibility = function(head) - local head, done = injectspaces(tonut(head)) - return tonode(head), done + return injectspaces(head) end statistics.register("inserted spaces in output",function() @@ -99,7 +99,7 @@ end) -- -- local function compact(n) -- local t = { } --- for n in traverse_id(glyph_code,n) do +-- for n in nextglyph, n do -- t[#t+1] = utfchar(getchar(n)) -- check for unicode -- end -- return concat(t,"") @@ -107,8 +107,7 @@ end) -- -- local function injectspans(head) -- local done = false --- for n in traverse_nodes(tonuts(head)) do --- local id = getid(n) +-- for n, id in nextnode, tonuts(head) do -- if id == disc then -- local r = getfield(n,"replace") -- local p = getfield(n,"pre") @@ -138,8 +137,7 @@ end) -- -- local function injectspans(head) -- local done = false --- for n in traverse_nodes(tonut(head)) do --- local id = getid(n) +-- for n, id in nextnode, tonut(head) do -- if id == disc then -- local a = getattr(n,a_hyphenated) -- if a then diff --git a/tex/context/base/mkiv/node-aux.lua b/tex/context/base/mkiv/node-aux.lua index 5e85ead1c..cdd3403ac 100644 --- a/tex/context/base/mkiv/node-aux.lua +++ b/tex/context/base/mkiv/node-aux.lua @@ -51,8 +51,10 @@ local setprev = nuts.setprev local setcomponents = nuts.setcomponents local setattrlist = nuts.setattrlist -local traverse_nodes = nuts.traverse -local traverse_id = nuts.traverse_id +----- traverse_nodes = nuts.traverse +----- traverse_id = nuts.traverse_id +local nextnode = nuts.traversers.node +local nextglyph = nuts.traversers.glyph local flush_node = nuts.flush local flush_list = nuts.flush_list local hpack_nodes = nuts.hpack @@ -154,7 +156,7 @@ function nodes.repackhlist(list,...) end local function set_attributes(head,attr,value) - for n, id in traverse_nodes(head) do + for n, id in nextnode, head do setattr(n,attr,value) if id == hlist_node or id == vlist_node then set_attributes(getlist(n),attr,value) @@ -163,7 +165,7 @@ local function set_attributes(head,attr,value) end local function set_unset_attributes(head,attr,value) - for n, id in traverse_nodes(head) do + for n, id in nextnode, head do if not getattr(n,attr) then setattr(n,attr,value) end @@ -174,7 +176,7 @@ local function set_unset_attributes(head,attr,value) end local function unset_attributes(head,attr) - for n, id in traverse_nodes(head) do + for n, id in nextnode, head do setattr(n,attr,unsetvalue) if id == hlist_code or id == vlist_code then unset_attributes(getlist(n),attr) @@ -285,7 +287,7 @@ function nuts.firstcharacter(n,untagged) -- tagged == subtype > 255 if untagged then return first_glyph(n) else - for g in traverse_id(glyph_code,n) do + for g in nextglyph ,n do return g end end @@ -294,7 +296,7 @@ end local function firstcharinbox(n) local l = getlist(getbox(n)) if l then - for g in traverse_id(glyph_code,l) do + for g in nextglyph, l do return getchar(g) end end @@ -428,9 +430,9 @@ nodes.link = function(list,currentfont,currentattr,head,tail) end local function locate(start,wantedid,wantedsubtype) - for n, id in traverse_nodes(start) do + for n, id, subtype in nextnode, start do if id == wantedid then - if not wantedsubtype or getsubtype(n) == wantedsubtype then + if not wantedsubtype or subtype == wantedsubtype then return n end elseif id == hlist_code or id == vlist_code then @@ -553,7 +555,7 @@ function nuts.count_components(n,marks) if components then if marks then local i = 0 - for g in traverse_id(glyph_code,components) do + for g in nextglyph, components do if not marks[getchar(g)] then i = i + 1 end @@ -592,7 +594,7 @@ end function nuts.copy_only_glyphs(current) local head = nil local previous = nil - for n in traverse_id(glyph_code,current) do + for n in nextglyph, current do n = copy_node(n) if head then setlink(previous,n) diff --git a/tex/context/base/mkiv/node-bck.lua b/tex/context/base/mkiv/node-bck.lua index 995620710..8174888ee 100644 --- a/tex/context/base/mkiv/node-bck.lua +++ b/tex/context/base/mkiv/node-bck.lua @@ -27,9 +27,6 @@ local cell_code = listcodes.cell local nuts = nodes.nuts local nodepool = nuts.pool -local tonode = nuts.tonode -local tonut = nuts.tonut - local getnext = nuts.getnext local getprev = nuts.getprev local getid = nuts.getid @@ -49,13 +46,15 @@ local setprop = nuts.setprop local takebox = nuts.takebox local findtail = nuts.tail -local traverse = nuts.traverse -local traverse_id = nuts.traverse_id +local nextnode = nuts.traversers.node +local nexthlist = nuts.traversers.hlist +local nextlist = nuts.traversers.list local flush_node_list = nuts.flush_list local new_rule = nodepool.rule local new_kern = nodepool.kern +local new_hlist = nodepool.hlist local privateattributes = attributes.private local unsetvalue = attributes.unsetvalue @@ -84,6 +83,8 @@ trackers.register("backgrounds.alignments",function(v) trace_alignment = v end) -- For color only we can get away with it with an extra attribute flagging a row -- but for more complex stuff we can better do as we do here now. +local overshoot = math.floor(65781/5) -- could be an option per table (just also store it) + local function colored_a(current,list,template,id) local width, height, depth = getwhd(current) local total = height + depth @@ -101,8 +102,8 @@ local function colored_a(current,list,template,id) if not rule then rule = new_rule(width,height,depth) end - local back = new_kern(-((id == vlist_code and total) or width)) setattributelist(rule,template) + local back = new_kern(-((id == vlist_code and total) or width)) return setlink(rule,back,list) end end @@ -123,11 +124,16 @@ local function colored_b(current,list,template,id,indent) end -- if not rule then - rule = new_rule(width-indent,height,depth) + rule = new_rule(width-indent,height+overshoot,depth+overshoot) setattributelist(rule,template) end - local back = new_kern(-((id == vlist_code and total) or width)) - return setlink(fore,rule,back,list) + if overshoot == 0 then + local back = new_kern(-((id == vlist_code and total) or width)) + return setlink(fore,rule,back,list) + else + rule = new_hlist(rule) + return setlink(fore,rule,list) + end end end @@ -137,11 +143,11 @@ local enabled = false local alignments = false local function add_alignbackgrounds(head,list) - for current in traverse_id(hlist_code,list) do + for current in nexthlist, list do if getsubtype(current) == cell_code then local list = getlist(current) if list then - for template in traverse_id(hlist_code,list) do + for template in nexthlist, list do local background = getattr(template,a_alignbackground) if background then local list = colored_a(current,list,template) @@ -166,11 +172,11 @@ end local function add_backgrounds(head,id,list) if list then - for current, id in traverse(list) do + for current, id, subtype in nextnode, list do if id == hlist_code or id == vlist_code then local list = getlist(current) if list then - if alignments and getsubtype(current) == alignment_code then + if alignments and subtype == alignment_code then local l = add_alignbackgrounds(current,list) if l then list = l @@ -197,16 +203,75 @@ local function add_backgrounds(head,id,list) end end +if LUATEXVERSION >= 1.090 then + + -- local function add_alignbackgrounds(head,list) + add_alignbackgrounds = function(head,list) + for current, id, subtype, list in nextlist, list do + if list and id == hlist_code and subtype == cell_code then + for template in nexthlist, list do + local background = getattr(template,a_alignbackground) + if background then + local list = colored_a(current,list,template) + if list then + setlist(current,list) + end + setattr(template,a_alignbackground,unsetvalue) -- or property + end + break + end + end + end + local template = getprop(head,"alignmentchecked") + if template then + list = colored_b(head,list,template[1],hlist_code,template[2]) + flush_node_list(template) + templates[currentrow] = false + return list + end + end + + -- local function add_backgrounds(head,id,list) + add_backgrounds = function(head,id,list) + if list then + for current, id, subtype, list in nextlist, list do + if list then + if alignments and subtype == alignment_code then + local l = add_alignbackgrounds(current,list) + if l then + list = l + setlist(current,list) + end + end + local l = add_backgrounds(current,id,list) + if l then + list = l + setlist(current,l) + end + end + end + end + if id == hlist_code or id == vlist_code then + local background = getattr(head,a_background) + if background then + list = colored_a(head,list,head,id) + -- not needed + setattr(head,a_background,unsetvalue) -- or property + return list + end + end + end + +end + function nodes.handlers.backgrounds(head) - local h = tonut(head) - add_backgrounds(h,getid(h),getlist(h)) - return head, true + add_backgrounds(head,getid(head),getlist(head)) + return head end function nodes.handlers.backgroundspage(head,where) if head and where == "alignment" then - local head = tonut(head) - for n in traverse_id(hlist_code,head) do + for n in nexthlist, head do local p = getprop(n,"alignmentchecked") if not p and getsubtype(n) == alignment_code then currentrow = currentrow + 1 @@ -218,25 +283,27 @@ function nodes.handlers.backgroundspage(head,where) end end end - return head, true + return head end function nodes.handlers.backgroundsvbox(head,where) if head and where == "vbox" then - local head = tonut(head) - for n in traverse_id(hlist_code,getlist(head)) do - local p = getprop(n,"alignmentchecked") - if not p and getsubtype(n) == alignment_code then - currentrow = currentrow + 1 - local template = templates[currentrow] - if trace_alignment then - report_alignment("%03i %s %s",currentrow,"vbox",template and "+" or "-") + local list = getlist(head) + if list then + for n in nexthlist, list do + local p = getprop(n,"alignmentchecked") + if not p and getsubtype(n) == alignment_code then + currentrow = currentrow + 1 + local template = templates[currentrow] + if trace_alignment then + report_alignment("%03i %s %s",currentrow,"vbox",template and "+" or "-") + end + setprop(n,"alignmentchecked",template) end - setprop(n,"alignmentchecked",template) end end end - return head, true + return head end -- interfaces.implement { diff --git a/tex/context/base/mkiv/node-fin.lua b/tex/context/base/mkiv/node-fin.lua index 975eb0bec..f7e2c7904 100644 --- a/tex/context/base/mkiv/node-fin.lua +++ b/tex/context/base/mkiv/node-fin.lua @@ -16,7 +16,6 @@ local next, type, format = next, type, string.format local attributes, nodes, node = attributes, nodes, node local nuts = nodes.nuts -local tonode = nuts.tonode local tonut = nuts.tonut local getnext = nuts.getnext @@ -34,6 +33,8 @@ local copy_node = nuts.copy local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after +local nextnode = nuts.traversers.node + local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes local rulecodes = nodes.rulecodes @@ -44,6 +45,7 @@ local glue_code = nodecodes.glue local rule_code = nodecodes.rule local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist +local localpar_code = nodecodes.localpar local states = attributes.states local numbers = attributes.numbers @@ -82,37 +84,34 @@ local finalizer = plugin.finalizer local flusher = plugin.flusher if not processor then return function(head) - return head, false + return head end elseif initializer or finalizer or resolver then return function(head) starttiming(attributes) - local done, used, ok, inheritance = false, nil, false, nil + local used, inheritance if resolver then inheritance = resolver() end if initializer then initializer(namespace,attribute,head) end - head, ok = processor(namespace,attribute,head,inheritance) - if ok then - if finalizer then - head, ok, used = finalizer(namespace,attribute,head) - if used and flusher then - head = flusher(namespace,attribute,head,used) - end + head = processor(namespace,attribute,head,inheritance) + if finalizer then + head, used = finalizer(namespace,attribute,head) + if used and flusher then + head = flusher(namespace,attribute,head,used) end - done = true end stoptiming(attributes) - return head, done + return head end else return function(head) starttiming(attributes) - local head, done = processor(namespace,attribute,head) + head = processor(namespace,attribute,head) stoptiming(attributes) - return head, done + return head end end nodes.plugindata = nil @@ -126,7 +125,7 @@ end -- the injectors local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger -local current, current_selector, done = 0, 0, false -- nb, stack has a local current ! +local current, current_selector = 0, 0 -- nb, stack has a local current ! local nsbegin, nsend, nsreset function states.initialize(namespace,attribute,head) @@ -138,7 +137,6 @@ function states.initialize(namespace,attribute,head) nstrigger = triggering and namespace.triggering and a_trigger current = 0 current_selector = 0 - done = false -- todo: done cleanup nsstep = namespace.resolve_step if nsstep then nsreset = namespace.resolve_reset @@ -151,7 +149,6 @@ end function states.finalize(namespace,attribute,head) -- is this one ok? if current > 0 and nsnone then - head = tonut(head) local id = getid(head) if id == hlist_code or id == vlist_code then local content = getlist(head) @@ -164,20 +161,114 @@ function states.finalize(namespace,attribute,head) -- is this one ok? else head = insert_node_before(head,head,copy_node(nsnone)) end - return tonode(head), true, true + return head, true end - return head, false, false + return head, false end -- we need to deal with literals too (reset as well as oval) +-- local function process(attribute,head,inheritance,default) -- one attribute +-- local stack = head +-- local check = false +-- local leader = nil +-- while stack do +-- local id = getid(stack) +-- if id == glyph_code or id == disc_code then +-- check = true -- disc no longer needed as we flatten replace +-- elseif id == glue_code then +-- leader = getleader(stack) +-- if leader then +-- check = true +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = getlist(stack) +-- if content then +-- -- begin nested -- +-- local list +-- if nstrigger and getattr(stack,nstrigger) then +-- local outer = getattr(stack,attribute) +-- if outer ~= inheritance then +-- list = process(attribute,content,inheritance,outer) +-- else +-- list = process(attribute,content,inheritance,default) +-- end +-- else +-- list = process(attribute,content,inheritance,default) +-- end +-- if content ~= list then +-- setlist(stack,list) +-- end +-- -- end nested -- +-- end +-- elseif id == rule_code then +-- check = getwidth(stack) ~= 0 +-- end +-- -- much faster this way than using a check() and nested() function +-- if check then +-- local c = getattr(stack,attribute) +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- end +-- elseif current ~= c then +-- head = insert_node_before(head,stack,copy_node(nsdata[c])) +-- current = c +-- end +-- if leader then +-- local savedcurrent = current +-- local ci = getid(leader) +-- if ci == hlist_code or ci == vlist_code then +-- -- else we reset inside a box unneeded, okay, the downside is +-- -- that we trigger color in each repeated box, so there is room +-- -- for improvement here +-- current = 0 +-- end +-- -- begin nested -- +-- local list +-- if nstrigger and getattr(stack,nstrigger) then +-- local outer = getattr(stack,attribute) +-- if outer ~= inheritance then +-- list = process(attribute,leader,inheritance,outer) +-- else +-- list = process(attribute,leader,inheritance,default) +-- end +-- else +-- list = process(attribute,leader,inheritance,default) +-- end +-- if leader ~= list then +-- setleader(stack,list) +-- end +-- -- end nested -- +-- current = savedcurrent +-- leader = false +-- end +-- elseif default and inheritance then +-- if current ~= default then +-- head = insert_node_before(head,stack,copy_node(nsdata[default])) +-- current = default +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current = 0 +-- end +-- check = false +-- end +-- stack = getnext(stack) +-- end +-- return head +-- end +-- +-- states.process = function(namespace,attribute,head,default) +-- return process(attribute,head,default) +-- end + local function process(attribute,head,inheritance,default) -- one attribute - local stack = head - local done = false local check = false local leader = nil - while stack do - local id = getid(stack) + for stack, id in nextnode, head do if id == glyph_code or id == disc_code then check = true -- disc no longer needed as we flatten replace elseif id == glue_code then @@ -189,33 +280,19 @@ local function process(attribute,head,inheritance,default) -- one attribute local content = getlist(stack) if content then -- begin nested -- + local list if nstrigger and getattr(stack,nstrigger) then local outer = getattr(stack,attribute) if outer ~= inheritance then - local list, ok = process(attribute,content,inheritance,outer) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = process(attribute,content,inheritance,outer) else - local list, ok = process(attribute,content,inheritance,default) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = process(attribute,content,inheritance,default) end else - local list, ok = process(attribute,content,inheritance,default) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = process(attribute,content,inheritance,default) + end + if content ~= list then + setlist(stack,list) end -- end nested -- end @@ -230,12 +307,10 @@ local function process(attribute,head,inheritance,default) -- one attribute if current ~= default then head = insert_node_before(head,stack,copy_node(nsdata[default])) current = default - done = true end elseif current ~= c then head = insert_node_before(head,stack,copy_node(nsdata[c])) current = c - done = true end if leader then local savedcurrent = current @@ -247,33 +322,19 @@ local function process(attribute,head,inheritance,default) -- one attribute current = 0 end -- begin nested -- + local list if nstrigger and getattr(stack,nstrigger) then local outer = getattr(stack,attribute) if outer ~= inheritance then - local list, ok = process(attribute,leader,inheritance,outer) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = process(attribute,leader,inheritance,outer) else - local list, ok = process(attribute,leader,inheritance,default) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = process(attribute,leader,inheritance,default) end else - local list, ok = process(attribute,leader,inheritance,default) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = process(attribute,leader,inheritance,default) + end + if leader ~= list then + setleader(stack,list) end -- end nested -- current = savedcurrent @@ -283,23 +344,19 @@ local function process(attribute,head,inheritance,default) -- one attribute if current ~= default then head = insert_node_before(head,stack,copy_node(nsdata[default])) current = default - done = true end elseif current > 0 then head = insert_node_before(head,stack,copy_node(nsnone)) current = 0 - done = true end check = false end - stack = getnext(stack) end - return head, done + return head end states.process = function(namespace,attribute,head,default) - local head, done = process(attribute,tonut(head),default) - return tonode(head), done + return process(attribute,head,default) end -- we can force a selector, e.g. document wide color spaces, saves a little @@ -308,14 +365,106 @@ end -- state changes while the main state stays the same (like two glyphs following -- each other with the same color but different color spaces e.g. \showcolor) +-- local function selective(attribute,head,inheritance,default) -- two attributes +-- local stack = head +-- local check = false +-- local leader = nil +-- while stack do +-- local id = getid(stack) +-- if id == glyph_code or id == disc_code then +-- check = true -- disc no longer needed as we flatten replace +-- elseif id == glue_code then +-- leader = getleader(stack) +-- if leader then +-- check = true +-- end +-- elseif id == hlist_code or id == vlist_code then +-- local content = getlist(stack) +-- if content then +-- -- begin nested +-- local list +-- if nstrigger and getattr(stack,nstrigger) then +-- local outer = getattr(stack,attribute) +-- if outer ~= inheritance then +-- list = selective(attribute,content,inheritance,outer) +-- else +-- list = selective(attribute,content,inheritance,default) +-- end +-- else +-- list = selective(attribute,content,inheritance,default) +-- end +-- if content ~= list then +-- setlist(stack,list) +-- end +-- -- end nested +-- end +-- elseif id == rule_code then +-- check = getwidth(stack) ~= 0 +-- end +-- +-- if check then +-- local c = getattr(stack,attribute) +-- if c then +-- if default and c == inheritance then +-- if current ~= default then +-- local data = nsdata[default] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector])) +-- current = default +-- end +-- else +-- local s = getattr(stack,nsselector) +-- -- local s = nsforced or getattr(stack,nsselector) +-- if current ~= c or current_selector ~= s then +-- local data = nsdata[c] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or s or nsselector])) +-- current = c +-- current_selector = s +-- end +-- end +-- if leader then +-- -- begin nested +-- local list +-- if nstrigger and getattr(stack,nstrigger) then +-- local outer = getattr(stack,attribute) +-- if outer ~= inheritance then +-- list = selective(attribute,leader,inheritance,outer) +-- else +-- list = selective(attribute,leader,inheritance,default) +-- end +-- else +-- list = selective(attribute,leader,inheritance,default) +-- end +-- if leader ~= list then +-- setleader(stack,list) +-- end +-- -- end nested +-- leader = false +-- end +-- elseif default and inheritance then +-- if current ~= default then +-- local data = nsdata[default] +-- head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector])) +-- current = default +-- end +-- elseif current > 0 then +-- head = insert_node_before(head,stack,copy_node(nsnone)) +-- current, current_selector = 0, 0 +-- end +-- check = false +-- end +-- stack = getnext(stack) +-- end +-- return head +-- end +-- +-- states.selective = function(namespace,attribute,head,default) +-- return selective(attribute,head,default) +-- end + local function selective(attribute,head,inheritance,default) -- two attributes - -- local head = head - local stack = head - local done = false local check = false local leader = nil - while stack do - local id = getid(stack) + for stack, id in nextnode, head do if id == glyph_code or id == disc_code then check = true -- disc no longer needed as we flatten replace elseif id == glue_code then @@ -327,33 +476,19 @@ local function selective(attribute,head,inheritance,default) -- two attributes local content = getlist(stack) if content then -- begin nested + local list if nstrigger and getattr(stack,nstrigger) then local outer = getattr(stack,attribute) if outer ~= inheritance then - local list, ok = selective(attribute,content,inheritance,outer) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = selective(attribute,content,inheritance,outer) else - local list, ok = selective(attribute,content,inheritance,default) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = selective(attribute,content,inheritance,default) end else - local list, ok = selective(attribute,content,inheritance,default) - if content ~= list then - setlist(stack,list) - end - if ok then - done = true - end + list = selective(attribute,content,inheritance,default) + end + if content ~= list then + setlist(stack,list) end -- end nested end @@ -369,9 +504,6 @@ local function selective(attribute,head,inheritance,default) -- two attributes local data = nsdata[default] head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector])) current = default - if ok then - done = true - end end else local s = getattr(stack,nsselector) @@ -379,43 +511,25 @@ local function selective(attribute,head,inheritance,default) -- two attributes if current ~= c or current_selector ~= s then local data = nsdata[c] head = insert_node_before(head,stack,copy_node(data[nsforced or s or nsselector])) - -- head = insert_node_before(head,stack,copy_node(data[s or nsselector])) current = c current_selector = s - if ok then - done = true - end end end if leader then -- begin nested + local list if nstrigger and getattr(stack,nstrigger) then local outer = getattr(stack,attribute) if outer ~= inheritance then - local list, ok = selective(attribute,leader,inheritance,outer) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = selective(attribute,leader,inheritance,outer) else - local list, ok = selective(attribute,leader,inheritance,default) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = selective(attribute,leader,inheritance,default) end else - local list, ok = selective(attribute,leader,inheritance,default) - if leader ~= list then - setleader(stack,list) - end - if ok then - done = true - end + list = selective(attribute,leader,inheritance,default) + end + if leader ~= list then + setleader(stack,list) end -- end nested leader = false @@ -425,22 +539,19 @@ local function selective(attribute,head,inheritance,default) -- two attributes local data = nsdata[default] head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector])) current = default - done = true end elseif current > 0 then head = insert_node_before(head,stack,copy_node(nsnone)) - current, current_selector, done = 0, 0, true + current, current_selector = 0, 0 end check = false end - stack = getnext(stack) end - return head, done + return head end states.selective = function(namespace,attribute,head,default) - local head = selective(attribute,tonut(head),default) - return tonode(head), true + return selective(attribute,head,default) end -- Ideally the next one should be merged with the previous but keeping it separate is @@ -454,7 +565,6 @@ end local function stacked(attribute,head,default) -- no triggering, no inheritance, but list-wise local stack = head - local done = false local current = default or 0 local depth = 0 local check = false @@ -472,36 +582,24 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance, local content = getlist(stack) if content then -- the problem is that broken lines gets the attribute which can be a later one + local list if nslistwise then local a = getattr(stack,attribute) if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below local p = current current = a head = insert_node_before(head,stack,copy_node(nsdata[a])) - local list = stacked(attribute,content,current) -- two return values - if content ~= list then - setlist(stack,list) - end + list = stacked(attribute,content,current) -- two return values head, stack = insert_node_after(head,stack,copy_node(nsnone)) current = p - done = true else - local list, ok = stacked(attribute,content,current) - if content ~= list then - setlist(stack,list) -- only if ok - end - if ok then - done = true - end + list = stacked(attribute,content,current) end else - local list, ok = stacked(attribute,content,current) - if content ~= list then - setlist(stack,list) -- only if ok - end - if ok then - done = true - end + list = stacked(attribute,content,current) + end + if content ~= list then + setlist(stack,list) -- only if ok end end elseif id == rule_code then @@ -515,16 +613,12 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance, head = insert_node_before(head,stack,copy_node(nsdata[a])) depth = depth + 1 current = a - done = true end if leader then - local list, ok = stacked(attribute,content,current) + local list = stacked(attribute,content,current) if leader ~= list then setleader(stack,list) -- only if ok end - if ok then - done = true - end leader = false end elseif default > 0 then @@ -533,7 +627,6 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance, head = insert_node_before(head,stack,copy_node(nsnone)) depth = depth - 1 current = 0 - done = true end check = false end @@ -543,24 +636,22 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance, head = insert_node_after(head,stack,copy_node(nsnone)) depth = depth - 1 end - return head, done + return head end states.stacked = function(namespace,attribute,head,default) - local head, done = stacked(attribute,tonut(head),default) - return tonode(head), done + return stacked(attribute,head,default) end -- experimental local function stacker(attribute,head,default) -- no triggering, no inheritance, but list-wise --- nsbegin() + -- nsbegin() local stacked = false local current = head local previous = head - local done = false local attrib = default or unsetvalue local check = false local leader = false @@ -576,35 +667,23 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance, end elseif id == hlist_code or id == vlist_code then local content = getlist(current) - if not content then - -- skip - elseif nslistwise then - local a = getattr(current,attribute) - if a and attrib ~= a and nslistwise[a] then -- viewerlayer - head = insert_node_before(head,current,copy_node(nsdata[a])) - local list = stacker(attribute,content,a) - if list ~= content then - setlist(current,list) + if content then + local list + if nslistwise then + local a = getattr(current,attribute) + if a and attrib ~= a and nslistwise[a] then -- viewerlayer + head = insert_node_before(head,current,copy_node(nsdata[a])) + list = stacker(attribute,content,a) + head, current = insert_node_after(head,current,copy_node(nsnone)) + else + list = stacker(attribute,content,attrib) end - done = true - head, current = insert_node_after(head,current,copy_node(nsnone)) else - local list, ok = stacker(attribute,content,attrib) - if content ~= list then - setlist(current,list) - end - if ok then - done = true - end + list = stacker(attribute,content,default) end - else - local list, ok = stacker(attribute,content,default) if list ~= content then setlist(current,list) end - if ok then - done = true - end end elseif id == rule_code then check = getwidth(current) ~= 0 @@ -622,13 +701,9 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance, head = insert_node_before(head,current,tonut(n)) -- a end attrib = a - done = true if leader then -- tricky as a leader has to be a list so we cannot inject before - local list, ok = stacker(attribute,leader,attrib) - if ok then - done = true - end + local list = stacker(attribute,leader,attrib) leader = false end end @@ -647,13 +722,13 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance, end end - return head, done + return head end states.stacker = function(namespace,attribute,head,default) - local head, done = stacker(attribute,tonut(head),default) + local head = stacker(attribute,head,default) nsreset() - return tonode(head), done + return head end -- -- -- diff --git a/tex/context/base/mkiv/node-fnt.lua b/tex/context/base/mkiv/node-fnt.lua index f846f996d..044be8ca8 100644 --- a/tex/context/base/mkiv/node-fnt.lua +++ b/tex/context/base/mkiv/node-fnt.lua @@ -40,8 +40,6 @@ local nodecodes = nodes.nodecodes local handlers = nodes.handlers local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getattr = nuts.getattr local getid = nuts.getid @@ -62,9 +60,12 @@ local setprev = nuts.setprev local isglyph = nuts.isglyph -- unchecked local ischar = nuts.ischar -- checked -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char -local protect_glyph = nuts.protect_glyph +----- traverse_id = nuts.traverse_id +----- traverse_char = nuts.traverse_char +local nextboundary = nuts.traversers.boundary +local nextdisc = nuts.traversers.disc +local nextchar = nuts.traversers.char + local flush_node = nuts.flush local disc_code = nodecodes.disc @@ -172,7 +173,7 @@ local function start_trace(head) report_fonts() report_fonts("checking node list, run %s",run) report_fonts() - local n = tonut(head) + local n = head while n do local char, id = isglyph(n) if char then @@ -212,10 +213,8 @@ function handlers.characters(head,groupcode,size,packtype,direction) local basefont = nil local prevfont = nil local prevattr = 0 - local done = false local variants = nil local redundant = nil - local nuthead = tonut(head) local lastfont = nil local lastproc = nil local lastnone = nil @@ -296,7 +295,7 @@ function handlers.characters(head,groupcode,size,packtype,direction) end end - for n in traverse_char(nuthead) do + for n in nextchar, head do local font = getfont(n) -- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context @@ -361,7 +360,7 @@ function handlers.characters(head,groupcode,size,packtype,direction) -- but we need to get rid of those nodes in order to build ligatures -- and kern (a rather context thing) - for b in traverse_id(boundary_code,nuthead) do + for b in nextboundary, head do if getsubtype(b) == word_boundary then if redundant then r = r + 1 @@ -379,8 +378,8 @@ function handlers.characters(head,groupcode,size,packtype,direction) for i=1,r do local r = redundant[i] local p, n = getboth(r) - if r == nuthead then - nuthead = n + if r == head then + head = n setprev(n) else setlink(p,n) @@ -411,7 +410,7 @@ function handlers.characters(head,groupcode,size,packtype,direction) -- basefont is not supported in disc only runs ... it would mean a lot of -- ranges .. we could try to run basemode as a separate processor run but -- not for now (we can consider it when the new node code is tested - for d in traverse_id(disc_code,nuthead) do + for d in nextdisc, head do -- we could use first_glyph, only doing replace is good enough because -- pre and post are normally used for hyphens and these come from fonts -- that part of the hyphenated word @@ -420,7 +419,7 @@ function handlers.characters(head,groupcode,size,packtype,direction) local prevfont = nil local prevattr = nil local none = false - for n in traverse_char(r) do + for n in nextchar, r do local font = getfont(n) local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context if font ~= prevfont or attr ~= prevattr then @@ -466,26 +465,14 @@ function handlers.characters(head,groupcode,size,packtype,direction) elseif u == 1 then local attr = a > 0 and 0 or false -- 0 is the savest way for i=1,#lastproc do - local h, d = lastproc[i](head,lastfont,attr,direction) - if d then - if h then - head = h - end - done = true - end + head = lastproc[i](head,lastfont,attr,direction) end else -- local attr = a == 0 and false or 0 -- 0 is the savest way local attr = a > 0 and 0 or false -- 0 is the savest way for font, processors in next, usedfonts do -- unordered for i=1,#processors do - local h, d = processors[i](head,font,attr,direction,u) - if d then - if h then - head = h - end - done = true - end + head = processors[i](head,font,attr,direction,u) end end end @@ -495,26 +482,14 @@ function handlers.characters(head,groupcode,size,packtype,direction) local font, dynamics = next(attrfonts) for attribute, processors in next, dynamics do -- unordered, attr can switch in between for i=1,#processors do - local h, d = processors[i](head,font,attribute,direction) - if d then - if h then - head = h - end - done = true - end + head = processors[i](head,font,attribute,direction) end end else for font, dynamics in next, attrfonts do for attribute, processors in next, dynamics do -- unordered, attr can switch in between for i=1,#processors do - local h, d = processors[i](head,font,attribute,direction,a) - if d then - if h then - head = h - end - done = true - end + head = processors[i](head,font,attribute,direction,a) end end end @@ -527,7 +502,7 @@ function handlers.characters(head,groupcode,size,packtype,direction) local start = range[1] local stop = range[2] if (start or stop) and (start ~= stop) then - local front = nuthead == start + local front = head == start if stop then start = ligaturing(start,stop) start = kerning(start,stop) @@ -535,9 +510,8 @@ function handlers.characters(head,groupcode,size,packtype,direction) start = ligaturing(start) start = kerning(start) end - if front and nuthead ~= start then - -- nuthead = start - head = tonode(start) + if front and head ~= start then + head = start end end else @@ -547,7 +521,7 @@ function handlers.characters(head,groupcode,size,packtype,direction) local start = range[1] local stop = range[2] if start then -- and start ~= stop but that seldom happens - local front = nuthead == start + local front = head == start local prev = getprev(start) local next = getnext(stop) if stop then @@ -565,19 +539,369 @@ function handlers.characters(head,groupcode,size,packtype,direction) setlink(stop,next) end -- till here - if front and nuthead ~= start then - nuthead = start - head = tonode(start) + if front and head ~= start then + head = start end end end end stoptiming(nodes) if trace_characters then - nodes.report(head,done) + nodes.report(head) + end + return head +end + +if LUATEXVERSION >= 1.090 then + + function handlers.characters(head,groupcode,size,packtype,direction) + -- either next or not, but definitely no already processed list + starttiming(nodes) + + local usedfonts = { } + local attrfonts = { } + local basefonts = { } + local basefont = nil + local prevfont = nil + local prevattr = 0 + local variants = nil + local redundant = nil + local lastfont = nil + local lastproc = nil + local lastnone = nil + + local a, u, b, r, e = 0, 0, 0, 0, 0 + + if trace_fontrun then + start_trace(head) + end + + -- There is no gain in checking for a single glyph and then having a fast path. On the + -- metafun manual (with some 2500 single char lists) the difference is just noise. + + local function protectnone() + protect_glyphs(firstnone,lastnone) + firstnone = nil + end + + local function setnone(n) + if firstnone then + protectnone() + end + if basefont then + basefont[2] = getprev(n) + basefont = false + end + if not firstnone then + firstnone = n + end + lastnone = n + end + + local function setbase(n) + if firstnone then + protectnone() + end + if force_basepass then + if basefont then + basefont[2] = getprev(n) + end + b = b + 1 + basefont = { n, false } + basefonts[b] = basefont + end + end + + local function setnode(n,font,attr) -- we could use prevfont and prevattr when we set then first + if firstnone then + protectnone() + end + if basefont then + basefont[2] = getprev(n) + basefont = false + end + if attr > 0 then + local used = attrfonts[font] + if not used then + used = { } + attrfonts[font] = used + end + if not used[attr] then + local fd = setfontdynamics[font] + if fd then + used[attr] = fd[attr] + a = a + 1 + end + end + else + local used = usedfonts[font] + if not used then + lastfont = font + lastproc = fontprocesses[font] + if lastproc then + usedfonts[font] = lastproc + u = u + 1 + end + end + end + end + + for n, char, font in nextchar, head do + -- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context + local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context + if font ~= prevfont or attr ~= prevattr then + prevfont = font + prevattr = attr + variants = fontvariants[font] + local fontmode = fontmodes[font] + if fontmode == "none" then + setnone(n) + elseif fontmode == "base" then + setbase(n) + else + setnode(n,font,attr) + end + elseif firstnone then + lastnone = n + end + if variants then + if char >= 0xFE00 and (char <= 0xFE0F or (char >= 0xE0100 and char <= 0xE01EF)) then + local hash = variants[char] + if hash then + local p = getprev(n) + if p then + local char = ischar(p) -- checked + local variant = hash[char] + if variant then + if trace_variants then + report_fonts("replacing %C by %C",char,variant) + end + setchar(p,variant) + if redundant then + r = r + 1 + redundant[r] = n + else + r = 1 + redundant = { n } + end + end + end + elseif keep_redundant then + -- go on, can be used for tracing + elseif redundant then + r = r + 1 + redundant[r] = n + else + r = 1 + redundant = { n } + end + end + end + end + + if firstnone then + protectnone() + end + + if force_boundaryrun then + + -- we can inject wordboundaries and then let the hyphenator do its work + -- but we need to get rid of those nodes in order to build ligatures + -- and kern (a rather context thing) + + for b, subtype in nextboundary, head do + if subtype == word_boundary then + if redundant then + r = r + 1 + redundant[r] = b + else + r = 1 + redundant = { b } + end + end + end + + end + + if redundant then + for i=1,r do + local r = redundant[i] + local p, n = getboth(r) + if r == head then + head = n + setprev(n) + else + setlink(p,n) + end + if b > 0 then + for i=1,b do + local bi = basefonts[i] + local b1 = bi[1] + local b2 = bi[2] + if b1 == b2 then + if b1 == r then + bi[1] = false + bi[2] = false + end + elseif b1 == r then + bi[1] = n + elseif b2 == r then + bi[2] = p + end + end + end + flush_node(r) + end + end + + if force_discrun then + + -- basefont is not supported in disc only runs ... it would mean a lot of + -- ranges .. we could try to run basemode as a separate processor run but + -- not for now (we can consider it when the new node code is tested + for d in nextdisc, head do + -- we could use first_glyph, only doing replace is good enough because + -- pre and post are normally used for hyphens and these come from fonts + -- that part of the hyphenated word + local _, _, r = getdisc(d) + if r then + local prevfont = nil + local prevattr = nil + local none = false + for n, char, font in nextchar, r do + local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context + if font ~= prevfont or attr ~= prevattr then + prevfont = font + prevattr = attr + local fontmode = fontmodes[font] + if fontmode == "none" then + setnone(n) + elseif fontmode == "base" then + setbase(n) + else + setnode(n,font,attr) + end + elseif firstnone then + -- lastnone = n + lastnone = nil + end + -- we assume one font for now (and if there are more and we get into issues then + -- we can always remove the break) + break + end + if firstnone then + protectnone() + end + -- elseif expanders then + -- local subtype = getsubtype(d) + -- if subtype == automatic_code or subtype == explicit_code then + -- expanders[subtype](d) + -- e = e + 1 + -- end + end + end + + end + + if trace_fontrun then + stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expanders) + end + + -- in context we always have at least 2 processors + if u == 0 then + -- skip + elseif u == 1 then + local attr = a > 0 and 0 or false -- 0 is the savest way + for i=1,#lastproc do + head = lastproc[i](head,lastfont,attr,direction) + end + else + -- local attr = a == 0 and false or 0 -- 0 is the savest way + local attr = a > 0 and 0 or false -- 0 is the savest way + for font, processors in next, usedfonts do -- unordered + for i=1,#processors do + head = processors[i](head,font,attr,direction,u) + end + end + end + if a == 0 then + -- skip + elseif a == 1 then + local font, dynamics = next(attrfonts) + for attribute, processors in next, dynamics do -- unordered, attr can switch in between + for i=1,#processors do + head = processors[i](head,font,attribute,direction) + end + end + else + for font, dynamics in next, attrfonts do + for attribute, processors in next, dynamics do -- unordered, attr can switch in between + for i=1,#processors do + head = processors[i](head,font,attribute,direction,a) + end + end + end + end + if b == 0 then + -- skip + elseif b == 1 then + -- only one font + local range = basefonts[1] + local start = range[1] + local stop = range[2] + if (start or stop) and (start ~= stop) then + local front = head == start + if stop then + start = ligaturing(start,stop) + start = kerning(start,stop) + elseif start then -- safeguard + start = ligaturing(start) + start = kerning(start) + end + if front and head ~= start then + head = start + end + end + else + -- multiple fonts + for i=1,b do + local range = basefonts[i] + local start = range[1] + local stop = range[2] + if start then -- and start ~= stop but that seldom happens + local front = head == start + local prev = getprev(start) + local next = getnext(stop) + if stop then + start, stop = ligaturing(start,stop) + start, stop = kerning(start,stop) + else + start = ligaturing(start) + start = kerning(start) + end + -- is done automatically + if prev then + setlink(prev,start) + end + if next then + setlink(stop,next) + end + -- till here + if front and head ~= start then + head = start + end + end + end + end + stoptiming(nodes) + if trace_characters then + nodes.report(head) + end + return head end - return head, true + end -handlers.protectglyphs = function(n) protect_glyphs (tonut(n)) return n, true end -handlers.unprotectglyphs = function(n) unprotect_glyphs(tonut(n)) return n, true end + +handlers.protectglyphs = protect_glyphs +handlers.unprotectglyphs = unprotect_glyphs diff --git a/tex/context/base/mkiv/node-ltp.lua b/tex/context/base/mkiv/node-ltp.lua index 865f69c2c..c51298b4e 100644 --- a/tex/context/base/mkiv/node-ltp.lua +++ b/tex/context/base/mkiv/node-ltp.lua @@ -191,7 +191,6 @@ local parameters = fonthashes.parameters local nuts = nodes.nuts local tonut = nuts.tonut -local tonode = nuts.tonode local getfield = nuts.getfield local getid = nuts.getid @@ -2148,8 +2147,6 @@ local dcolor = { [0] = "red", "green", "blue", "magenta", "cyan", "gray" } local temp_head = new_temp() function constructors.methods.basic(head,d) - head = tonut(head) - if trace_basic then report_parbuilders("starting at %a",head) end @@ -2455,7 +2452,7 @@ function constructors.methods.basic(head,d) par.best_line = par.best_bet.line_number local asked_looseness = par.looseness if asked_looseness == 0 then - return tonode(wrap_up(par)) + return wrap_up(par) end local r = n_active local actual_looseness = 0 @@ -2478,7 +2475,7 @@ function constructors.methods.basic(head,d) until r == p_active par.best_line = par.best_bet.line_number if actual_looseness == asked_looseness or par.final_pass then - return tonode(wrap_up(par)) + return wrap_up(par) end end end @@ -2498,7 +2495,7 @@ function constructors.methods.basic(head,d) par.final_pass = true end end - return tonode(wrap_up(par)) + return wrap_up(par) end -- standard tex logging .. will be adapted .. diff --git a/tex/context/base/mkiv/node-met.lua b/tex/context/base/mkiv/node-met.lua index 4141c8b66..3ec03458d 100644 --- a/tex/context/base/mkiv/node-met.lua +++ b/tex/context/base/mkiv/node-met.lua @@ -88,65 +88,69 @@ end nodes = nodes or { } local nodes = nodes -local nodecodes = nodes.nodecodes - -nodes.tostring = node.tostring or tostring -nodes.copy = node.copy -nodes.copy_node = node.copy -nodes.copy_list = node.copy_list -nodes.delete = node.delete -nodes.dimensions = node.dimensions -nodes.rangedimensions = node.rangedimensions -nodes.end_of_math = node.end_of_math -nodes.flush = node.flush_node -nodes.flush_node = node.flush_node -nodes.flush_list = node.flush_list -nodes.free = node.free -nodes.insert_after = node.insert_after -nodes.insert_before = node.insert_before -nodes.hpack = node.hpack -nodes.new = node.new -nodes.tail = node.tail -nodes.traverse = node.traverse -nodes.traverse_id = node.traverse_id -nodes.traverse_char = node.traverse_char -nodes.slide = node.slide -nodes.vpack = node.vpack -nodes.fields = node.fields -nodes.is_node = node.is_node -nodes.setglue = node.setglue - -nodes.first_glyph = node.first_glyph -nodes.has_glyph = node.has_glyph or node.first_glyph - -nodes.current_attr = node.current_attr -nodes.has_field = node.has_field -nodes.last_node = node.last_node -nodes.usedlist = node.usedlist -nodes.protrusion_skippable = node.protrusion_skippable -nodes.check_discretionaries = node.check_discretionaries -nodes.write = node.write - -nodes.count = node.count -nodes.length = node.length - -nodes.has_attribute = node.has_attribute -nodes.set_attribute = node.set_attribute -nodes.find_attribute = node.find_attribute -nodes.unset_attribute = node.unset_attribute - -nodes.protect_glyph = node.protect_glyph -nodes.protect_glyphs = node.protect_glyphs -nodes.unprotect_glyph = node.unprotect_glyph -nodes.unprotect_glyphs = node.unprotect_glyphs -nodes.kerning = node.kerning -nodes.ligaturing = node.ligaturing -nodes.mlist_to_hlist = node.mlist_to_hlist - -nodes.effective_glue = node.effective_glue -nodes.getglue = node.getglue -nodes.setglue = node.setglue -nodes.is_zero_glue = node.is_zero_glue +local nodecodes = nodes.nodecodes + +nodes.tostring = node.tostring or tostring +nodes.copy = node.copy +nodes.copy_node = node.copy +nodes.copy_list = node.copy_list +nodes.delete = node.delete +nodes.dimensions = node.dimensions +nodes.rangedimensions = node.rangedimensions +nodes.end_of_math = node.end_of_math +nodes.flush = node.flush_node +nodes.flush_node = node.flush_node +nodes.flush_list = node.flush_list +nodes.free = node.free +nodes.insert_after = node.insert_after +nodes.insert_before = node.insert_before +nodes.hpack = node.hpack +nodes.new = node.new +nodes.tail = node.tail +nodes.traverse = node.traverse +nodes.traverse_id = node.traverse_id +nodes.traverse_char = node.traverse_char +nodes.traverse_glyph = node.traverse_glyph +nodes.traverse_list = node.traverse_list +nodes.slide = node.slide +nodes.vpack = node.vpack +nodes.fields = node.fields +nodes.is_node = node.is_node +nodes.setglue = node.setglue +nodes.uses_font = node.uses_font + +nodes.first_glyph = node.first_glyph +nodes.has_glyph = node.has_glyph or node.first_glyph + +nodes.current_attr = node.current_attr +nodes.has_field = node.has_field +nodes.last_node = node.last_node +nodes.usedlist = node.usedlist +nodes.protrusion_skippable = node.protrusion_skippable +nodes.check_discretionaries = node.check_discretionaries +nodes.write = node.write +nodes.flatten_discretionaries = node.flatten_discretionaries + +nodes.count = node.count +nodes.length = node.length + +nodes.has_attribute = node.has_attribute +nodes.set_attribute = node.set_attribute +nodes.find_attribute = node.find_attribute +nodes.unset_attribute = node.unset_attribute + +nodes.protect_glyph = node.protect_glyph +nodes.protect_glyphs = node.protect_glyphs +nodes.unprotect_glyph = node.unprotect_glyph +nodes.unprotect_glyphs = node.unprotect_glyphs +nodes.kerning = node.kerning +nodes.ligaturing = node.ligaturing +nodes.mlist_to_hlist = node.mlist_to_hlist + +nodes.effective_glue = node.effective_glue +nodes.getglue = node.getglue +nodes.setglue = node.setglue +nodes.is_zero_glue = node.is_zero_glue nodes.tonode = function(n) return n end nodes.tonut = function(n) return n end diff --git a/tex/context/base/mkiv/node-mig.lua b/tex/context/base/mkiv/node-mig.lua index b3820a7d8..32b09a186 100644 --- a/tex/context/base/mkiv/node-mig.lua +++ b/tex/context/base/mkiv/node-mig.lua @@ -89,12 +89,11 @@ local function locate(head,first,last,ni,nm) end function nodes.handlers.migrate(head,where) - local done = false if head then if trace_migrations then report_nodes("migration sweep %a",where) end - local current = tonut(head) + local current = head while current do local id = getid(current) -- inserts_too is a temp hack, we should only do them when it concerns @@ -124,13 +123,12 @@ function nodes.handlers.migrate(head,where) setlink(last,n) end setlink(current,first) - done = true current = last end end current = getnext(next) end - return head, done + return head end end diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua index 282a37e2e..b970a46af 100644 --- a/tex/context/base/mkiv/node-nut.lua +++ b/tex/context/base/mkiv/node-nut.lua @@ -96,6 +96,7 @@ local fastcopy = table.fastcopy local nodecodes = nodes.nodecodes local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist +local glyph_code = nodecodes.glyph local nuts = nodes.nuts or { } nodes.nuts = nuts @@ -174,17 +175,25 @@ if not direct.getdirection then end -if LUATEXFUNCTIONALITY < 6695 then +if not node.direct.traverse_glyph or not node.direct.traverse_list then - local getnext = direct.getnext - local getid = direct.getid + logs.report("system","using fake node list traversers") + + local getnext = node.direct.getnext + local getid = node.direct.getid + local getsubtype = node.direct.getsubtype + local getchar = node.direct.getchar + local getfont = node.direct.getfont + local getlist = node.direct.getlist local function iterate(h,n) if n then - local n = getnext(n) - return n, getid(n) - elseif h then - return h, getid(h), getnext(h) + n = getnext(n) + else + n = h + end + if n then + return n, getid(n), getsubtype(n) end end @@ -192,68 +201,147 @@ if LUATEXFUNCTIONALITY < 6695 then return iterate, h end + function node.direct.traverse_id(id,h) + local function iterate(h,n) + if n then + n = getnext(n) + else + n = h + end + while n do + if getid(n) == id then + return n, getsubtype(n) + else + n = getnext(n) + end + end + end + return iterate, h + end + + local function iterate(h,n) + if n then + n = getnext(n) + else + n = h + end + while n do + if getid(n) == glyph_code then + return n, getfont(n), getchar(n) + else + n = getnext(n) + end + end + end + + function node.direct.traverse_glyph(h) + return iterate, h + end + + local function iterate(h,n) + if n then + n = getnext(n) + else + n = h + end + while n do + if getid(n) == glyph_code and subtype(n) < 256 then + return n, getfont(n), getchar(n) + else + n = getnext(n) + end + end + end + + function node.direct.traverse_char(h) + return iterate, h + end + + local function iterate(h,n) + if n then + n = getnext(n) + else + n = h + end + while n do + local id = getid(n) + if id == hlist_code or id == vlist_code then + return n, id, getsubtype(n), getlist(n) + else + n = getnext(n) + end + end + end + + function node.direct.traverse_list(h) + return iterate, h + end + end -local nuts = nodes.nuts - -nuts.tostring = direct.tostring -nuts.copy = direct.copy -nuts.copy_node = direct.copy -nuts.copy_list = direct.copy_list -nuts.delete = direct.delete -nuts.dimensions = direct.dimensions -nuts.rangedimensions = direct.rangedimensions -nuts.end_of_math = direct.end_of_math -nuts.flush = direct.flush_node -nuts.flush_node = direct.flush_node -nuts.flush_list = direct.flush_list -nuts.free = direct.free -nuts.insert_after = direct.insert_after -nuts.insert_before = direct.insert_before -nuts.hpack = direct.hpack -nuts.new = direct.new -nuts.tail = direct.tail -nuts.traverse = direct.traverse -nuts.traverse_id = direct.traverse_id -nuts.traverse_char = direct.traverse_char -nuts.slide = direct.slide -nuts.writable_spec = direct.writable_spec -nuts.vpack = direct.vpack -nuts.is_node = direct.is_node -nuts.is_direct = direct.is_direct -nuts.is_nut = direct.is_direct -nuts.first_glyph = direct.first_glyph -nuts.has_glyph = direct.has_glyph or direct.first_glyph -nuts.count = direct.count -nuts.length = direct.length -nuts.find_attribute = direct.find_attribute -nuts.unset_attribute = direct.unset_attribute - -nuts.current_attr = direct.current_attr -nuts.has_field = direct.has_field -nuts.last_node = direct.last_node -nuts.usedlist = direct.usedlist -nuts.protrusion_skippable = direct.protrusion_skippable -nuts.check_discretionaries = direct.check_discretionaries -nuts.write = direct.write - -nuts.has_attribute = direct.has_attribute -nuts.set_attribute = direct.set_attribute -nuts.unset_attribute = direct.unset_attribute - -nuts.protect_glyph = direct.protect_glyph -nuts.protect_glyphs = direct.protect_glyphs -nuts.unprotect_glyph = direct.unprotect_glyph -nuts.unprotect_glyphs = direct.unprotect_glyphs -nuts.ligaturing = direct.ligaturing -nuts.kerning = direct.kerning +local nuts = nodes.nuts + +nuts.check_discretionaries = direct.check_discretionaries +nuts.copy = direct.copy +nuts.copy_list = direct.copy_list +nuts.copy_node = direct.copy +nuts.count = direct.count +nuts.current_attr = direct.current_attr +nuts.delete = direct.delete +nuts.dimensions = direct.dimensions +nuts.end_of_math = direct.end_of_math +nuts.find_attribute = direct.find_attribute +nuts.first_glyph = direct.first_glyph +nuts.flatten_discretionaries = direct.flatten_discretionaries +nuts.flush = direct.flush_node +nuts.flush_list = direct.flush_list +nuts.flush_node = direct.flush_node +nuts.free = direct.free +nuts.get_synctex_fields = direct.get_synctex_fields +nuts.has_attribute = direct.has_attribute +nuts.has_field = direct.has_field +nuts.has_glyph = direct.has_glyph or direct.first_glyph +nuts.hpack = direct.hpack +nuts.insert_after = direct.insert_after +nuts.insert_before = direct.insert_before +nuts.is_direct = direct.is_direct +nuts.is_node = direct.is_node +nuts.is_nut = direct.is_direct +nuts.kerning = direct.kerning +nuts.last_node = direct.last_node +nuts.length = direct.length +nuts.ligaturing = direct.ligaturing +nuts.new = direct.new +nuts.protect_glyph = direct.protect_glyph +nuts.protect_glyphs = direct.protect_glyphs +nuts.protrusion_skippable = direct.protrusion_skippable +nuts.rangedimensions = direct.rangedimensions +nuts.set_attribute = direct.set_attribute +nuts.set_synctex_fields = direct.set_synctex_fields +nuts.slide = direct.slide +nuts.tail = direct.tail +nuts.tostring = direct.tostring +nuts.traverse = direct.traverse +nuts.traverse_char = direct.traverse_char +nuts.traverse_glyph = direct.traverse_glyph +nuts.traverse_id = direct.traverse_id +nuts.traverse_list = direct.traverse_list +nuts.unprotect_glyph = direct.unprotect_glyph +nuts.unprotect_glyphs = direct.unprotect_glyphs +nuts.unset_attribute = direct.unset_attribute +nuts.unset_attribute = direct.unset_attribute +nuts.usedlist = direct.usedlist +nuts.uses_font = direct.uses_font +nuts.vpack = direct.vpack +nuts.writable_spec = direct.writable_spec +nuts.write = direct.write if not direct.mlist_to_hlist then -- needed local n_mlist_to_hlist = node.mlist_to_hlist function nuts.mlist_to_hlist(head) - return tonode(n_mlist_to_hlist(tonut(head))) + return n_mlist_to_hlist(tonut(head)) end end @@ -825,115 +913,3 @@ function nuts.copy_properties(source,target,what) return newprops -- for checking end --- here: - -nuts.get_synctex_fields = direct.get_synctex_fields -nuts.set_synctex_fields = direct.set_synctex_fields - --- for now - -nodes.uses_font = nodes.uses_font -nuts.uses_font = direct.uses_font - -if not nuts.uses_font then - - local glyph_code = nodecodes.glyph - local getdisc = nuts.getdisc - local getfont = nuts.getfont - local traverse_id = nuts.traverse_id - local tonut = nodes.tonut - - function nuts.uses_font(n,font) - local pre, post, replace = getdisc(n) - if pre then - -- traverse_char - for n in traverse_id(glyph_code,pre) do - if getfont(n) == font then - return true - end - end - end - if post then - for n in traverse_id(glyph_code,post) do - if getfont(n) == font then - return true - end - end - end - if replace then - for n in traverse_id(glyph_code,replace) do - if getfont(n) == font then - return true - end - end - end - return false - end - - function nodes.uses_font(n,font) - return nuts.uses_font(tonut(n),font) - end - -end - --- for the moment (pre 6380) - -if not nuts.unprotect_glyph then - - local protect_glyph = nuts.protect_glyph - local protect_glyphs = nuts.protect_glyphs - local unprotect_glyph = nuts.unprotect_glyph - local unprotect_glyphs = nuts.unprotect_glyphs - - local getnext = nuts.getnext - local setnext = nuts.setnext - - function nuts.protectglyphs(first,last) - if first == last then - return protect_glyph(first) - elseif last then - local nxt = getnext(last) - setnext(last) - local f, b = protect_glyphs(first) - setnext(last,nxt) - return f, b - else - return protect_glyphs(first) - end - end - - function nuts.unprotectglyphs(first,last) - if first == last then - return unprotect_glyph(first) - elseif last then - local nxt = getnext(last) - setnext(last) - local f, b = unprotect_glyphs(first) - setnext(last,nxt) - return f, b - else - return unprotect_glyphs(first) - end - end - -end - -if LUATEXFUNCTIONALITY < 6384 then -- LUATEXVERSION < 1.070 - - local getfield = nuts.getfield - local setfield = nuts.setfield - - function nuts.getboxglue(n,glue_set,glue_order,glue_sign) - return - getfield(n,"glue_set"), - getfield(n,"glue_order"), - getfield(n,"glue_sign") - end - - function nuts.setboxglue(n,glue_set,glue_order,glue_sign) - setfield(n,"glue_set", glue_set or 0) - setfield(n,"glue_order",glue_order or 0) - setfield(n,"glue_sign", glue_sign or 0) - end - -end diff --git a/tex/context/base/mkiv/node-ppt.lua b/tex/context/base/mkiv/node-ppt.lua index 5ebfca87d..0124f885b 100644 --- a/tex/context/base/mkiv/node-ppt.lua +++ b/tex/context/base/mkiv/node-ppt.lua @@ -30,8 +30,9 @@ local getfield = nuts.getfield local getlist = nuts.getlist local setlist = nuts.setlist local removenode = nuts.remove -local traverse = nuts.traverse -local traverse_id = nuts.traverse_id + +local nextnode = nuts.traversers.node +local nextwhatsit = nuts.traversers.whatsit local nodecodes = nodes.nodecodes local whatsitcodes = nodes.whatsitcodes @@ -193,7 +194,7 @@ end -- maybe actions will get parent too local function delayed(head,parent) -- direct based - for target in traverse(head) do + for target, id in nextnode, head do local p = propertydata[target] if p then -- local deferred = p.deferred -- kind of late lua (but too soon as we have no access to pdf.h/v) @@ -244,7 +245,6 @@ local function delayed(head,parent) -- direct based end -- end end - local id = getid(target) if id == hlist_code or id == vlist_code then local list = getlist(target) if list then @@ -268,14 +268,13 @@ function properties.delayed(head) -- if nofdelayed > 0 then -- if next(propertydata) then starttiming(properties) - head = delayed(tonut(head)) + head = delayed(head) stoptiming(properties) - return tonode(head), true -- done in shipout anyway -- else -- delayed = 0 - -- end + -- end end - return head, false + return head end -- more explicit ones too @@ -317,102 +316,203 @@ table.setmetatableindex(anchored,function(t,k) return v end) -function properties.attach(head) +-- function properties.attach(head) +-- +-- if nofslots <= 0 then +-- return head +-- end +-- +-- local last = nil +-- +-- starttiming(properties) +-- +-- for source in nextwhatsit, head do +-- if getsubtype(source) == userdefined_code then +-- if last then +-- removenode(head,last,true) +-- last = nil +-- end +-- if getfield(source,"user_id") == property_id then +-- local slot = getfield(source,"value") +-- local data = cache[slot] +-- if data then +-- cache[slot] = nil +-- local where = data[1] +-- local target = anchored[where](source) +-- if target then +-- local first = data[2] +-- local method = type(first) +-- local p_target = propertydata[target] +-- local p_source = propertydata[source] +-- if p_target then +-- if p_source then +-- for k, v in next, p_source do +-- p_target[k] = v +-- end +-- end +-- if method == "table" then +-- for k, v in next, first do +-- p_target[k] = v +-- end +-- elseif method == "function" then +-- first(target,head,where,p_target,unpack(data,3)) +-- elseif method == "string" then +-- actions[first](target,head,where,p_target,unpack(data,3)) +-- end +-- elseif p_source then +-- if method == "table" then +-- propertydata[target] = p_source +-- for k, v in next, first do +-- p_source[k] = v +-- end +-- elseif method == "function" then +-- propertydata[target] = p_source +-- first(target,head,where,p_source,unpack(data,3)) +-- elseif method == "string" then +-- propertydata[target] = p_source +-- actions[first](target,head,where,p_source,unpack(data,3)) +-- end +-- else +-- if method == "table" then +-- propertydata[target] = first +-- elseif method == "function" then +-- local t = { } +-- propertydata[target] = t +-- first(target,head,where,t,unpack(data,3)) +-- elseif method == "string" then +-- local t = { } +-- propertydata[target] = t +-- actions[first](target,head,where,t,unpack(data,3)) +-- end +-- end +-- if trace_setting then +-- report_setting("node %i, id %s, data %s", +-- target,nodecodes[getid(target)],serialize(propertydata[target],false)) +-- end +-- end +-- if nofslots == 1 then +-- nofslots = 0 +-- last = source +-- break +-- else +-- nofslots = nofslots - 1 +-- end +-- end +-- last = source +-- end +-- end +-- end +-- +-- if last then +-- removenode(head,last,true) +-- end +-- +-- stoptiming(properties) +-- +-- return head +-- +-- end - if nofslots <= 0 then - return head, false - end +if LUATEXVERSION >= 1.090 then + + function properties.attach(head) - local done = false - local last = nil - local head = tonut(head) + if nofslots <= 0 then + return head + end - starttiming(properties) + local last = nil - for source in traverse_id(whatsit_code,head) do - if getsubtype(source) == userdefined_code then - if last then - removenode(head,last,true) - last = nil - end - if getfield(source,"user_id") == property_id then - local slot = getfield(source,"value") - local data = cache[slot] - if data then - cache[slot] = nil - local where = data[1] - local target = anchored[where](source) - if target then - local first = data[2] - local method = type(first) - local p_target = propertydata[target] - local p_source = propertydata[source] - if p_target then - if p_source then - for k, v in next, p_source do - p_target[k] = v + starttiming(properties) + + for source, subtype in nextwhatsit, head do + if subtype == userdefined_code then + if last then + removenode(head,last,true) + last = nil + end + if getfield(source,"user_id") == property_id then + local slot = getfield(source,"value") + local data = cache[slot] + if data then + cache[slot] = nil + local where = data[1] + local target = anchored[where](source) + if target then + local first = data[2] + local method = type(first) + local p_target = propertydata[target] + local p_source = propertydata[source] + if p_target then + if p_source then + for k, v in next, p_source do + p_target[k] = v + end end - end - if method == "table" then - for k, v in next, first do - p_target[k] = v + if method == "table" then + for k, v in next, first do + p_target[k] = v + end + elseif method == "function" then + first(target,head,where,p_target,unpack(data,3)) + elseif method == "string" then + actions[first](target,head,where,p_target,unpack(data,3)) end - elseif method == "function" then - first(target,head,where,p_target,unpack(data,3)) - elseif method == "string" then - actions[first](target,head,where,p_target,unpack(data,3)) - end - elseif p_source then - if method == "table" then - propertydata[target] = p_source - for k, v in next, first do - p_source[k] = v + elseif p_source then + if method == "table" then + propertydata[target] = p_source + for k, v in next, first do + p_source[k] = v + end + elseif method == "function" then + propertydata[target] = p_source + first(target,head,where,p_source,unpack(data,3)) + elseif method == "string" then + propertydata[target] = p_source + actions[first](target,head,where,p_source,unpack(data,3)) + end + else + if method == "table" then + propertydata[target] = first + elseif method == "function" then + local t = { } + propertydata[target] = t + first(target,head,where,t,unpack(data,3)) + elseif method == "string" then + local t = { } + propertydata[target] = t + actions[first](target,head,where,t,unpack(data,3)) end - elseif method == "function" then - propertydata[target] = p_source - first(target,head,where,p_source,unpack(data,3)) - elseif method == "string" then - propertydata[target] = p_source - actions[first](target,head,where,p_source,unpack(data,3)) end - else - if method == "table" then - propertydata[target] = first - elseif method == "function" then - local t = { } - propertydata[target] = t - first(target,head,where,t,unpack(data,3)) - elseif method == "string" then - local t = { } - propertydata[target] = t - actions[first](target,head,where,t,unpack(data,3)) + if trace_setting then + report_setting("node %i, id %s, data %s", + target,nodecodes[getid(target)],serialize(propertydata[target],false)) end end - if trace_setting then - report_setting("node %i, id %s, data %s", - target,nodecodes[getid(target)],serialize(propertydata[target],false)) + if nofslots == 1 then + nofslots = 0 + last = source + break + else + nofslots = nofslots - 1 end end - if nofslots == 1 then - nofslots = 0 - last = source - break - else - nofslots = nofslots - 1 - end + last = source end - last = source end end - end - if last then - removenode(head,last,true) - end + if last then + removenode(head,last,true) + end - stoptiming(properties) + stoptiming(properties) - return head, done + return head + + end + +local tasks = nodes.tasks end @@ -420,9 +520,6 @@ local tasks = nodes.tasks -- maybe better hard coded in-place --- tasks.prependaction("processors","before","nodes.properties.attach") --- tasks.appendaction("shipouts","normalizers","nodes.properties.delayed") - statistics.register("properties processing time", function() return statistics.elapsedseconds(properties) end) @@ -430,7 +527,7 @@ end) -- only for development -- local function show(head,level,report) --- for target in traverse(head) do +-- for target in nextnode, head do -- local p = propertydata[target] -- if p then -- report("level %i, node %i, id %s, data %s", diff --git a/tex/context/base/mkiv/node-pro.lua b/tex/context/base/mkiv/node-pro.lua index ad4553b56..ad1035bbc 100644 --- a/tex/context/base/mkiv/node-pro.lua +++ b/tex/context/base/mkiv/node-pro.lua @@ -35,7 +35,7 @@ do local n = 0 local function reconstruct(head) -- we probably have a better one - local t, n, h = { }, 0, tonut(head) + local t, n, h = { }, 0, head while h do n = n + 1 local char, id = isglyph(h) @@ -49,7 +49,7 @@ do return concat(t) end - function processors.tracer(what,state,head,groupcode,before,after,show) + function processors.tracer(what,head,groupcode,before,after,show) if not groupcode then groupcode = "unknown" elseif groupcode == "" then @@ -57,9 +57,9 @@ do end n = n + 1 if show then - report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s, stream: %s",what,n,state,groupcode,before,after,reconstruct(head)) + report_nodes("%s: location %a, group %a, # before %a, # after %s, stream: %s",what,n,groupcode,before,after,reconstruct(head)) else - report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s",what,n,state,groupcode,before,after) + report_nodes("%s: location %a, group %a, # before %a, # after %s",what,n,groupcode,before,after) end end @@ -74,28 +74,22 @@ do local has_glyph = nodes.has_glyph local count_nodes = nodes.countall - function processors.pre_linebreak_filter(head,groupcode) -- ,size,packtype,direction + local function pre_linebreak_filter(head,groupcode) -- ,size,packtype,direction local found = force_processors or has_glyph(head) if found then if trace_callbacks then local before = count_nodes(head,true) - local head, done = actions(head,groupcode) -- ,size,packtype,direction + head = actions(head,groupcode) -- ,size,packtype,direction local after = count_nodes(head,true) - if done then - tracer("pre_linebreak","changed",head,groupcode,before,after,true) - else - tracer("pre_linebreak","unchanged",head,groupcode,before,after,true) - end - return done and head or true + tracer("pre_linebreak",head,groupcode,before,after,true) else - local head, done = actions(head,groupcode) -- ,size,packtype,direction - return done and head or true + head = actions(head,groupcode) -- ,size,packtype,direction end elseif trace_callbacks then local n = count_nodes(head,false) - tracer("pre_linebreak","no chars",head,groupcode,n,n) + tracer("pre_linebreak",head,groupcode,n,n) end - return true + return head end local function hpack_filter(head,groupcode,size,packtype,direction,attributes) @@ -103,26 +97,21 @@ do if found then if trace_callbacks then local before = count_nodes(head,true) - local head, done = actions(head,groupcode,size,packtype,direction,attributes) + head = actions(head,groupcode,size,packtype,direction,attributes) local after = count_nodes(head,true) - if done then - tracer("hpack","changed",head,groupcode,before,after,true) - else - tracer("hpack","unchanged",head,groupcode,before,after,true) - end - return done and head or true + tracer("hpack",head,groupcode,before,after,true) else - local head, done = actions(head,groupcode,size,packtype,direction,attributes) - return done and head or true + head = actions(head,groupcode,size,packtype,direction,attributes) end elseif trace_callbacks then local n = count_nodes(head,false) - tracer("hpack","no chars",head,groupcode,n,n) + tracer("hpack",head,groupcode,n,n) end - return true + return head end - processors.hpack_filter = hpack_filter + processors.pre_linebreak_filter = pre_linebreak_filter + processors.hpack_filter = hpack_filter do @@ -130,11 +119,8 @@ do local hpack = nodes.hpack function nodes.fullhpack(head,...) - local ok = hpack_filter(head) - if not done or done == true then - ok = head - end - local hp, b = hpack(ok,...) + head = hpack_filter(head) + local hp, b = hpack(head,...) setboth(hp) return hp, b end @@ -147,54 +133,41 @@ do local hpack = nuts.hpack function nuts.fullhpack(head,...) - local ok = hpack_filter(tonode(head)) - if not done or done == true then - ok = head - else - ok = tonut(ok) - end - local hp, b = hpack(...) + local head = tonut(hpack_filter(tonode(head))) + local hp, b = hpack(head,...) setboth(hp) return hp, b end end - callbacks.register('pre_linebreak_filter', processors.pre_linebreak_filter, "all kind of horizontal manipulations (before par break)") - callbacks.register('hpack_filter' , processors.hpack_filter, "all kind of horizontal manipulations (before hbox creation)") + callbacks.register('pre_linebreak_filter', pre_linebreak_filter, "horizontal manipulations (before par break)") + callbacks.register('hpack_filter' , hpack_filter, "horizontal manipulations (before hbox creation)") end do + -- Beware, these are packaged boxes so no first_glyph test needed. Maybe some day I'll add a hash + -- with valid groupcodes. Watch out, much can pass twice, for instance vadjust passes two times, local actions = tasks.actions("finalizers") -- head, where local count_nodes = nodes.countall - -- beware, these are packaged boxes so no first_glyph test - -- maybe some day a hash with valid groupcodes - -- - -- beware, much can pass twice, for instance vadjust passes two times - -- - -- something weird here .. group mvl when making a vbox - - function processors.post_linebreak_filter(head,groupcode) + local function post_linebreak_filter(head,groupcode) if trace_callbacks then local before = count_nodes(head,true) - local head, done = actions(head,groupcode) + head = actions(head,groupcode) local after = count_nodes(head,true) - if done then - tracer("post_linebreak","changed",head,groupcode,before,after,true) - else - tracer("post_linebreak","unchanged",head,groupcode,before,after,true) - end - return done and head or true + tracer("post_linebreak",head,groupcode,before,after,true) else - local head, done = actions(head,groupcode) - return done and head or true + head = actions(head,groupcode) end + return head end - callbacks.register("post_linebreak_filter", processors.post_linebreak_filter,"all kind of horizontal manipulations (after par break)") + processors.post_linebreak_filter = post_linebreak_filter + + callbacks.register("post_linebreak_filter", post_linebreak_filter,"horizontal manipulations (after par break)") end @@ -218,9 +191,9 @@ do if line and getsubtype(line) == line_code then local head = getlist(line) if head then - local okay, done = actions(head,groupcode,line) - if okay and okay ~= head then - setlist(line,okay) + local result = actions(head,groupcode,line) + if result and result ~= head then + setlist(line,result) end end end diff --git a/tex/context/base/mkiv/node-ref.lua b/tex/context/base/mkiv/node-ref.lua index 1ec77e83d..287112cc8 100644 --- a/tex/context/base/mkiv/node-ref.lua +++ b/tex/context/base/mkiv/node-ref.lua @@ -404,8 +404,8 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx end local list = getlist(current) if list then - local h, ok - h, ok, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) + local h + h, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) if h ~= current then setlist(current,h) end @@ -441,48 +441,9 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx if reference and (done[reference] or 0) == 0 then head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) end - return head, true, pardir, txtdir + return head, pardir, txtdir end --- local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) -- singular ! --- if not pardir then --- pardir = "===" --- end --- if not texdir then --- txtdir = "===" --- end --- local current = head --- while current do --- local id = getid(current) --- if id == hlist_code or id == vlist_code then --- local r = getattr(current,attribute) --- if r and not done[r] then --- done[r] = true --- inject_list(id,current,r,make,stack,pardir,txtdir) --- end --- local list = getlist(current) --- if list then --- local h = inject_area(list,attribute,make,stack,done,current,pardir,txtdir) --- if h ~= current then --- setlist(current,h) --- end --- end --- elseif id == dir_code then --- txtdir = getdir(current) --- elseif id == localpar_code then --- pardir = getdir(current) --- else --- local r = getattr(current,attribute) --- if r and not done[r] then --- done[r] = true --- head, current = inject_range(head,current,current,r,make,stack,parent,pardir,txtdir) --- end --- end --- current = getnext(current) --- end --- return head, true --- end - -- tracing: todo: use predefined colors local register_color = colors.register @@ -672,11 +633,9 @@ end function nodes.references.handler(head) if head and topofstack > 0 then - local head = tonut(head) - local head, done = inject_areas(head,attribute,makereference,stack,done) - return tonode(head), done + return (inject_areas(head,attribute,makereference,stack,done)) else - return head, false + return head end end @@ -783,21 +742,12 @@ local function makedestination(width,height,depth,reference) end end --- function nodes.destinations.handler(head) --- if head and topofstack > 0 then --- return inject_area(head,attribute,makedestination,stack,done) -- singular --- else --- return head, false --- end --- end function nodes.destinations.handler(head) if head and topofstack > 0 then - local head = tonut(head) - local head, done = inject_areas(head,attribute,makedestination,stack,done) - return tonode(head), done + return (inject_areas(head,attribute,makedestination,stack,done)) else - return head, false + return head end end @@ -907,15 +857,3 @@ statistics.register("interactive elements", function() return nil end end) - -function references.enableinteraction() - enableaction("shipouts","nodes.references.handler") - enableaction("shipouts","nodes.destinations.handler") - function references.enableinteraction() end -end - -implement { - name = "enableinteraction", - actions = references.enableinteraction, - onlyonce = true -} diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua index a6211e80e..a33766d77 100644 --- a/tex/context/base/mkiv/node-res.lua +++ b/tex/context/base/mkiv/node-res.lua @@ -147,21 +147,22 @@ nutpool.register = register_node -- could be register_nut -- so far -local disc = register_nut(new_nut("disc")) -local kern = register_nut(new_nut("kern",kerncodes.userkern)) -local fontkern = register_nut(new_nut("kern",kerncodes.fontkern)) -local italickern = register_nut(new_nut("kern",kerncodes.italiccorrection)) -local penalty = register_nut(new_nut("penalty")) -local glue = register_nut(new_nut("glue")) -- glue.spec = nil -local glue_spec = register_nut(new_nut("glue_spec")) -local glyph = register_nut(new_nut("glyph",0)) +local disc = register_nut(new_nut(nodecodes.disc)) +local kern = register_nut(new_nut(nodecodes.kern,kerncodes.userkern)) +local fontkern = register_nut(new_nut(nodecodes.kern,kerncodes.fontkern)) +local italickern = register_nut(new_nut(nodecodes.kern,kerncodes.italiccorrection)) +local penalty = register_nut(new_nut(nodecodes.penalty)) +local glue = register_nut(new_nut(nodecodes.glue)) -- glue.spec = nil +local glue_spec = register_nut(new_nut(nodecodes.gluespec)) +local glyph = register_nut(new_nut(nodecodes.glyph,0)) -local textdir = register_nut(new_nut("dir")) -local latelua = register_nut(new_nut("whatsit",whatsitcodes.latelua)) -local special = register_nut(new_nut("whatsit",whatsitcodes.special)) +local textdir = register_nut(new_nut(nodecodes.dir)) -local user_node = new_nut("whatsit",whatsitcodes.userdefined) +local latelua = register_nut(new_nut(nodecodes.whatsit,whatsitcodes.latelua)) +local special = register_nut(new_nut(nodecodes.whatsit,whatsitcodes.special)) + +local user_node = new_nut(nodecodes.whatsit,whatsitcodes.userdefined) local user_number = register_nut(copy_nut(user_node)) setfield(user_number, "type",usercodes.number) local user_nodes = register_nut(copy_nut(user_node)) setfield(user_nodes, "type",usercodes.node) @@ -170,40 +171,40 @@ local user_tokens = register_nut(copy_nut(user_node)) setfield(user_tokens ----- user_lua = register_nut(copy_nut(user_node)) setfield(user_lua, "type",usercodes.lua) -- in > 0.95 local user_attributes = register_nut(copy_nut(user_node)) setfield(user_attributes,"type",usercodes.attribute) -local left_margin_kern = register_nut(new_nut("margin_kern",0)) -local right_margin_kern = register_nut(new_nut("margin_kern",1)) +local left_margin_kern = register_nut(new_nut(nodecodes.marginkern,0)) +local right_margin_kern = register_nut(new_nut(nodecodes.marginkern,1)) -local lineskip = register_nut(new_nut("glue",skipcodes.lineskip)) -local baselineskip = register_nut(new_nut("glue",skipcodes.baselineskip)) -local leftskip = register_nut(new_nut("glue",skipcodes.leftskip)) -local rightskip = register_nut(new_nut("glue",skipcodes.rightskip)) +local lineskip = register_nut(new_nut(nodecodes.glue,skipcodes.lineskip)) +local baselineskip = register_nut(new_nut(nodecodes.glue,skipcodes.baselineskip)) +local leftskip = register_nut(new_nut(nodecodes.glue,skipcodes.leftskip)) +local rightskip = register_nut(new_nut(nodecodes.glue,skipcodes.rightskip)) -local temp = register_nut(new_nut("temp",0)) +local temp = register_nut(new_nut(nodecodes.temp,0)) -local noad = register_nut(new_nut("noad")) -local delimiter = register_nut(new_nut("delim")) -local fence = register_nut(new_nut("fence")) -local submlist = register_nut(new_nut("sub_mlist")) -local accent = register_nut(new_nut("accent")) -local radical = register_nut(new_nut("radical")) -local fraction = register_nut(new_nut("fraction")) -local subbox = register_nut(new_nut("sub_box")) -local mathchar = register_nut(new_nut("math_char")) -local mathtextchar = register_nut(new_nut("math_text_char")) -local choice = register_nut(new_nut("choice")) +local noad = register_nut(new_nut(nodecodes.noad)) +local delimiter = register_nut(new_nut(nodecodes.delim)) +local fence = register_nut(new_nut(nodecodes.fence)) +local submlist = register_nut(new_nut(nodecodes.submlist)) +local accent = register_nut(new_nut(nodecodes.accent)) +local radical = register_nut(new_nut(nodecodes.radical)) +local fraction = register_nut(new_nut(nodecodes.fraction)) +local subbox = register_nut(new_nut(nodecodes.subbox)) +local mathchar = register_nut(new_nut(nodecodes.mathchar)) +local mathtextchar = register_nut(new_nut(nodecodes.mathtextchar)) +local choice = register_nut(new_nut(nodecodes.choice)) -local boundary = register_nut(new_nut("boundary",boundarycodes.user)) -local wordboundary = register_nut(new_nut("boundary",boundarycodes.word)) +local boundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.user)) +local wordboundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.word)) local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,gluecodes.cleaders) setglue(cleader,0,65536,0,2,0) -- the dir field needs to be set otherwise crash: -local rule = register_nut(new_nut("rule")) setdir(rule, "TLT") -local emptyrule = register_nut(new_nut("rule",rulecodes.empty)) setdir(rule, "TLT") -local userrule = register_nut(new_nut("rule",rulecodes.user)) setdir(rule, "TLT") -local hlist = register_nut(new_nut("hlist")) setdir(hlist,"TLT") -local vlist = register_nut(new_nut("vlist")) setdir(vlist,"TLT") +local rule = register_nut(new_nut(nodecodes.rule)) setdir(rule, "TLT") +local emptyrule = register_nut(new_nut(nodecodes.rule,rulecodes.empty)) setdir(rule, "TLT") +local userrule = register_nut(new_nut(nodecodes.rule,rulecodes.user)) setdir(rule, "TLT") +local hlist = register_nut(new_nut(nodecodes.hlist)) setdir(hlist,"TLT") +local vlist = register_nut(new_nut(nodecodes.vlist)) setdir(vlist,"TLT") function nutpool.glyph(fnt,chr) local n = copy_nut(glyph) @@ -388,6 +389,26 @@ function nutpool.userrule(width,height,depth,dir) -- w/h/d == nil will let them return n end +if LUATEXFUNCTIONALITY > 6738 then + + local outlinerule = register_nut(new_nut(nodecodes.rule,rulecodes.outline)) setdir(rule, "TLT") + + function nutpool.outlinerule(width,height,depth,line,dir) -- w/h/d == nil will let them adapt + local n = copy_nut(outlinerule) + if width or height or depth then + setwhd(n,width,height,depth) + end + if line then + setfield(n,"transform",line) + end + if dir then + setdir(n,dir) + end + return n + end + +end + function nutpool.leader(width,list) local n = copy_nut(cleader) if width then @@ -572,8 +593,9 @@ end -- housekeeping local function cleanup(nofboxes) -- todo - if nodes.tracers.steppers then -- to be resolved - nodes.tracers.steppers.reset() -- todo: make a registration subsystem + local tracers = nodes.tracers + if tracers and tracers.steppers then -- to be resolved + tracers.steppers.reset() -- todo: make a registration subsystem end local nl = 0 local nr = nofreserved @@ -624,3 +646,45 @@ statistics.register("node memory usage", function() -- comes after cleanup ! end) lua.registerfinalizer(cleanup, "cleanup reserved nodes") + +-- experiment + +do + + local glyph = tonode(glyph) + local traverse_id = nodes.traverse_id + + local traversers = table.setmetatableindex(function(t,k) + local v = traverse_id(type(k) == "number" and k or nodecodes[k],glyph) + t[k] = v + return v + end) + + traversers.node = nodes.traverse (glyph) + traversers.char = nodes.traverse_char (glyph) + if nuts.traverse_glyph then traversers.glyph = nodes.traverse_glyph(glyph) end + if nuts.traverse_list then traversers.list = nodes.traverse_list (glyph) end + + nodes.traversers = traversers + +end + +do + + local glyph = glyph + local traverse_id = nuts.traverse_id + + local traversers = table.setmetatableindex(function(t,k) + local v = traverse_id(type(k) == "number" and k or nodecodes[k],glyph) + t[k] = v + return v + end) + + traversers.node = nuts.traverse (glyph) + traversers.char = nuts.traverse_char (glyph) + if nuts.traverse_glyph then traversers.glyph = nuts.traverse_glyph(glyph) end + if nuts.traverse_list then traversers.list = nuts.traverse_list (glyph) end + + nuts.traversers = traversers + +end diff --git a/tex/context/base/mkiv/node-rul.lua b/tex/context/base/mkiv/node-rul.lua index 7c4c2c2f2..39ad1cf58 100644 --- a/tex/context/base/mkiv/node-rul.lua +++ b/tex/context/base/mkiv/node-rul.lua @@ -57,12 +57,13 @@ local insert_node_after = nuts.insert_after local insert_node_before = nuts.insert_before local find_tail = nuts.tail local setglue = nuts.setglue -local traverse_id = nuts.traverse_id local list_dimensions = nuts.rangedimensions local hpack_nodes = nuts.hpack local current_attr = nuts.current_attr local copy_list = nuts.copy_list +local nexthlist = nuts.traversers.hlist + local nodecodes = nodes.nodecodes local rulecodes = nodes.rulecodes local gluecodes = nodes.gluecodes @@ -122,8 +123,8 @@ local setmetatableindex = table.setmetatableindex -- -local striprange = nodes.striprange -local processwords = nodes.processwords +local striprange = nuts.striprange +local processwords = nuts.processwords -- @@ -332,7 +333,7 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a end end if mp and mp ~= "" then - local r = userrule { + local r = usernutrule { width = w, height = ht, depth = dp, @@ -345,7 +346,7 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a ca = color, ta = transparency, } - inject(tonut(r),w,ht,dp) + inject(r,w,ht,dp) else local tx = d.text if tx then @@ -375,10 +376,8 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a return head end -local process = nodes.processwords - rules.handler = function(head) - return process(a_ruled,data,flush_ruled,head) + return processwords(a_ruled,data,flush_ruled,head) end function rules.enable() @@ -431,9 +430,9 @@ local function flush_shifted(head,first,last,data,level,parent,strip) -- not tha return head end -local process = nodes.processwords - -nodes.shifts.handler = function(head) return process(a_shifted,data,flush_shifted,head) end +nodes.shifts.handler = function(head) + return processwords(a_shifted,data,flush_shifted,head) +end function nodes.shifts.enable() enableaction("shipouts","nodes.shifts.handler") @@ -461,7 +460,7 @@ local function linefiller(current,data,width,location) local ca = data.ca local ta = data.ta if mp and mp ~= "" then - return tonut(userrule { + return usernutrule { width = width, height = height, depth = depth, @@ -473,7 +472,7 @@ local function linefiller(current,data,width,location) ta = ta, option = location, direction = getdir(current), - }) + } else local rule = new_rule(width,height,depth) if ca then @@ -497,7 +496,7 @@ function nodes.linefillers.filler(current,data,width,height,depth) local ca = data.ca local ta = data.ta if mp and mp ~= "" then - return tonut(userrule { + return usernutrule { width = width, height = height, depth = depth, @@ -509,7 +508,7 @@ function nodes.linefillers.filler(current,data,width,height,depth) ta = ta, option = location, direction = getdir(current), - }) + } else local rule = new_rule(width,height,depth) if ca then @@ -535,9 +534,8 @@ local function find_attr(head,attr) end end -function nodes.linefillers.handler(head) --- local current = tonut(head) -- when we hook into the contributers - for current in traverse_id(hlist_code,tonut(head)) do +function nodes.linefillers.handler(head) -- traverse_list + for current in nexthlist, head do -- LUATEXVERSION >= 1.090 if getsubtype(current) == line_code then local list = getlist(current) if list then @@ -661,6 +659,132 @@ function nodes.linefillers.handler(head) return head end +if LUATEXVERSION >= 1.090 then + + function nodes.linefillers.handler(head) -- traverse_list + for current, subtype, list in nexthlist, head do -- LUATEXVERSION >= 1.090 + if list and subtype == line_code then + -- why doesn't leftskip take the attributes + -- or list[linefiller] or maybe first match (maybe we need a fast helper for that) + local a = getattr(current,a_linefiller) + if a then + local class = a % 1000 + local data = data[class] + if data then + local location = data.location + local scope = data.scope + local distance = data.distance + local threshold = data.threshold + local leftlocal = false + local rightlocal = false + -- + if scope == v_right then + leftlocal = true + elseif scope == v_left then + rightlocal = true + elseif scope == v_local then + leftlocal = true + rightlocal = true + end + -- + if location == v_left or location == v_both then + local lskip = nil -- leftskip + local iskip = nil -- indentation + local head = list + while head do + local id = getid(head) + if id == glue_code then + if getsubtype(head) == leftskip_code then + lskip = head + else + break + end + elseif id == localpar_code or id == dir_code then + -- go on + elseif id == hlist_code then + if getsubtype(head) == indent_code then + iskip = head + end + break + else + break + end + head = getnext(head) + end + if head then + local indentation = iskip and getwidth(iskip) or 0 + local leftfixed = lskip and getwidth(lskip) or 0 + local lefttotal = lskip and effective_glue(lskip,current) or 0 + local width = lefttotal - (leftlocal and leftfixed or 0) + indentation - distance + if width > threshold then + if iskip then + setwidth(iskip,0) + end + if lskip then + setglue(lskip,leftlocal and getwidth(lskip) or nil) + if distance > 0 then + insert_node_after(list,lskip,new_kern(distance)) + end + insert_node_after(list,lskip,linefiller(current,data,width,"left")) + else + insert_node_before(list,head,linefiller(current,data,width,"left")) + if distance > 0 then + insert_node_before(list,head,new_kern(distance)) + end + end + end + end + end + -- + if location == v_right or location == v_both then + local pskip = nil -- parfillskip + local rskip = nil -- rightskip + local tail = find_tail(list) + while tail and getid(tail) == glue_code do + local subtype = getsubtype(tail) + if subtype == rightskip_code then + rskip = tail + elseif subtype == parfillskip_code then + pskip = tail + else + break + end + tail = getprev(tail) + end + if tail then + local rightfixed = rskip and getwidth(rskip) or 0 + local righttotal = rskip and effective_glue(rskip,current) or 0 + local parfixed = pskip and getwidth(pskip) or 0 + local partotal = pskip and effective_glue(pskip,current) or 0 + local width = righttotal - (rightlocal and rightfixed or 0) + partotal - distance + if width > threshold then + if pskip then + setglue(pskip) + end + if rskip then + setglue(rskip,rightlocal and getwidth(rskip) or nil) + if distance > 0 then + insert_node_before(list,rskip,new_kern(distance)) + end + insert_node_before(list,rskip,linefiller(current,data,width,"right")) + else + insert_node_after(list,tail,linefiller(current,data,width,"right")) + if distance > 0 then + insert_node_after(list,tail,new_kern(distance)) + end + end + end + end + end + end + end + end + end + return head + end + +end + local enable = false function nodes.linefillers.enable() @@ -751,8 +875,6 @@ implement { -- We add a bonus feature here: -local new_rule = nodes.pool.rule - interfaces.implement { name = "autorule", arguments = { @@ -772,14 +894,15 @@ interfaces.implement { t.height, t.depth ) + setattrlist(n,current_attr()) if LUATEXFUNCTIONALITY >= 6710 then if l then - n.left = l + setfield(n,"left",l) end if r then - n.right = r + etfield(n,"right",r) end end - context(n) + context(tonode(n)) end } diff --git a/tex/context/base/mkiv/node-scn.lua b/tex/context/base/mkiv/node-scn.lua index b294b3013..62c9fecec 100644 --- a/tex/context/base/mkiv/node-scn.lua +++ b/tex/context/base/mkiv/node-scn.lua @@ -12,8 +12,6 @@ local attributes = attributes local nodes = nodes local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut local getnext = nuts.getnext local getprev = nuts.getprev @@ -97,7 +95,7 @@ local function striprange(first,last) -- todo: dir return first, last end -nodes.striprange = striprange +nuts.striprange = striprange -- todo: order and maybe other dimensions @@ -228,17 +226,11 @@ local function processwords(attribute,data,flush,head,parent,skip) -- we have hl end end -nodes.processwords = function(attribute,data,flush,head,parent) -- we have hlistdir and local dir - head = tonut(head) - if parent then - parent = tonut(parent) - end - local head, done = processwords(attribute,data,flush,head,parent) - return tonode(head), done +nuts.processwords = function(attribute,data,flush,head,parent) -- we have hlistdir and local dir + return processwords(attribute,data,flush,head,parent) end -- works on lines ! - -- todo: stack because skip can change when nested local function processranges(attribute,flush,head,parent,depth,skip) @@ -319,11 +311,6 @@ local function processranges(attribute,flush,head,parent,depth,skip) end end -nodes.processranges = function(attribute,flush,head,parent) -- we have hlistdir and local dir - head = tonut(head) - if parent then - parent = tonut(parent) - end - local head, done = processranges(attribute,flush,head,parent,0) - return tonode(head), done +nuts.processranges = function(attribute,flush,head,parent) -- we have hlistdir and local dir + return processranges(attribute,flush,head,parent,0) end diff --git a/tex/context/base/mkiv/node-shp.lua b/tex/context/base/mkiv/node-shp.lua index 2c20d9567..74f3c4da2 100644 --- a/tex/context/base/mkiv/node-shp.lua +++ b/tex/context/base/mkiv/node-shp.lua @@ -27,15 +27,14 @@ local whatsit_code = nodecodes.whatsit local fulldisc_code = disccodes.discretionary -local texgetbox = tex.getbox - local implement = interfaces.implement local nuts = nodes.nuts local tonut = nuts.tonut local tonode = nuts.tonode local remove_node = nuts.remove -local traverse_nodes = nuts.traverse + +local nextnode = nuts.traversers.node local setfield = nuts.setfield local setlink = nuts.setlink @@ -50,6 +49,9 @@ local getsubtype = nuts.getsubtype local setlist = nuts.setlist +local getbox = nuts.getbox +local getboxnode = nodes.getbox + local removables = { [whatsitcodes.open] = true, [whatsitcodes.close] = true, @@ -117,6 +119,8 @@ local function cleanup_redundant(head) -- better name is: flatten_page return head end +handlers.cleanuppage = cleanup_redundant -- nut + local function cleanup_flushed(head) -- rough local start = head while start do @@ -143,26 +147,20 @@ local function cleanup_flushed(head) -- rough return head end -function handlers.cleanuppage(head) - return tonode(cleanup_redundant(tonut(head))), true -end - -function handlers.cleanupbox(head) - return tonode(cleanup_flushed(tonut(head))), true +function handlers.cleanupbox(box) + cleanup_flushed(getbox(box)) end local actions = tasks.actions("shipouts") -function handlers.finalize(head,where) -- problem, attr loaded before node, todo ... - return actions(head,where) +function handlers.finalizebox(box) + actions(getbox(box)) -- nut end --- handlers.finalize = actions - -- interface -implement { name = "cleanupbox", actions = { texgetbox, cleanup_flushed }, arguments = "integer" } -implement { name = "finalizebox", actions = { texgetbox, actions }, arguments = "integer" } +implement { name = "cleanupbox", actions = handlers.cleanupbox, arguments = "integer" } +implement { name = "finalizebox", actions = handlers.finalizebox, arguments = "integer" } -- just in case we want to optimize lookups: @@ -192,7 +190,7 @@ local function count(head,data,subcategory) -- no components, pre, post, replace .. can maybe an option .. but -- we use this for optimization so it makes sense to look the the -- main node only - for n, id in traverse_nodes(tonut(head)) do + for n, id in nextnode, tonut(head) do local dn = data[nodecodes[id]] -- we could use id and then later convert to nodecodes dn[subcategory] = dn[subcategory] + 1 if id == hlist_code or id == vlist_code then diff --git a/tex/context/base/mkiv/node-syn.lua b/tex/context/base/mkiv/node-syn.lua index 9d716c44a..efac2795a 100644 --- a/tex/context/base/mkiv/node-syn.lua +++ b/tex/context/base/mkiv/node-syn.lua @@ -126,8 +126,6 @@ local report_system = logs.reporter("system") local tex = tex local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getid = nuts.getid local getlist = nuts.getlist @@ -623,16 +621,10 @@ end collect = collect_max function synctex.collect(head,where) - if enabled then - if where == "object" then - return head, false - else - local h = tonut(head) - h = collect(h,h) - return tonode(h), true - end + if enabled and where ~= "object" then + return collect(head,head) else - return head, false + return head end end @@ -678,7 +670,7 @@ function synctex.enable() enabled = true set_synctex_mode(3) -- we want details if not used then - nodes.tasks.appendaction("shipouts", "after", "luatex.synctex.collect") + nodes.tasks.enableaction("shipouts","luatex.synctex.collect") report_system("synctex functionality is enabled, expect 5-10 pct runtime overhead!") used = true end diff --git a/tex/context/base/mkiv/node-tex.lua b/tex/context/base/mkiv/node-tex.lua index c9d3091df..81ed80d15 100644 --- a/tex/context/base/mkiv/node-tex.lua +++ b/tex/context/base/mkiv/node-tex.lua @@ -10,9 +10,11 @@ builders = builders or { } local kernel = builders.kernel or { } builders.kernel = kernel +local nuts = nodes.nuts + local hyphenate = lang.hyphenate -local ligaturing = node.ligaturing -local kerning = node.kerning +local ligaturing = nuts.ligaturing +local kerning = nuts.kerning kernel.originals = { hyphenate = hyphenate, @@ -21,18 +23,18 @@ kernel.originals = { } function kernel.hyphenation(head) - local done = hyphenate(head) - return head, done + hyphenate(head) + return head end function kernel.ligaturing(head) - local head, tail, done = ligaturing(head) -- we return 3 values indeed - return head, done + local head, tail = ligaturing(head) + return head end function kernel.kerning(head) - local head, tail, done = kerning(head) -- we return 3 values indeed - return head, done + local head, tail = kerning(head) + return head end callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere") diff --git a/tex/context/base/mkiv/node-tra.lua b/tex/context/base/mkiv/node-tra.lua index a2e5a7653..077506e46 100644 --- a/tex/context/base/mkiv/node-tra.lua +++ b/tex/context/base/mkiv/node-tra.lua @@ -57,8 +57,9 @@ local flush_list = nuts.flush_list local count_nodes = nuts.countall local used_nodes = nuts.usedlist -local traverse_by_id = nuts.traverse_id -local traverse_nodes = nuts.traverse +local nextnode = nuts.traversers.node +local nextglyph = nuts.traversers.glyph + local d_tostring = nuts.tostring local nutpool = nuts.pool @@ -90,7 +91,7 @@ function nodes.showlist(head, message) if message then report_nodes(message) end - for n in traverse_nodes(tonut(head)) do + for n in nextnode, tonut(head) do report_nodes(d_tostring(n)) end end @@ -98,7 +99,7 @@ end function nodes.handlers.checkglyphs(head,message) local h = tonut(head) local t = { } - for g in traverse_by_id(glyph_code,h) do + for g in nextglyph, h do t[#t+1] = formatters["%U:%s"](getchar(g),getsubtype(g)) end if #t > 0 then @@ -114,8 +115,8 @@ end function nodes.handlers.checkforleaks(sparse) local l = { } local q = used_nodes() - for p in traverse_nodes(q) do - local s = table.serialize(nodes.astable(p,sparse),nodecodes[getid(p)]) + for p, id in nextnode, q do + local s = table.serialize(nodes.astable(p,sparse),nodecodes[id]) l[s] = (l[s] or 0) + 1 end flush_list(q) @@ -155,7 +156,12 @@ local function tosequence(start,stop,compact) t[#t+1] = nodecodes[id] end elseif id == dir_code or id == localpar_code then - t[#t+1] = "[" .. getdir(start) .. "]" + local d = getdir(start) + if d then + t[#t+1] = "[" .. d .. "]" + else + t[#t+1] = "[]" + end elseif compact then t[#t+1] = "[]" else @@ -180,13 +186,13 @@ end nodes.tosequence = tosequence nuts .tosequence = tosequence -function nodes.report(t,done) - report_nodes("output %a, changed %a, %s nodes",status.output_active,done,count_nodes(tonut(t))) +function nodes.report(t) + report_nodes("output %a, %s nodes",status.output_active,count_nodes(t)) end function nodes.packlist(head) local t = { } - for n in traverse_nodes(tonut(head)) do + for n in nextnode, tonut(head) do t[#t+1] = d_tostring(n) end return t @@ -198,9 +204,9 @@ function nodes.idstostring(head,tail) local t = { } local last_id = nil local last_n = 0 - for n, id in traverse_nodes(head,tail) do -- hm, does not stop at tail + for n, id, subtype in nextnode, head do if id == whatsit_code then - id = whatcodes[getsubtype(n)] + id = whatcodes[subtype] else id = nodecodes[id] end @@ -353,10 +359,9 @@ local what = { [0] = "unknown", "line", "box", "indent", "row", "cell" } local function showboxes(n,symbol,depth) depth = depth or 0 symbol = symbol or "." - for n, id in traverse_nodes(tonut(n)) do + for n, id, subtype in nextnode, tonut(n) do if id == hlist_code or id == vlist_code then - local s = getsubtype(n) - report_nodes(rep(symbol,depth) .. what[s] or s) + report_nodes(rep(symbol,depth) .. what[subtype] or subtype) showboxes(getlist(n),symbol,depth+1) end end diff --git a/tex/context/base/mkiv/node-tsk.lua b/tex/context/base/mkiv/node-tsk.lua index 4aec3a038..b61515aed 100644 --- a/tex/context/base/mkiv/node-tsk.lua +++ b/tex/context/base/mkiv/node-tsk.lua @@ -55,6 +55,7 @@ function tasks.new(specification) -- was: name,arguments,list local sequence = specification.sequence if name and sequence then local tasklist = newsequencer { + name = name -- we can move more to the sequencer now .. todo } tasksdata[name] = { @@ -171,18 +172,26 @@ function tasks.disablegroup(name,group) end end -function tasks.appendaction(name,group,action,where,kind) +function tasks.appendaction(name,group,action,where,kind,state) local data = validgroup(name,"append action") if data then - appendaction(data.list,group,action,where,kind) + local list = data.list + appendaction(list,group,action,where,kind) + if state == "disabled" or (state == "production" and environment.initex) then + disableaction(list,action) + end data.runner = false end end -function tasks.prependaction(name,group,action,where,kind) +function tasks.prependaction(name,group,action,where,kind,state) local data = validgroup(name,"prepend action") if data then - prependaction(data.list,group,action,where,kind) + local list = data.list + prependaction(list,group,action,where,kind) + if state == "disabled" or (state == "production" and environment.initex) then + disableaction(list,action) + end data.runner = false end end @@ -222,123 +231,23 @@ function tasks.actions(name) -- we optimize for the number or arguments (no ...) if data then local t = data.templates if t then + t.name = data.name return function(...) total = total + 1 -- will go away local runner = data.runner if not runner then created = created + 1 --- if trace_tasks then - report_tasks("creating runner %a",name) --- end - runner = compile(data.list,data.processor,t) - data.runner = runner - end - return runner(...) - end - end - local n = data.arguments or 0 - if n == 0 then - return function(head) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 if trace_tasks then report_tasks("creating runner %a",name) end - runner = compile(data.list,data.processor,0) - data.runner = runner - end - return runner(head) - end - elseif n == 1 then - return function(head,one) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,1) - end - runner = compile(data.list,data.processor,1) - data.runner = runner - end - return runner(head,one) - end - elseif n == 2 then - return function(head,one,two) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,2) - end - runner = compile(data.list,data.processor,2) - data.runner = runner - end - return runner(head,one,two) - end - elseif n == 3 then - return function(head,one,two,three) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,3) - end - runner = compile(data.list,data.processor,3) - data.runner = runner - end - return runner(head,one,two,three) - end - elseif n == 4 then - return function(head,one,two,three,four) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,4) - end - runner = compile(data.list,data.processor,4) - data.runner = runner - end - return runner(head,one,two,three,four) - end - elseif n == 5 then - return function(head,one,two,three,four,five) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,5) - end - runner = compile(data.list,data.processor,5) - data.runner = runner - end - return runner(head,one,two,three,four,five) - end - else - return function(head,...) - total = total + 1 -- will go away - local runner = data.runner - if not runner then - created = created + 1 - if trace_tasks then - report_tasks("creating runner %a with %s extra arguments",name,n) - end - runner = compile(data.list,data.processor,"n") + runner = compile(data.list,data.processor,t) data.runner = runner end - return runner(head,...) + return runner(...) end end - else - return nil end + return nil end function tasks.table(name) --maybe move this to task-deb.lua @@ -368,12 +277,119 @@ function tasks.table(name) --maybe move this to task-deb.lua end end --- this will move +-- -- shipouts -- -- + +-- the shipout handlers acts on boxes so we don't need to return something +-- and also don't need to keep the state (done) + +tasks.new { + name = "shipouts", + processor = nodeprocessor, + sequence = { + "before", -- users + "normalizers", -- system + "finishers", -- system + "after", -- users + "wrapup", -- system + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead)))) +]], + +nut = [[ + nuthead = %action%(nuthead) +]], + +nohead = [[ + %action%(tonode(nuthead)) +]], + +nonut = [[ + %action%(nuthead) +]], + + } +} + +-- -- finalizers -- -- + +tasks.new { + name = "finalizers", + sequence = { + "before", -- for users + "normalizers", + "fonts", + "lists", + "after", -- for users + }, + processor = nodeprocessor, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode) +]], + +nonut = [[ + %action%(nuthead,groupcode) +]], + + } +} + +-- -- processors -- -- tasks.new { name = "processors", - arguments = 5, -- often only the first is used, and the last three are only passed in hpack filter --- arguments = 2, processor = nodeprocessor, sequence = { "before", -- for users @@ -383,56 +399,297 @@ tasks.new { "fonts", "lists", "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode,size,packtype,direction,attributes) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode,size,packtype,direction,attributes))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode,size,packtype,direction,attributes) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode,size,packtype,direction,attributes) +]], + +nonut = [[ + %action%(nuthead,groupcode,size,packtype,direction,attributes) +]], + } } tasks.new { name = "finalizers", - arguments = 1, processor = nodeprocessor, sequence = { "before", -- for users "normalizers", --- "characters", --- "finishers", "fonts", "lists", "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead)))) +]], + +nut = [[ + nuthead = %action%(nuthead) +]], + +nohead = [[ + %action%(tonode(nuthead)) +]], + +nonut = [[ + %action%(nuthead) +]], + } } tasks.new { - name = "shipouts", - arguments = 1, - -- nostate = true, -- maybe but only for main ones so little gain + name = "mvlbuilders", processor = nodeprocessor, sequence = { "before", -- for users "normalizers", - "finishers", "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode) +]], + +nonut = [[ + %action%(nuthead,groupcode) +]], + } } tasks.new { - name = "mvlbuilders", - arguments = 1, + name = "vboxbuilders", processor = nodeprocessor, sequence = { "before", -- for users "normalizers", "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode,size,packtype,maxdepth,direction) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode,size,packtype,maxdepth,direction))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode,size,packtype,maxdepth,direction) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode,size,packtype,maxdepth,direction) +]], + +nonut = [[ + %action%(nuthead,groupcode,size,packtype,maxdepth,direction) +]], + } + } tasks.new { - name = "vboxbuilders", - arguments = 5, + name = "contributers", processor = nodeprocessor, sequence = { "before", -- for users "normalizers", "after", -- for users + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,groupcode,line) + local nuthead = tonut(head) + local nutline = tonut(line) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),groupcode,line))) +]], + +nut = [[ + nuthead = %action%(nuthead,groupcode,nutline) +]], + +nohead = [[ + %action%(tonode(nuthead),groupcode,line) +]], + +nonut = [[ + %action%(nuthead,groupcode,nutline) +]], + + } +} + +-- -- math -- -- + +tasks.new { + name = "math", + processor = nodeprocessor, + sequence = { + "before", + "normalizers", + "builders", + "after", + }, + templates = { + +default = [[ +return function(head) + return head +end +]], + +process = [[ +local tonut = nodes.tonut +local tonode = nodes.nuts.tonode + +%localize% + +return function(head,style,penalties) + local nuthead = tonut(head) + +%actions% + return tonode(nuthead) +end +]], + +step = [[ + nuthead = tonut((%action%(tonode(nuthead),style,penalties))) +]], + +nut = [[ + nuthead = %action%(nuthead,style,penalties) +]], + +nohead = [[ + %action%(tonode(nuthead),style,penalties) +]], + +nonut = [[ + %action%(nuthead,style,penalties) +]], + } } @@ -458,18 +715,7 @@ tasks.new { -- } -- } -tasks.new { - name = "contributers", - arguments = 2, -- [head] where parent - processor = nodeprocessor, - sequence = { - "before", -- for users - "normalizers", - "after", -- for users - } -} - --- for now quite useless (too fuzzy0 +-- for now quite useless (too fuzzy) -- -- tasks.new { -- name = "listbuilders", diff --git a/tex/context/base/mkiv/pack-obj.lua b/tex/context/base/mkiv/pack-obj.lua index 3f2b2edfe..479c234b4 100644 --- a/tex/context/base/mkiv/pack-obj.lua +++ b/tex/context/base/mkiv/pack-obj.lua @@ -26,10 +26,7 @@ local new_latelua = nuts.pool.latelua local settexdimen = tokens.setters.dimen -local gettexbox = tokens.getters.box -local settexbox = tokens.setters.box -local gettexdimen = tokens.getters.dimen -local gettexcount = tokens.getters.count +local getcount = tex.getcount local implement = interfaces.implement local setmacro = interfaces.setmacro @@ -129,7 +126,7 @@ local objects = objects function objects.register(ns,id,b,referenced,offset,mode) objects.n = objects.n + 1 - nodes.handlers.finalize(gettexbox(b),"object") + nodes.handlers.finalizebox(b) if mode == 0 then -- tex data[ns][id] = { @@ -160,7 +157,7 @@ function objects.restore(ns,id) -- why not just pass a box number here too (ok, if status then local list = getlist(hbox) local page = new_latelua(function() - saveobject(ns .. "::" .. id,index,gettexcount("realpageno")) + saveobject(ns .. "::" .. id,index,getcount("realpageno")) end) setlink(list,page) end @@ -191,7 +188,7 @@ function objects.reference(ns,id) end function objects.page(ns,id) - return getobjectpage(ns .."::" .. id,gettexcount("realpageno")) + return getobjectpage(ns .."::" .. id,getcount("realpageno")) end function objects.found(ns,id) diff --git a/tex/context/base/mkiv/pack-rul.lua b/tex/context/base/mkiv/pack-rul.lua index c9771546c..a270bffe7 100644 --- a/tex/context/base/mkiv/pack-rul.lua +++ b/tex/context/base/mkiv/pack-rul.lua @@ -51,10 +51,12 @@ local setboxglue = nuts.setboxglue local getboxglue = nuts.getboxglue local hpack = nuts.hpack -local traverse_id = nuts.traverse_id local list_dimensions = nuts.dimensions local flush_node = nuts.flush +local nexthlist = nuts.traversers.hlist +local nextvlist = nuts.traversers.vlist + local checkformath = false directives.register("framed.checkmath",function(v) checkformath = v end) -- experiment @@ -108,12 +110,12 @@ local function doreshapeframedbox(n) end end local hdone = false - for h in traverse_id(hlist_code,list) do -- no dir etc needed + for h in nexthlist, list do -- no dir etc needed check(h,true) hdone = true end -- local vdone = false - for v in traverse_id(vlist_code,list) do -- no dir etc needed + for v in nextvlist, list do -- no dir etc needed check(v,false) -- vdone = true end @@ -121,7 +123,7 @@ local function doreshapeframedbox(n) -- done) elseif maxwidth ~= 0 then if hdone then - for h in traverse_id(hlist_code,list) do + for h in nexthlist, list do local l = getlist(h) if l then local subtype = getsubtype(h) @@ -142,7 +144,7 @@ local function doreshapeframedbox(n) end end -- if vdone then - -- for v in traverse_id(vlist_code,list) do + -- for v in nextvlist, list do -- local width = getwidth(n) -- if width > maxwidth then -- setwidth(v,maxwidth) @@ -164,7 +166,108 @@ local function doreshapeframedbox(n) texsetdimen("global","framedaveragewidth",averagewidth) end -local function doanalyzeframedbox(n) +if LUATEXVERSION >= 1.090 then + + local traverse_list = node.direct.traverse_list + + local nextlist = nuts.traversers.list + + -- local function doreshapeframedbox(n) + doreshapeframedbox = function(n) + local box = getbox(n) + local noflines = 0 + local nofnonzero = 0 + local firstheight = nil + local lastdepth = nil + local lastlinelength = 0 + local minwidth = 0 + local maxwidth = 0 + local totalwidth = 0 + local averagewidth = 0 + local boxwidth = getwidth(box) + if boxwidth ~= 0 then -- and h.subtype == vlist_code + local list = getlist(box) + if list then + local hdone = false + for n, id, subtype, list in nextlist, list do -- no dir etc needed + local width, height, depth = getwhd(n) + if not firstheight then + firstheight = height + end + lastdepth = depth + noflines = noflines + 1 + if list then + if id == hlist_code then + if subtype == box_code or subtype == line_code then + lastlinelength = list_dimensions(list,getdir(n)) + else + lastlinelength = width + end + hdone = true + else + lastlinelength = width + -- vdone = true + end + if lastlinelength > maxwidth then + maxwidth = lastlinelength + end + if lastlinelength < minwidth or minwidth == 0 then + minwidth = lastlinelength + end + if lastlinelength > 0 then + nofnonzero = nofnonzero + 1 + end + totalwidth = totalwidth + lastlinelength + end + end + if not firstheight then + -- done) + elseif maxwidth ~= 0 then + if hdone then + for h, id, subtype, list in nextlist, list do + if list and id == hlist_code then + if subtype == box_code or subtype == line_code then + local p = hpack(list,maxwidth,'exactly',getdir(h)) -- multiple return value + local set, order, sign = getboxglue(p) + setboxglue(h,set,order,sign) + setlist(p) + flush_node(p) + elseif checkformath and subtype == equation_code then + -- display formulas use a shift + if nofnonzero == 1 then + setshift(h,0) + end + end + setwidth(h,maxwidth) + end + end + end + -- if vdone then + -- for v in nextvlist, list do + -- local width = getwidth(n) + -- if width > maxwidth then + -- setwidth(v,maxwidth) + -- end + -- end + -- end + setwidth(box,maxwidth) + averagewidth = noflines > 0 and totalwidth/noflines or 0 + else -- e.g. empty math {$ $} or \hbox{} or ... + setwidth(box,0) + end + end + end + texsetcount("global","framednoflines",noflines) + texsetdimen("global","framedfirstheight",firstheight or 0) -- also signal + texsetdimen("global","framedlastdepth",lastdepth or 0) + texsetdimen("global","framedminwidth",minwidth) + texsetdimen("global","framedmaxwidth",maxwidth) + texsetdimen("global","framedaveragewidth",averagewidth) + end + +end + +local function doanalyzeframedbox(n) -- traverse_list local box = getbox(n) local noflines = 0 local firstheight = nil @@ -180,10 +283,10 @@ local function doanalyzeframedbox(n) lastdepth = depth noflines = noflines + 1 end - for h in traverse_id(hlist_code,list) do + for h in nexthlist, list do check(h) end - for v in traverse_id(vlist_code,list) do + for v in nextvlist, list do check(v) end end @@ -228,10 +331,10 @@ local function maxboxwidth(box) end end end - for h in traverse_id(hlist_code,list) do -- no dir etc needed + for h in nexthlist, list do -- no dir etc needed check(h,true) end - for v in traverse_id(vlist_code,list) do -- no dir etc needed + for v in nextvlist, list do -- no dir etc needed check(v,false) end return maxwidth diff --git a/tex/context/base/mkiv/page-imp.mkiv b/tex/context/base/mkiv/page-imp.mkiv index c08f9856f..d4526a59f 100644 --- a/tex/context/base/mkiv/page-imp.mkiv +++ b/tex/context/base/mkiv/page-imp.mkiv @@ -63,9 +63,21 @@ \newbox \shipoutscratchbox -\setnewconstant\shipoutfinalizemethod\plusone % this will be default (we will have two finalizers) +\setnewconstant\shipoutfinalizemethod\plusone -\unexpanded\def\installshipoutmethod#1#2% % a handler takes one argument: something to be boxed +\unexpanded\def\shipoutrange#1#2% + {\begingroup + \scratchtoks\emptytoks + \dostepwiserecurse{#1}{\numexpr#2-\plusone\relax}\plusone{\etoksapp\scratchtoks{##1,}}% + \xdef\pagestoshipout{\the\scratchtoks,\number#2}% + \doglobal\appendtoks + \ifnum\realpageno>\numexpr#2+\plusone\relax + \global\everypar{\normalend}% + \fi + \to\everyaftershipout + \endgroup} + +\unexpanded\def\installshipoutmethod#1#2% % a handler takes one argument: something to be boxed {\setgvalue{\??shipoutmethod#1}##1{#2{##1}}} % and shipped out (don't depend on the exact package) \let\installpagehandler\installshipoutmethod % will go @@ -73,13 +85,6 @@ \unexpanded\def\invokepagehandler#1% {\expandnamespacevalue\??shipoutmethod{#1}\v!normal} -% \def\page_shipouts_handle -% {\csname\??shipoutmethod\ifcsname\??shipoutmethod\v_page_target_method\endcsname -% \v_page_target_method -% \else -% \v!none -% \fi\endcsname} - \def\page_shipouts_handle {\ifcsname\??shipoutmethod\v_page_target_method\endcsname \expandafter\lastnamedcs @@ -112,12 +117,14 @@ \page_boxes_flush_before \fi \the\everybeforeshipout - \ifcase\shipoutfinalizemethod + \ifcase\shipoutfinalizemethod % not nice ... needs thinking \page_shipouts_handle{#1}% \else - \setbox\shipoutscratchbox\hpack{#1}% just in case there are objects there, hook for testing (will go away) - \finalizeshipoutbox\shipoutscratchbox - \page_shipouts_handle{\box\shipoutscratchbox}% + \setbox\shipoutscratchbox\hpack + {#1}% just in case there are objects there, hook for testing (will go away) + \page_shipouts_handle + {\finalizeshipoutbox\shipoutscratchbox + \box\shipoutscratchbox}% \fi \setnextrealpageno % so this comes before \everyaftershipout so in fact: \the\everyaftershipout % at this point we're already on the next realpage @@ -127,11 +134,12 @@ \def\page_shipouts_ignore#1% {\begingroup - \message - {[\ifarrangingpages arranged \fi page + \writestatus\m!system + {\ifarrangingpages arranged \fi page \ifarrangingpages\the\arrangeno\else\the\realpageno\fi\normalspace - not flushed]}% - \setbox\scratchbox\hpack{#1}% + not flushed}% + % \setbox\scratchbox\hpack + % {#1}% no finalize \deadcycles\zerocount \endgroup} @@ -173,7 +181,8 @@ \normalexpanded{\doifelseinset{\the\shippedoutpages}{\pagestoshipout}}\donetrue\donefalse \fi \ifdone - \setbox\shipoutscratchbox\hpack{#1}% + \setbox\shipoutscratchbox\hpack + {#1}% finalizes \ifcase\shipoutfinalizemethod \finalizeshipoutbox\shipoutscratchbox \fi @@ -190,13 +199,14 @@ \fi} \def\page_shipouts_arrange#1% - {% \global\advance\shippedoutpages\plusone - \begingroup - \setbox\scratchbox\hpack + {\begingroup + \setbox\shipoutscratchbox\hpack + {#1}% finalizes + \setbox\shipoutscratchbox\hpack {\page_otr_flush_every_stuff \page_otr_flush_special_content \box\shipoutscratchbox}% - \pusharrangedpage\scratchbox + \pusharrangedpage\shipoutscratchbox \deadcycles\zerocount \endgroup} diff --git a/tex/context/base/mkiv/page-inj.mkvi b/tex/context/base/mkiv/page-inj.mkvi index cabd07bac..5f48ffd13 100644 --- a/tex/context/base/mkiv/page-inj.mkvi +++ b/tex/context/base/mkiv/page-inj.mkvi @@ -124,7 +124,7 @@ \ifx\currentpageinjectionalternative\v!none \else % increment counter but don’t generate output \forgetparindent \dontcomplain - \setconstant\shipoutfinalizemethod\zerocount + \setconstant\shipoutfinalizemethod\zerocount % this is messy \page_injections_flush_indeed \fi} diff --git a/tex/context/base/mkiv/page-lin.lua b/tex/context/base/mkiv/page-lin.lua index a6b6a12c4..b990cb223 100644 --- a/tex/context/base/mkiv/page-lin.lua +++ b/tex/context/base/mkiv/page-lin.lua @@ -79,8 +79,9 @@ local getdepth = nuts.getdepth local setprop = nuts.setprop local getprop = nuts.getprop -local traverse_id = nuts.traverse_id -local traverse = nuts.traverse +local nexthlist = nuts.traversers.hlist +local nextvlist = nuts.traversers.vlist + local copy_node = nuts.copy ----- hpack_nodes = nuts.hpack local is_display_math = nuts.is_display_math @@ -283,7 +284,7 @@ end local function listisnumbered(list) if list then - for n in traverse_id(hlist_code,list) do + for n in nexthlist, list do -- LUATEXVERSION >= 1.090 if getsubtype(n) == line_code then local a = getattr(n,a_linenumber) if a then @@ -383,7 +384,7 @@ function boxed.stage_one(n,nested) local skip = false local function check() - for n in traverse_id(hlist_code,list) do -- attr test here and quit as soon as zero found + for n in nexthlist, list do -- LUATEXVERSION >= 1.090 local subtype = getsubtype(n) if subtype ~= line_code then -- go on @@ -450,7 +451,7 @@ function boxed.stage_one(n,nested) if not list then return end - for n in traverse_id(vlist_code,list) do + for n in nextvlist, list do -- LUATEXVERSION >= 1.090 local p = properties[n] if p and p.columngap then if trace_numbers then @@ -473,7 +474,7 @@ function boxed.stage_two(n,m) if #current_list > 0 then m = m or lines.scratchbox local t, tn = { }, 0 - for l in traverse_id(hlist_code,getlist(getbox(m))) do + for l in nexthlist, getlist(getbox(m)) do -- LUATEXVERSION >= 1.090 tn = tn + 1 t[tn] = copy_node(l) -- use take_box instead end diff --git a/tex/context/base/mkiv/page-mix.lua b/tex/context/base/mkiv/page-mix.lua index 107ac1410..192b8a30a 100644 --- a/tex/context/base/mkiv/page-mix.lua +++ b/tex/context/base/mkiv/page-mix.lua @@ -69,8 +69,6 @@ local getpenalty = nuts.getpenalty local getwidth = nuts.getwidth local getheight = nuts.getheight local getdepth = nuts.getdepth -local traverse_id = nuts.traverse_id -local traverse = nuts.traverse local theprop = nuts.theprop @@ -829,23 +827,6 @@ local function report_deltas(result,str) report_state("%s, cycles %s, deltas % | t",str,result.cycle or 1,t) end --- local function xxcollectinserts(h) --- local skips, total, order = 0, 0, 0 --- print(h) --- if h then --- h = getlist(h) --- for n in traverse(h) do --- print(tonode(n)) --- end --- for n in traverse_id(insert_code,h) do --- order = order + 1 --- total = total + getheight(n) --- skips = skips + structures.notes.check_spacing(getsubtype(n),order) --- end --- end --- return skips, total --- end - local function setsplit(specification) splitruns = splitruns + 1 if trace_state then diff --git a/tex/context/base/mkiv/scrn-ref.mkvi b/tex/context/base/mkiv/scrn-ref.mkvi index bace13312..df395e550 100644 --- a/tex/context/base/mkiv/scrn-ref.mkvi +++ b/tex/context/base/mkiv/scrn-ref.mkvi @@ -83,15 +83,15 @@ %D delayed ... -\def\scrn_reference_enable_references - {\ifproductionrun - \clf_enableinteraction % only once anyway - \glet\scrn_reference_enable_references\relax - \fi} - -\appendtoks - \scrn_reference_enable_references -\to \everysetupinteraction +% \def\scrn_reference_enable_references +% {\ifproductionrun +% \clf_enableinteraction % only once anyway +% \glet\scrn_reference_enable_references\relax +% \fi} +% +% \appendtoks +% \scrn_reference_enable_references +% \to \everysetupinteraction \setupinteraction % start fit page and reset form [\c!openaction=, diff --git a/tex/context/base/mkiv/scrp-cjk.lua b/tex/context/base/mkiv/scrp-cjk.lua index b31dc335a..faef77eec 100644 --- a/tex/context/base/mkiv/scrp-cjk.lua +++ b/tex/context/base/mkiv/scrp-cjk.lua @@ -15,14 +15,12 @@ if not modules then modules = { } end modules ['scrp-cjk'] = { -- line would have to be a hard coded ones. local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode local insert_node_after = nuts.insert_after local insert_node_before = nuts.insert_before local copy_node = nuts.copy local remove_node = nuts.remove -local traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph local getnext = nuts.getnext local getprev = nuts.getprev @@ -509,9 +507,8 @@ scripts.installmethod { } function scripts.decomposehangul(head) - local head = tonut(head) local done = false - for current in traverse_id(glyph_code,head) do + for current in nextglyph, head do local lead_consonant, medial_vowel, tail_consonant = decomposed(getchar(current)) if lead_consonant then setchar(current,lead_consonant) @@ -526,7 +523,7 @@ function scripts.decomposehangul(head) done = true end end - return tonode(head), done + return head, done end -- nodes.tasks.prependaction("processors","normalizers","scripts.decomposehangul") diff --git a/tex/context/base/mkiv/scrp-ini.lua b/tex/context/base/mkiv/scrp-ini.lua index 9bd70e30a..0eee550ac 100644 --- a/tex/context/base/mkiv/scrp-ini.lua +++ b/tex/context/base/mkiv/scrp-ini.lua @@ -52,8 +52,6 @@ local enableaction = nodes.tasks.enableaction local disableaction = nodes.tasks.disableaction local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getchar = nuts.getchar @@ -65,8 +63,11 @@ local isglyph = nuts.isglyph local insert_node_after = nuts.insert_after local first_glyph = nuts.first_glyph -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char + +----- traverse_id = nuts.traverse_id +----- traverse_char = nuts.traverse_char +local nextglyph = nuts.traversers.glyph +local nextchar = nuts.traversers.char local nodepool = nuts.pool @@ -417,7 +418,7 @@ scripts.categorytonumber = categorytonumber scripts.numbertocategory = numbertocategory local function colorize(start,stop) - for n in traverse_id(glyph_code,start) do + for n in nextglyph, start do local kind = numbertocategory[getattr(n,a_scriptstatus)] if kind then local ac = scriptcolors[kind] @@ -450,13 +451,12 @@ end -- we can have a fonts.hashes.originals function scripts.injectors.handler(head) - head = tonut(head) local start = first_glyph(head) -- we already have glyphs here (subtype 1) if not start then - return tonode(head), false + return head else local last_a, normal_process, lastfont, originals = nil, nil, nil, nil - local done, first, last, ok = false, nil, nil, false + local first, last, ok = nil, nil, false while start do local char, id = isglyph(start) if char then @@ -473,7 +473,7 @@ function scripts.injectors.handler(head) else normal_process(head,first,last) end - ok, done = false, true + ok = false end first, last = nil, nil end @@ -517,7 +517,7 @@ function scripts.injectors.handler(head) else normal_process(head,first,last) end - ok, done = false, true + ok = false end first, last = nil, nil end @@ -532,7 +532,7 @@ function scripts.injectors.handler(head) else normal_process(head,first,last) end - ok, done = false, true + ok = false end first, last = nil, nil end @@ -554,7 +554,7 @@ function scripts.injectors.handler(head) else normal_process(head,first,last) end - first, last, ok, done = nil, nil, false, true + first, last, ok = nil, nil, false elseif first then first, last = nil, nil end @@ -570,16 +570,15 @@ function scripts.injectors.handler(head) else normal_process(head,first,last) end - done = true end - return tonode(head), done + return head end end -- kind of experimental .. might move to it's own module -- function scripts.splitters.handler(head) --- return head, false +-- return head -- end local function addwords(tree,data) @@ -759,9 +758,7 @@ end local tree, attr, proc function splitters.handler(head) -- todo: also first_glyph test - head = tonut(head) local current = head - local done = false while current do if getid(current) == glyph_code then local a = getattr(current,a_scriptsplitting) @@ -792,7 +789,6 @@ function splitters.handler(head) -- todo: also first_glyph test end end head, current = proc(handler,head,current,last,1) - done = true else if trace_splitdetail then -- could be punctuation @@ -803,7 +799,6 @@ function splitters.handler(head) -- todo: also first_glyph test end end head, current = proc(handler,head,current,last,2) - done = true end end end @@ -813,7 +808,7 @@ function splitters.handler(head) -- todo: also first_glyph test end current = getnext(current) end - return tonode(head), done + return head end local function marker(head,current,font,color) -- could become: nodes.tracers.marker @@ -907,7 +902,7 @@ setmetatableindex(cache_nop,function(t,k) local v = { } t[k] = v return v end) -- playing nice function autofontfeature.handler(head) - for n in traverse_char(tonut(head)) do + for n in nextchar, head do -- if getattr(n,a_scriptinjection) then -- -- already tagged by script feature, maybe some day adapt -- else @@ -951,6 +946,53 @@ function autofontfeature.handler(head) return head end +if LUATEXVERSION >= 1.090 then + + function autofontfeature.handler(head) + for n, font, char in nextchar, head do + -- if getattr(n,a_scriptinjection) then + -- -- already tagged by script feature, maybe some day adapt + -- else + local script = otfscripts[char] + if script then + local dynamic = getattr(n,0) or 0 + if dynamic > 0 then + local slot = cache_yes[font] + local attr = slot[script] + if not attr then + attr = mergecontext(dynamic,name,2) + slot[script] = attr + if trace_scripts then + report_scripts("script: %s, trigger %C, dynamic: %a, variant: %a",script,char,attr,"extended") + end + end + if attr ~= 0 then + n[0] = attr + -- maybe set scriptinjection when associated + end + else + local slot = cache_nop[font] + local attr = slot[script] + if not attr then + attr = registercontext(font,script,2) + slot[script] = attr + if trace_scripts then + report_scripts("script: %s, trigger %C, dynamic: %s, variant: %a",script,char,attr,"normal") + end + end + if attr ~= 0 then + setattr(n,0,attr) + -- maybe set scriptinjection when associated + end + end + end + -- end + end + return head + end + +end + function autofontfeature.enable() report_scripts("globally enabled") enableaction("processors","scripts.autofontfeature.handler") diff --git a/tex/context/base/mkiv/spac-adj.lua b/tex/context/base/mkiv/spac-adj.lua deleted file mode 100644 index 3db59881b..000000000 --- a/tex/context/base/mkiv/spac-adj.lua +++ /dev/null @@ -1,67 +0,0 @@ -if not modules then modules = { } end modules ['spac-adj'] = { - version = 1.001, - comment = "companion to spac-adj.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- sort of obsolete code - -local a_vadjust = attributes.private('graphicvadjust') - -local nodecodes = nodes.nodecodes - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist - -local remove_node = nodes.remove -local hpack_node = node.hpack - -local enableaction = nodes.tasks.enableaction - -function nodes.handlers.graphicvadjust(head,groupcode) -- we can make an actionchain for mvl only - if groupcode == "" then -- mvl only - local h, p, done = head, nil, false - while h do - local id = h.id - if id == hlist_code or id == vlist_code then - local a = h[a_vadjust] - if a then - if p then - local n - head, h, n = remove_node(head,h) - local pl = p.list - if n.width ~= 0 then - n = hpack_node(n,0,'exactly') -- todo: dir - end - if pl then - pl.prev = n - n.next = pl - end - p.list = n - done = true - else - -- can't happen - end - else - p = h - h = h.next - end - else - h = h.next - end - end - return head, done - else - return head, false - end -end - -interfaces.implement { - name = "enablegraphicvadjust", - onlyonce = true, - actions = function() - enableaction("finalizers","nodes.handlers.graphicvadjust") - end -} diff --git a/tex/context/base/mkiv/spac-adj.mkiv b/tex/context/base/mkiv/spac-adj.mkiv deleted file mode 100644 index d29d15c17..000000000 --- a/tex/context/base/mkiv/spac-adj.mkiv +++ /dev/null @@ -1,51 +0,0 @@ -%D \module -%D [ file=spac-adj, % moved from spac-par.mkiv -%D version=2009.10.16, % 1997.03.31, was core-spa.tex -%D title=\CONTEXT\ Spacing Macros, -%D subtitle=Paragraphs, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Spacing Macros / Adjustments} - -\unprotect - -% Very nasty but needed for margin stuff inside colored -% paragraphs. Obsolete for while . - -\registerctxluafile{spac-adj}{} - -\definesystemattribute [graphicvadjust] [public] - -\unexpanded\def\enablegraphicvadjust - {\writestatus\m!system{graphicvadjusting is no longer needed!} - \clf_enablegraphicvadjust %once anyway - \glet\enablegraphicvadjust\relax} - -\unexpanded\def\graphicvadjust % currently not enabled ... nasty bidi handling - {\clf_enablegraphicvadjust % and probably no longer needed anyway - \dowithnextboxcontentcs\forgetall\spac_vadjust_graphic_finish\vbox} - -\def\spac_vadjust_graphic_finish - {\vadjust - {\vbox attr \graphicvadjustattribute \plusone - {\unvbox\nextbox - % corrects for one line paragraphs - \nointerlineskip - \kern-\struttotal - \nointerlineskip - \verticalstrut}}} - -\unexpanded\def\fakedvadjust - {\dowithnextboxcs\spac_vadjust_faked_finish\vtop} - -\def\spac_vadjust_faked_finish - {\setbox\nextbox\hpack{\llap{\lower\strutdepth\box\nextbox}}% - \smashedbox\nextbox} - -\protect \endinput diff --git a/tex/context/base/mkiv/spac-ali.lua b/tex/context/base/mkiv/spac-ali.lua index 640478d34..3da0e57f4 100644 --- a/tex/context/base/mkiv/spac-ali.lua +++ b/tex/context/base/mkiv/spac-ali.lua @@ -63,9 +63,8 @@ local nofrealigned = 0 -- raggedright 0 0 fil -- raggedcenter 0 + 0 + - -local function handler(head,leftpage,realpageno) +local function handler(head,leftpage,realpageno) -- traverse_list local current = head - local done = false while current do local id = getid(current) if id == hlist_code then @@ -102,7 +101,6 @@ local function handler(head,leftpage,realpageno) elseif trace_realign then report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno) end - done = true nofrealigned = nofrealigned + 1 end end @@ -113,14 +111,11 @@ local function handler(head,leftpage,realpageno) end current = getnext(current) end - return head, done + return head end function alignments.handler(head) - local leftpage = isleftpage() - local realpageno = texgetcount("realpageno") - local head, done = handler(tonut(head),leftpage,realpageno) - return tonode(head), done + return handler(head,isleftpage(),texgetcount("realpageno")) end local enabled = false diff --git a/tex/context/base/mkiv/spac-chr.lua b/tex/context/base/mkiv/spac-chr.lua index 0fa639f92..20b72e1b9 100644 --- a/tex/context/base/mkiv/spac-chr.lua +++ b/tex/context/base/mkiv/spac-chr.lua @@ -27,9 +27,6 @@ local nodes, node = nodes, node local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut - local getnext = nuts.getnext local getprev = nuts.getprev local getattr = nuts.getattr @@ -48,13 +45,13 @@ local setcolor = nodes.tracers.colors.set local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after local remove_node = nuts.remove -local traverse_id = nuts.traverse_id -local traverse_char = nuts.traverse_char +----- traverse_id = nuts.traverse_id +----- traverse_char = nuts.traverse_char +local nextchar = nuts.traversers.char +local nextglyph = nuts.traversers.glyph local copy_node = nuts.copy -local tasks = nodes.tasks - local nodepool = nuts.pool local new_penalty = nodepool.penalty local new_glue = nodepool.glue @@ -101,8 +98,7 @@ local function inject_quad_space(unicode,head,current,fraction) setattrlist(glue,current) setattrlist(current) -- why reset all setattr(glue,a_character,unicode) - head, current = insert_node_after(head,current,glue) - return head, current + return insert_node_after(head,current,glue) end local function inject_char_space(unicode,head,current,parent) @@ -112,8 +108,7 @@ local function inject_char_space(unicode,head,current,parent) setattrlist(glue,current) setattrlist(current) -- why reset all setattr(glue,a_character,unicode) - head, current = insert_node_after(head,current,glue) - return head, current + return insert_node_after(head,current,glue) end local function inject_nobreak_space(unicode,head,current,space,spacestretch,spaceshrink) @@ -132,8 +127,7 @@ local function inject_nobreak_space(unicode,head,current,space,spacestretch,spac head, current = insert_node_after(head,current,kern) head, current = insert_node_after(head,current,penalty) end - head, current = insert_node_after(head,current,glue) - return head, current + return insert_node_after(head,current,glue) end local function nbsp(head,current) @@ -152,26 +146,12 @@ end function characters.replacenbsp(head,original) local head, current = nbsp(head,original) - head = remove_node(head,original,true) - return head, current + return remove_node(head,original,true) end --- function characters.replacenbspaces(head) --- for current in traverse_id(glyph_code,head) do --- if getchar(current) == 0x00A0 then --- local h = nbsp(head,current) --- if h then --- head = remove_node(h,current,true) --- end --- end --- end --- return head --- end - function characters.replacenbspaces(head) - local head = tonut(head) local wipe = false - for current in traverse_id(glyph_code,head) do -- can be anytiem so no traverse_char + for current in nextglyph, head do -- can be anytime so no traverse_char if getchar(current) == 0x00A0 then if wipe then head = remove_node(h,current,true) @@ -184,15 +164,40 @@ function characters.replacenbspaces(head) end end if wipe then - head = remove_node(h,current,true) + head = remove_node(head,current,true) + end + return head +end + +if LUATEXVERSION >= 1.090 then + + function characters.replacenbspaces(head) + local wipe = false + for current, font, char in nextglyph, head do -- can be anytime so no traverse_char + if char == 0x00A0 then + if wipe then + head = remove_node(h,current,true) + wipe = false + end + local h = nbsp(head,current) + if h then + wipe = current + end + end + end + if wipe then + head = remove_node(head,current,true) + end + return head end - return tonode(head) + end -- This initialization might move someplace else if we need more of it. The problem is that -- this module depends on fonts so we have an order problem. local nbsphash = { } setmetatableindex(nbsphash,function(t,k) + -- this needs checking ! for i=unicodeblocks.devanagari.first,unicodeblocks.devanagari.last do nbsphash[i] = true end for i=unicodeblocks.kannada .first,unicodeblocks.kannada .last do nbsphash[i] = true end setmetatableindex(nbsphash,nil) @@ -319,9 +324,7 @@ local methods = { characters.methods = methods -- function characters.handler(head) -- todo: use traverse_id --- head = tonut(head) -- local current = head --- local done = false -- while current do -- local char, id = isglyph(current) -- if char then @@ -335,28 +338,49 @@ characters.methods = methods -- if h then -- head = remove_node(h,current,true) -- end --- done = true -- end -- current = next -- else -- current = getnext(current) -- end -- end --- return tonode(head), done +-- return head -- end --- for current, char, font in traverse_char_data(head) will save 0.015 on a 300 page doc - -- this also works ok in math as we run over glyphs and these stay glyphs ... not sure -- about scripts and such but that is not important anyway ... some day we can consider -- special definitions in math function characters.handler(head) - local head = tonut(head) local wipe = false - for current in traverse_char(head) do - local char = getchar(current) - if char then + for current in nextchar, head do + local char = getchar(current) + local method = methods[char] + if method then + if wipe then + head = remove_node(head,wipe,true) + wipe = false + end + if trace_characters then + report_characters("replacing character %C, description %a",char,lower(chardata[char].description)) + end + local h = method(head,current) + if h then + wipe = current + end + end + end + if wipe then + head = remove_node(head,wipe,true) + end + return head +end + +if LUATEXVERSION >= 1.090 then + + function characters.handler(head) + local wipe = false + for current, char in nextchar, head do local method = methods[char] if method then if wipe then @@ -370,12 +394,12 @@ function characters.handler(head) if h then wipe = current end - done = true end end + if wipe then + head = remove_node(head,wipe,true) + end + return head end - if wipe then - head = remove_node(head,wipe,true) - end - return tonode(head), done + end diff --git a/tex/context/base/mkiv/spac-prf.lua b/tex/context/base/mkiv/spac-prf.lua index a28f30593..f4d452cbb 100644 --- a/tex/context/base/mkiv/spac-prf.lua +++ b/tex/context/base/mkiv/spac-prf.lua @@ -639,7 +639,7 @@ end local function profilelist(line,mvl) - local current = tonut(line) + local current = line local top = nil local bot = nil @@ -899,9 +899,8 @@ end -- -- function profiling.vboxhandler(head,where) -- if head and not ignore[where] then --- local h = tonut(head) --- if getnext(h) then --- profilelist(h) +-- if getnext(head) then +-- profilelist(head) -- end -- end -- return head @@ -911,7 +910,7 @@ function profiling.pagehandler(head) if head then profilelist(head,true) end - return head, true + return head end interfaces.implement { diff --git a/tex/context/base/mkiv/spac-ver.lua b/tex/context/base/mkiv/spac-ver.lua index 8f2136f95..05055ef63 100644 --- a/tex/context/base/mkiv/spac-ver.lua +++ b/tex/context/base/mkiv/spac-ver.lua @@ -116,7 +116,6 @@ local a_snapmethod = attributes.private('snapmethod') local a_snapvbox = attributes.private('snapvbox') local nuts = nodes.nuts -local tonode = nuts.tonode local tonut = nuts.tonut local getnext = nuts.getnext @@ -147,15 +146,16 @@ local getdepth = nuts.getdepth local find_node_tail = nuts.tail local flush_node = nuts.flush_node -local traverse_nodes = nuts.traverse -local traverse_nodes_id = nuts.traverse_id local insert_node_after = nuts.insert_after local insert_node_before = nuts.insert_before local remove_node = nuts.remove local count_nodes = nuts.countall local hpack_node = nuts.hpack local vpack_node = nuts.vpack ------ writable_spec = nuts.writable_spec + +local nextnode = nuts.traversers.node +local nexthlist = nuts.traversers.hlist + local nodereference = nuts.reference local theprop = nuts.theprop @@ -290,7 +290,7 @@ local function validvbox(parentid,list) end end local done = nil - for n, id in traverse_nodes(list) do + for n, id in nextnode, list do if id == vlist_code or id == hlist_code then if done then return nil @@ -325,7 +325,7 @@ local function already_done(parentid,list,a_snapmethod) -- todo: done when only return false end end - for n, id in traverse_nodes(list) do + for n, id in nextnode, list do if id == hlist_code or id == vlist_code then -- local a = getattr(n,a_snapmethod) -- if not a then @@ -534,7 +534,7 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut] if thebox and id == vlist_code then local list = getlist(thebox) local lw, lh, ld - for n in traverse_nodes_id(hlist_code,list) do + for n in nexthlist, list do lw, lh, ld = getwhd(n) break end @@ -570,7 +570,7 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut] if thebox and id == vlist_code then local list = getlist(thebox) local lw, lh, ld - for n in traverse_nodes_id(hlist_code,list) do + for n in nexthlist, list do lw, lh, ld = getwhd(n) end if lh then @@ -1879,7 +1879,7 @@ do trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)]) end end - return head, true + return head end -- alignment after_output end box new_graf vmode_par hmode_par insert penalty before_display after_display @@ -1910,29 +1910,25 @@ do function vspacing.pagehandler(newhead,where) -- local newhead = texlists.contrib_head if newhead then - newhead = tonut(newhead) local newtail = find_node_tail(newhead) -- best pass that tail, known anyway local flush = false stackhack = true -- todo: only when grid snapping once enabled -- todo: fast check if head = tail - for n, id in traverse_nodes(newhead) do -- we could just look for glue nodes + for n, id, subtype in nextnode, newhead do -- we could just look for glue nodes if id ~= glue_code then flush = true - else - local subtype = getsubtype(n) - if subtype == userskip_code then - if getattr(n,a_skipcategory) then - stackhack = true - else - flush = true - end - elseif subtype == parskip_code then - -- if where == new_graf then ... end - if texgetcount("c_spac_vspacing_ignore_parskip") > 0 then --- texsetcount("c_spac_vspacing_ignore_parskip",0) - setglue(n) - -- maybe removenode - end + elseif subtype == userskip_code then + if getattr(n,a_skipcategory) then + stackhack = true + else + flush = true + end + elseif subtype == parskip_code then + -- if where == new_graf then ... end + if texgetcount("c_spac_vspacing_ignore_parskip") > 0 then + -- texsetcount("c_spac_vspacing_ignore_parskip",0) + setglue(n) + -- maybe removenode end end end @@ -1953,7 +1949,7 @@ do if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end -- texlists.contrib_head = newhead end - return tonode(newhead) + return newhead else if stackhead then if trace_collect_vspacing then report("%s > appending %s nodes to stack (intermediate): %s",where,newhead) end @@ -1977,11 +1973,10 @@ do } function vspacing.vboxhandler(head,where) - if head and not ignore[where] then - local h = tonut(head) - if getnext(h) then -- what if a one liner and snapping? - h = collapser(h,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper - return tonode(h) + if head and not ignore[where] and getnext(head) then + if getnext(head) then -- what if a one liner and snapping? + head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper + return head end end return head diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex c8ca9b98e..d2e9b687d 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 16940503b..6cf05d9b4 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/strc-mar.lua b/tex/context/base/mkiv/strc-mar.lua index a2cbc2ab2..bb79ac7a9 100644 --- a/tex/context/base/mkiv/strc-mar.lua +++ b/tex/context/base/mkiv/strc-mar.lua @@ -29,14 +29,17 @@ local getlist = nuts.getlist local getattr = nuts.getattr local getbox = nuts.getbox -local traverse = nuts.traverse -local traverse_id = nuts.traverse_id +local nextnode = nuts.traversers.node local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist +local whatsit_code = nodecodes.whatsit +local whatsitcodes = nodes.whatsitcodes +local latelua_code = whatsitcodes.latelua + local texsetattribute = tex.setattribute local a_marks = attributes.private("structure","marks") @@ -116,8 +119,9 @@ end -- identify range local function sweep(head,first,last) - for n, id in traverse(head) do - if id == glyph_code then + for n, id, subtype in nextnode, head do + -- we need to handle empty heads so we test for latelua + if id == glyph_code or (id == whatsit_code and subtype == latelua_code) then local a = getattr(n,a_marks) if not a then -- next diff --git a/tex/context/base/mkiv/strc-reg.mkiv b/tex/context/base/mkiv/strc-reg.mkiv index 04fdef9ad..81acb1cf3 100644 --- a/tex/context/base/mkiv/strc-reg.mkiv +++ b/tex/context/base/mkiv/strc-reg.mkiv @@ -835,10 +835,12 @@ \unexpanded\def\startregisterpages {\begingroup \dostarttagged\t!registerpages\empty - \useregisterstyleandcolor\c!pagestyle\c!pagecolor} + \useregisterstyleandcolor\c!pagestyle\c!pagecolor + \registerparameter\c!pageleft} \unexpanded\def\stopregisterpages - {\dostoptagged + {\registerparameter\c!pageright + \dostoptagged \endgroup} \unexpanded\def\startregisterseewords diff --git a/tex/context/base/mkiv/strc-ren.mkiv b/tex/context/base/mkiv/strc-ren.mkiv index 89aa6f55a..9db2f23e9 100644 --- a/tex/context/base/mkiv/strc-ren.mkiv +++ b/tex/context/base/mkiv/strc-ren.mkiv @@ -151,7 +151,7 @@ \strc_rendering_stop_placement} \unexpanded\def\strc_rendering_place_head_empty - {\hbox\headreferenceattributes{\getheadsyncs}} % \hpack ? + {\hpack\headreferenceattributes{\getheadsyncs}} %D \starttyping %D \def\StretchedBox#1% @@ -345,14 +345,14 @@ \nointerlineskip \dosomebreak\nobreak \fi - \getheadsyncs + \getheadsyncs % a latelua, why not in the box \else % somehow this goes ok even when we push in the margin probably because we gobble pars % in the process of collecting index entries etc \strut \flushnotes % new, here since we're in par mode \unhbox\b_strc_rendering_head - \getheadsyncs + \getheadsyncs % a latelua \ifconditional\headissomewhere \strc_sectioning_stay_on_this_line % test case: alternative=margintext and \startparagraph .. \else diff --git a/tex/context/base/mkiv/strc-sec.mkiv b/tex/context/base/mkiv/strc-sec.mkiv index 4e5115a7d..b3e7e46f5 100644 --- a/tex/context/base/mkiv/strc-sec.mkiv +++ b/tex/context/base/mkiv/strc-sec.mkiv @@ -249,7 +249,7 @@ userdata {\detokenize{#3}}% will be converted to table at the lua end \relax \xdef\currentstructurelistnumber{\clf_currentsectiontolist}% - % \currentstructuresynchronize has to be called someplace, since it introduces a node + % \currentstructuresynchronize has to be called someplace, since it introduces a node \setstructuresynchronization\currentstructurelistnumber \endgroup} @@ -755,6 +755,9 @@ \setfalse\headshownumber \fi} +% Beware, we do need some node for anchoring marks and normally a zwnj will +% do but it interferes so we deal with it at the \LUA\ end. + \newtoks\everyheadsynchronization \appendtoks @@ -762,8 +765,8 @@ \to \everyheadsynchronization \unexpanded\def\theheadsynchonization - {\the\everyheadsynchronization - \currentstructuresynchronize} + {% no, interferes: \signalcharacter + \the\everyheadsynchronization} % BEWARE: \marking[section]{my text} does not work as we use list indices instead % so we need a 'keep track of raw set option' (or maybe a funny internal prefix) @@ -983,8 +986,8 @@ \unexpanded\def\strc_rendering_place_head_section % see hidden below {\global\setbox\b_sectioning_delayed\hpack\bgroup \setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}% - \hpack\headreferenceattributes{}% - \currentstructuresynchronize + \hpack\headreferenceattributes{}% also does the mark + \theheadsynchonization \egroup} \unexpanded\def\strc_rendering_place_head_hidden % maybe trialtypesetting check @@ -994,7 +997,7 @@ {\noexpand\letgvalue{\??hiddenheadsync\currenthead}\relax \noexpand\setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}% \hpack\headreferenceattributes{}% otherwise no destination ... maybe tag ref as hidden and fall back on page reference - \currentstructuresynchronize}} % and it's a node anyway + \theheadsynchonization}} % and it's a node anyway \def\synchronizehead #1{\csname\??hiddenheadsync#1\endcsname} \def\theheadreferenceattributes#1{\csname\??hiddenheadattr#1\endcsname} diff --git a/tex/context/base/mkiv/supp-box.lua b/tex/context/base/mkiv/supp-box.lua index 3ea16dcf8..dc680cda0 100644 --- a/tex/context/base/mkiv/supp-box.lua +++ b/tex/context/base/mkiv/supp-box.lua @@ -62,10 +62,12 @@ local flush_list = nuts.flush_list local copy_node = nuts.copy local copy_list = nuts.copy_list local find_tail = nuts.tail -local traverse_id = nuts.traverse_id local list_dimensions = nuts.dimensions local hpack = nuts.hpack +local nextdisc = nuts.traversers.disc +local nexthlist = nuts.traversers.hlist + local listtoutf = nodes.listtoutf local nodepool = nuts.pool @@ -128,7 +130,7 @@ implement { -- local function hyphenatedhack(head,pre) -- pre = tonut(pre) --- for n in traverse_id(disc_code,tonut(head)) do +-- for n in nextdisc, tonut(head) do -- local hyphen = getfield(n,"pre") -- if hyphen then -- flush_list(hyphen) @@ -422,7 +424,7 @@ local function firstdirinbox(n) if b then local l = getlist(b) if l then - for h in traverse_id(hlist_code,l) do + for h in nexthlist, l do return getdir(h) end end diff --git a/tex/context/base/mkiv/syst-aux.mkiv b/tex/context/base/mkiv/syst-aux.mkiv index ee5761af0..1b56cbd7c 100644 --- a/tex/context/base/mkiv/syst-aux.mkiv +++ b/tex/context/base/mkiv/syst-aux.mkiv @@ -345,6 +345,18 @@ \let\doifnextoptionalelse \doifelsenextoptional \let\doifnextoptionalcselse\doifelsenextoptionalcs +% fails on assignments +% +% \unexpanded\def\doifelsenextoptional {\afterassignment\doifelsenextoptional_n \def\m_syst_action_yes} +% \def\doifelsenextoptional_n {\afterassignment\doifelsenextoptional_n_n\def\m_syst_action_nop} +% \def\doifelsenextoptional_n_n {\let\if_next_blank_space_token\iffalse +% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} +% +% \unexpanded\def\doifelsenextoptionalcs {\afterassignment\doifelsenextoptionalcs_n \let\m_syst_action_yes} +% \def\doifelsenextoptionalcs_n {\afterassignment\doifelsenextoptionalcs_n_n\let\m_syst_action_nop} +% \def\doifelsenextoptionalcs_n_n{\let\if_next_blank_space_token\iffalse +% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character} + \def\syst_helpers_inspect_next_optional_character {\ifx\nexttoken\blankspace \expandafter\syst_helpers_reinspect_next_optional_character @@ -728,6 +740,23 @@ \expandafter\secondoftwoarguments \fi} +%D Slightly faster on longer arguments (0.179 downto 0.141): +%D +%D \testfeatureonce{100000}{\doifelse{aaaaaaaaaaaaaaa}{bbbbbbbbbbbbbbb}\relax\relax} + +% \unexpanded\def\doifelse +% {\afterassignment\doifelse_n\edef\m_syst_string_one} +% +% \unexpanded\def\doifelse_n +% {\afterassignment\doifelse_n_n\edef\m_syst_string_two} +% +% \unexpanded\def\doifelse_n_n +% {\ifx\m_syst_string_one\m_syst_string_two +% \expandafter\firstoftwoarguments +% \else +% \expandafter\secondoftwoarguments +% \fi} + %D \macros %D {doifempty,doifemptyelse,doifnotempty} %D diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv index 181ec05be..ee8663293 100644 --- a/tex/context/base/mkiv/syst-ini.mkiv +++ b/tex/context/base/mkiv/syst-ini.mkiv @@ -214,13 +214,13 @@ \countdef \c_syst_max_allocated_read = 55 \c_syst_max_allocated_read = 16 \countdef \c_syst_min_allocated_language = 56 \c_syst_min_allocated_language = 0 \countdef \c_syst_max_allocated_language = 57 \c_syst_max_allocated_language = 255 -\countdef \c_syst_max_allocated_insert = 58 \c_syst_max_allocated_insert = 254 -\countdef \c_syst_min_allocated_insert = 59 \c_syst_min_allocated_insert = 128 +\countdef \c_syst_min_allocated_insert = 58 \c_syst_min_allocated_insert = 128 +\countdef \c_syst_max_allocated_insert = 59 \c_syst_max_allocated_insert = 254 \countdef \c_syst_min_allocated_family = 60 \c_syst_min_allocated_family = 128 \countdef \c_syst_max_allocated_family = 61 \c_syst_max_allocated_family = 255 -\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 127-1023 : private -\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0 % luatex >= 0.82 -\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 127 % luatex >= 0.82 +\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 0-1023 : private +\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0 +\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 127 \countdef \c_syst_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register \countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register diff --git a/tex/context/base/mkiv/syst-lua.mkiv b/tex/context/base/mkiv/syst-lua.mkiv index ca5f9679f..3600dac34 100644 --- a/tex/context/base/mkiv/syst-lua.mkiv +++ b/tex/context/base/mkiv/syst-lua.mkiv @@ -19,6 +19,42 @@ \def\expdoif #1#2{\clf_doifsame {#1}{#2}} \def\expdoifnot #1#2{\clf_doifnotsame {#1}{#2}} +%D Here is variant using a brainwave of the 12\high{+} hour \quotation {Long Road +%D Out of Eden}\footnote {Eden being Backo\TeX\ 2018, where the virtues of the \type +%D {\expanded} primitive were mentioned in talks.} trip. For now I don't really see +%D other useful applications. + +\ifdefined\immediateassignment + + \def\expandeddoif#1#2% + {\immediateassignment\edef\m_syst_string_one{#1}% + \immediateassignment\edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + + \def\expandeddoifnot#1#2% + {\immediateassignment\edef\m_syst_string_one{#1}% + \immediateassignment\edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + + \def\expandeddoifelse#1#2% + {\immediateassignment\edef\m_syst_string_one{#1}% + \immediateassignment\edef\m_syst_string_two{#2}% + \ifx\m_syst_string_one\m_syst_string_two + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\fi + % \testfeatureonce{100000}{\doifelse{hello world}{here i am}{}} % 0.3 % \testfeatureonce{100000}{\expandabledoifelse{hello world}{here i am}{}} % 1.5 diff --git a/tex/context/base/mkiv/tabl-tbl.mkiv b/tex/context/base/mkiv/tabl-tbl.mkiv index f80813eef..ff2c0f4e5 100644 --- a/tex/context/base/mkiv/tabl-tbl.mkiv +++ b/tex/context/base/mkiv/tabl-tbl.mkiv @@ -622,18 +622,18 @@ \tabl_tabulate_set_preamble} \def\tabl_tabulate_set_preskip#1% - {\doifelsenumber{#1} - {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble } + {\doifelsenumber{#1}% + {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }% {\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}} \def\tabl_tabulate_set_posskip#1% - {\doifelsenumber{#1} - {\s_tabl_tabulate_post#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble } + {\doifelsenumber{#1}% + {\s_tabl_tabulate_post#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }% {\s_tabl_tabulate_post.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}} \def\tabl_tabulate_set_preposskip#1% - {\doifelsenumber{#1} - {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble } + {\doifelsenumber{#1}% + {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble }% {\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble#1}} \def\tabl_tabulate_set_setups#1% @@ -1293,7 +1293,7 @@ \fi\fi} \def\tabl_tabulate_outside_after_indeed - {\tabulationparameter\c!after}% + {\tabulationparameter\c!after} \def\tabl_tabulate_outside_inbetween_indeed {\doifempty{\tabulationparameter\c!after} diff --git a/tex/context/base/mkiv/task-ini.lua b/tex/context/base/mkiv/task-ini.lua index 27d997584..29ae69eb1 100644 --- a/tex/context/base/mkiv/task-ini.lua +++ b/tex/context/base/mkiv/task-ini.lua @@ -18,226 +18,130 @@ if not modules then modules = { } end modules ['task-ini'] = { -- not apply the font handler, we can remove all checks for subtypes 255 local tasks = nodes.tasks -local prependaction = tasks.prependaction local appendaction = tasks.appendaction local disableaction = tasks.disableaction local enableaction = tasks.enableaction local freezegroup = tasks.freezegroup local freezecallbacks = callbacks.freeze -appendaction("processors", "normalizers", "languages.replacements.handler") -- disabled - -appendaction("processors", "normalizers", "typesetters.wrappers.handler") -- disabled -appendaction("processors", "normalizers", "typesetters.characters.handler") -- always on -appendaction("processors", "normalizers", "fonts.collections.process") -- disabled -appendaction("processors", "normalizers", "fonts.checkers.missing") -- disabled - -appendaction("processors", "characters", "scripts.autofontfeature.handler") -appendaction("processors", "characters", "scripts.splitters.handler") -- disabled -appendaction("processors", "characters", "typesetters.cleaners.handler") -- disabled -appendaction("processors", "characters", "typesetters.directions.handler") -- disabled -appendaction("processors", "characters", "typesetters.cases.handler") -- disabled -appendaction("processors", "characters", "typesetters.breakpoints.handler") -- disabled -appendaction("processors", "characters", "scripts.injectors.handler") -- disabled - -------------("processors", "words", "languages.replacements.handler") -- disabled -appendaction("processors", "words", "languages.words.check") -- disabled -- might move up, no disc check needed then -appendaction("processors", "words", "languages.hyphenators.handler") -- always on -appendaction("processors", "words", "typesetters.initials.handler") -- disabled -- might move up -appendaction("processors", "words", "typesetters.firstlines.handler") -- disabled - -appendaction("processors", "fonts", "builders.paragraphs.solutions.splitters.split") -- experimental -appendaction("processors", "fonts", "nodes.handlers.characters") -- maybe todo -appendaction("processors", "fonts", "nodes.injections.handler") -appendaction("processors", "fonts", "typesetters.fontkerns.handler") -appendaction("processors", "fonts", "nodes.handlers.protectglyphs", nil, "nohead") -- maybe todo -appendaction("processors", "fonts", "builders.kernel.ligaturing") -- not always on (could be selective: if only node mode) -appendaction("processors", "fonts", "builders.kernel.kerning") -- not always on (could be selective: if only node mode) -appendaction("processors", "fonts", "nodes.handlers.stripping") -- disabled (might move) -------------("processors", "fonts", "typesetters.italics.handler") -- disabled (after otf/kern handling) -appendaction("processors", "fonts", "nodes.handlers.flatten") - -appendaction("processors", "lists", "typesetters.rubies.check") -- disabled (maybe someplace else) -appendaction("processors", "lists", "typesetters.characteralign.handler") -- disabled (we need to to this after otf appliance) -appendaction("processors", "lists", "typesetters.spacings.handler") -- disabled -appendaction("processors", "lists", "typesetters.kerns.handler") -- disabled -appendaction("processors", "lists", "typesetters.digits.handler") -- disabled (after otf handling) -appendaction("processors", "lists", "typesetters.italics.handler") -- disabled (after otf/kern handling) -appendaction("processors", "lists", "languages.visualizediscretionaries") -- disabled - -appendaction("processors", "after", "typesetters.marksuspects") - -appendaction("shipouts", "normalizers", "typesetters.showsuspects") -appendaction("shipouts", "normalizers", "typesetters.margins.finalhandler") -- disabled -------------("shipouts", "normalizers", "nodes.handlers.cleanuppage") -- disabled -appendaction("shipouts", "normalizers", "builders.paragraphs.expansion.trace") -- disabled -appendaction("shipouts", "normalizers", "typesetters.alignments.handler") -- disabled -appendaction("shipouts", "normalizers", "nodes.references.handler") -- disabled -appendaction("shipouts", "normalizers", "nodes.destinations.handler") -- disabled -appendaction("shipouts", "normalizers", "nodes.rules.handler") -- disabled -appendaction("shipouts", "normalizers", "nodes.shifts.handler") -- disabled -appendaction("shipouts", "normalizers", "structures.tags.handler") -- disabled -appendaction("shipouts", "normalizers", "nodes.handlers.accessibility") -- disabled -appendaction("shipouts", "normalizers", "nodes.handlers.backgrounds") -- disabled -------------("shipouts", "normalizers", "nodes.handlers.export") -- disabled -appendaction("shipouts", "normalizers", "typesetters.rubies.attach") -- disabled - -appendaction("shipouts", "finishers", "nodes.visualizers.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.colors.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.transparencies.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.colorintents.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.negatives.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.effects.handler") -- disabled -appendaction("shipouts", "finishers", "attributes.viewerlayers.handler") -- disabled - ---maybe integrate relocate and families - -appendaction("math", "normalizers", "noads.handlers.showtree", nil, "nohead") - -appendaction("math", "normalizers", "noads.handlers.unscript", nil, "nohead") -- always on (maybe disabled) -appendaction("math", "normalizers", "noads.handlers.variants", nil, "nohead") -- always on -appendaction("math", "normalizers", "noads.handlers.relocate", nil, "nohead") -- always on -appendaction("math", "normalizers", "noads.handlers.families", nil, "nohead") -- always on - -appendaction("math", "normalizers", "noads.handlers.render", nil, "nohead") -- always on -appendaction("math", "normalizers", "noads.handlers.collapse", nil, "nohead") -- disabled -appendaction("math", "normalizers", "noads.handlers.fixscripts",nil, "nohead") -- * first-- always on -appendaction("math", "normalizers", "noads.handlers.domains", nil, "nohead") -- * last -- disabled -appendaction("math", "normalizers", "noads.handlers.autofences",nil, "nohead") -- disabled -appendaction("math", "normalizers", "noads.handlers.resize", nil, "nohead") -- always on -------------("math", "normalizers", "noads.handlers.respace", nil, "nohead") -- always on -appendaction("math", "normalizers", "noads.handlers.alternates",nil, "nohead") -- always on -appendaction("math", "normalizers", "noads.handlers.tags", nil, "nohead") -- disabled -appendaction("math", "normalizers", "noads.handlers.italics", nil, "nohead") -- disabled -appendaction("math", "normalizers", "noads.handlers.kernpairs", nil, "nohead") -- disabled -appendaction("math", "normalizers", "noads.handlers.classes", nil, "nohead") -- disabled - -appendaction("math", "builders", "builders.kernel.mlist_to_hlist") -- always on -------------("math", "builders", "noads.handlers.italics", nil, "nohead") -- disabled -appendaction("math", "builders", "typesetters.directions.processmath") -- disabled (has to happen pretty late) -appendaction("math", "builders", "noads.handlers.makeup", nil, "nohead") -- disabled (has to happen last) -appendaction("math", "builders", "noads.handlers.align", nil, "nohead") - -appendaction("finalizers", "lists", "typesetters.paragraphs.normalize") -- moved here -appendaction("finalizers", "lists", "typesetters.margins.localhandler") -- disabled -appendaction("finalizers", "lists", "builders.paragraphs.keeptogether") -------------("finalizers", "lists", "nodes.handlers.graphicvadjust") -- todo -appendaction("finalizers", "fonts", "builders.paragraphs.solutions.splitters.optimize") -- experimental -appendaction("finalizers", "lists", "builders.paragraphs.tag") - --- the next can also be in contributers normalizers (when we remove the loop in the handler) - -appendaction("finalizers", "lists", "nodes.linefillers.handler") - -appendaction("contributers", "normalizers", "nodes.handlers.flattenline") -appendaction("contributers", "normalizers", "nodes.handlers.textbackgrounds") - -appendaction("vboxbuilders", "normalizers", "nodes.handlers.backgroundsvbox") -appendaction("mvlbuilders", "normalizers", "nodes.handlers.backgroundspage") - -appendaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler") -- disabled -appendaction("mvlbuilders", "normalizers", "nodes.handlers.migrate") - -appendaction("mvlbuilders", "normalizers", "builders.vspacing.pagehandler") -- last ! -appendaction("mvlbuilders", "normalizers", "builders.profiling.pagehandler") -- here ! - -------------("vboxbuilders", "normalizers", "typesetters.margins.localhandler") -appendaction("vboxbuilders", "normalizers", "builders.vspacing.vboxhandler") -appendaction("vboxbuilders", "normalizers", "builders.profiling.vboxhandler") -- here ! - --- experimental too - -appendaction("mvlbuilders", "normalizers", "typesetters.checkers.handler") -appendaction("vboxbuilders", "normalizers", "typesetters.checkers.handler") - --- rather special (this might get hardcoded): - -prependaction("processors", "before", "nodes.properties.attach") -- enabled but optimized for quick abort -appendaction ("shipouts", "normalizers", "nodes.properties.delayed") -- enabled but optimized for quick abort - --- speedup: only kick in when used - -disableaction("processors", "typesetters.wrappers.handler") -disableaction("processors", "languages.replacements.handler") -disableaction("processors", "typesetters.characteralign.handler") -disableaction("processors", "scripts.autofontfeature.handler") -disableaction("processors", "scripts.splitters.handler") -disableaction("processors", "scripts.injectors.handler") -- was enabled -disableaction("processors", "fonts.collections.process") -disableaction("processors", "fonts.checkers.missing") -disableaction("processors", "chars.handle_breakpoints") -disableaction("processors", "typesetters.cleaners.handler") -disableaction("processors", "typesetters.cases.handler") -disableaction("processors", "typesetters.digits.handler") -disableaction("processors", "typesetters.breakpoints.handler") -disableaction("processors", "typesetters.directions.handler") -disableaction("processors", "languages.words.check") -disableaction("processors", "typesetters.initials.handler") -disableaction("processors", "typesetters.firstlines.handler") -disableaction("processors", "typesetters.spacings.handler") -disableaction("processors", "typesetters.kerns.handler") -disableaction("processors", "typesetters.italics.handler") -disableaction("processors", "languages.visualizediscretionaries") -disableaction("processors", "nodes.handlers.stripping") -disableaction("processors", "builders.paragraphs.solutions.splitters.split") -disableaction("processors", "typesetters.rubies.check") -disableaction("processors", "typesetters.fontkerns.handler") -disableaction("processors", "nodes.handlers.flatten") -disableaction("processors", "typesetters.marksuspects") - -disableaction("shipouts", "typesetters.showsuspects") -disableaction("shipouts", "typesetters.margins.finalhandler") -disableaction("shipouts", "builders.paragraphs.expansion.trace") -disableaction("shipouts", "typesetters.alignments.handler") -disableaction("shipouts", "nodes.rules.handler") -disableaction("shipouts", "nodes.shifts.handler") -disableaction("shipouts", "attributes.colors.handler") -disableaction("shipouts", "attributes.transparencies.handler") -disableaction("shipouts", "attributes.colorintents.handler") -disableaction("shipouts", "attributes.effects.handler") -disableaction("shipouts", "attributes.negatives.handler") -disableaction("shipouts", "attributes.viewerlayers.handler") -disableaction("shipouts", "structures.tags.handler") -disableaction("shipouts", "nodes.visualizers.handler") -disableaction("shipouts", "nodes.handlers.accessibility") -disableaction("shipouts", "nodes.references.handler") -disableaction("shipouts", "nodes.destinations.handler") -disableaction("shipouts", "nodes.handlers.backgrounds") --------------("shipouts", "nodes.handlers.export") -disableaction("shipouts", "typesetters.rubies.attach") - -disableaction("finalizers", "typesetters.margins.localhandler") -disableaction("finalizers", "builders.paragraphs.keeptogether") -disableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize") --------------("finalizers", "nodes.handlers.graphicvadjust") -- sort of obsolete -disableaction("finalizers", "builders.paragraphs.tag") -disableaction("finalizers", "nodes.linefillers.handler") - -disableaction("contributers","nodes.handlers.flattenline") -disableaction("contributers","nodes.handlers.textbackgrounds") - -disableaction("vboxbuilders","nodes.handlers.backgroundsvbox") -disableaction("mvlbuilders", "nodes.handlers.backgroundspage") - -disableaction("math", "noads.handlers.showtree") -disableaction("math", "noads.handlers.tags") -disableaction("math", "noads.handlers.italics") -disableaction("math", "noads.handlers.collapse") -disableaction("math", "noads.handlers.kernpairs") -disableaction("math", "noads.handlers.domains") -disableaction("math", "noads.handlers.classes") -disableaction("math", "noads.handlers.autofences") -disableaction("math", "noads.handlers.makeup") -disableaction("math", "typesetters.directions.processmath") - -disableaction("mvlbuilders", "typesetters.margins.globalhandler") -disableaction("mvlbuilders", "nodes.handlers.migrate") -disableaction("mvlbuilders", "typesetters.checkers.handler") -disableaction("mvlbuilders", "builders.profiling.pagehandler") - --------------("vboxbuilders","typesetters.margins.localhandler") -disableaction("vboxbuilders","typesetters.checkers.handler") -disableaction("vboxbuilders","builders.profiling.vboxhandler") +appendaction("processors", "before", "nodes.properties.attach", nil, "nut", "enabled" ) + +appendaction("processors", "normalizers", "typesetters.periodkerns.handler", nil, "nut", "disabled" ) +appendaction("processors", "normalizers", "languages.replacements.handler", nil, "nut", "disabled" ) +appendaction("processors", "normalizers", "typesetters.wrappers.handler", nil, "nut", "disabled" ) +appendaction("processors", "normalizers", "typesetters.characters.handler", nil, "nut", "enabled" ) +appendaction("processors", "normalizers", "fonts.collections.process", nil, "nut", "disabled" ) +appendaction("processors", "normalizers", "fonts.checkers.missing", nil, "nut", "disabled" ) + +appendaction("processors", "characters", "scripts.autofontfeature.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "scripts.splitters.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "typesetters.cleaners.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "typesetters.directions.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "typesetters.cases.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "typesetters.breakpoints.handler", nil, "nut", "disabled" ) +appendaction("processors", "characters", "scripts.injectors.handler", nil, "nut", "disabled" ) + +appendaction("processors", "words", "languages.words.check", nil, "nut", "disabled" ) +appendaction("processors", "words", "languages.hyphenators.handler", nil, "nut", "enabled" ) +appendaction("processors", "words", "typesetters.initials.handler", nil, "nut", "disabled" ) +appendaction("processors", "words", "typesetters.firstlines.handler", nil, "nut", "disabled" ) + +appendaction("processors", "fonts", "builders.paragraphs.solutions.splitters.split", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "nodes.handlers.characters", nil, "nut", "enabled" ) +appendaction("processors", "fonts", "nodes.injections.handler", nil, "nut", "enabled" ) +appendaction("processors", "fonts", "typesetters.fontkerns.handler", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "nodes.handlers.protectglyphs", nil, "nonut", "enabled" ) +appendaction("processors", "fonts", "builders.kernel.ligaturing", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "builders.kernel.kerning", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "nodes.handlers.stripping", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "nodes.handlers.flatten", nil, "nut", "disabled" ) +appendaction("processors", "fonts", "fonts.goodies.colorschemes.coloring", nil, "nut", "disabled" ) + +appendaction("processors", "lists", "typesetters.rubies.check", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.characteralign.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.spacings.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.kerns.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.digits.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "typesetters.italics.handler", nil, "nut", "disabled" ) +appendaction("processors", "lists", "languages.visualizediscretionaries", nil, "nut", "disabled" ) + +appendaction("processors", "after", "typesetters.marksuspects", nil, "nut", "disabled" ) + +appendaction("shipouts", "normalizers", "typesetters.showsuspects", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "typesetters.margins.finalhandler", nil, "nut", "disabled" ) +------------("shipouts", "normalizers", "nodes.handlers.cleanuppage", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "builders.paragraphs.expansion.trace", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "typesetters.alignments.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "nodes.references.handler", nil, "nut", "production") +appendaction("shipouts", "normalizers", "nodes.destinations.handler", nil, "nut", "production") +appendaction("shipouts", "normalizers", "nodes.rules.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "nodes.shifts.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "structures.tags.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "nodes.handlers.accessibility", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "nodes.handlers.backgrounds", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "typesetters.rubies.attach", nil, "nut", "disabled" ) +appendaction("shipouts", "normalizers", "nodes.properties.delayed", nil, "nut", "production") +appendaction("shipouts", "normalizers", "backends.pdf.nodeinjections.finalizepage", nil, "nut", "production") + +appendaction("shipouts", "finishers", "nodes.visualizers.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.colors.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.transparencies.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.colorintents.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.negatives.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.effects.handler", nil, "nut", "disabled" ) +appendaction("shipouts", "finishers", "attributes.viewerlayers.handler", nil, "nut", "disabled" ) + +appendaction("shipouts", "wrapup", "nodes.handlers.export", nil, "nut", "disabled" ) -- always last +appendaction("shipouts", "wrapup", "luatex.synctex.collect", nil, "nut", "disabled" ) + + +appendaction("math", "normalizers", "noads.handlers.showtree", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.unscript", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.variants", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.relocate", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.families", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.render", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.collapse", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.fixscripts", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.domains", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.autofences", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.resize", nil, "nonut", "enabled" ) +------------("math", "normalizers", "noads.handlers.respace", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.alternates", nil, "nonut", "enabled" ) +appendaction("math", "normalizers", "noads.handlers.tags", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.italics", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.kernpairs", nil, "nonut", "disabled" ) +appendaction("math", "normalizers", "noads.handlers.classes", nil, "nonut", "disabled" ) + +appendaction("math", "builders", "builders.kernel.mlist_to_hlist", nil, "node", "enabled" ) -- mandate +appendaction("math", "builders", "typesetters.directions.processmath", nil, "nut", "disabled" ) +appendaction("math", "builders", "noads.handlers.makeup", nil, "nonut", "disabled" ) +appendaction("math", "builders", "noads.handlers.align", nil, "nonut", "enabled" ) + +appendaction("finalizers", "lists", "typesetters.paragraphs.normalize", nil, "nut", "disabled" ) +appendaction("finalizers", "lists", "typesetters.margins.localhandler", nil, "nut", "disabled" ) +appendaction("finalizers", "lists", "builders.paragraphs.keeptogether", nil, "nut", "disabled" ) +appendaction("finalizers", "fonts", "builders.paragraphs.solutions.splitters.optimize", nil, "nut", "disabled" ) +appendaction("finalizers", "lists", "builders.paragraphs.tag", nil, "nut", "disabled" ) +appendaction("finalizers", "lists", "nodes.linefillers.handler", nil, "nut", "disabled" ) + +appendaction("contributers", "normalizers", "nodes.handlers.flattenline", nil, "nut", "disabled" ) +appendaction("contributers", "normalizers", "nodes.handlers.textbackgrounds", nil, "nut", "disabled" ) + +appendaction("vboxbuilders", "normalizers", "nodes.handlers.backgroundsvbox", nil, "nut", "disabled" ) +--------("vboxbuilders", "normalizers", "typesetters.margins.localhandler", nil, "nut", "disabled" ) +appendaction("vboxbuilders", "normalizers", "builders.vspacing.vboxhandler", nil, "nut", "enabled" ) +appendaction("vboxbuilders", "normalizers", "builders.profiling.vboxhandler", nil, "nut", "disabled" ) +appendaction("vboxbuilders", "normalizers", "typesetters.checkers.handler", nil, "nut", "disabled" ) + +appendaction("mvlbuilders", "normalizers", "nodes.handlers.backgroundspage", nil, "nut", "disabled" ) +appendaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler", nil, "nut", "disabled" ) +appendaction("mvlbuilders", "normalizers", "nodes.handlers.migrate", nil, "nut", "disabled" ) +appendaction("mvlbuilders", "normalizers", "builders.vspacing.pagehandler", nil, "nut", "enabled" ) +appendaction("mvlbuilders", "normalizers", "builders.profiling.pagehandler", nil, "nut", "disabled" ) +appendaction("mvlbuilders", "normalizers", "typesetters.checkers.handler", nil, "nut", "disabled" ) + +-- some protection freezecallbacks("find_.*_file", "find file using resolver") freezecallbacks("read_.*_file", "read file at once") @@ -255,8 +159,12 @@ freezegroup("finalizers", "normalizers") freezegroup("finalizers", "fonts") freezegroup("finalizers", "lists") +freezegroup("math", "normalizers") +freezegroup("math", "builders") + freezegroup("shipouts", "normalizers") freezegroup("shipouts", "finishers") +freezegroup("shipouts", "wrapup") freezegroup("mvlbuilders", "normalizers") freezegroup("vboxbuilders", "normalizers") @@ -269,13 +177,10 @@ freezegroup("math", "builders") -- new: disabled here -disableaction("processors", "builders.kernel.ligaturing") -disableaction("processors", "builders.kernel.kerning") - directives.register("nodes.basepass", function(v) if v then - enableaction("processors", "builders.kernel.ligaturing") - enableaction("processors", "builders.kernel.kerning") + enableaction("processors", "builders.kernel.ligaturing") + enableaction("processors", "builders.kernel.kerning") else disableaction("processors", "builders.kernel.ligaturing") disableaction("processors", "builders.kernel.kerning") diff --git a/tex/context/base/mkiv/trac-jus.lua b/tex/context/base/mkiv/trac-jus.lua index e7a030257..0acb685ed 100644 --- a/tex/context/base/mkiv/trac-jus.lua +++ b/tex/context/base/mkiv/trac-jus.lua @@ -15,7 +15,6 @@ local a_alignstate = attributes.private("alignstate") local a_justification = attributes.private("justification") local nuts = nodes.nuts -local tonut = nuts.tonut local getfield = nuts.getfield local getlist = nuts.getlist @@ -26,7 +25,8 @@ local setlink = nuts.setlink local getwidth = nuts.getwidth local findtail = nuts.tail -local traverse_id = nuts.traverse_id +local nexthlist = nuts.traversers.hlist + local list_dimensions = nuts.dimensions local copy_list = nuts.copy_list @@ -77,7 +77,7 @@ trackers.register("visualizers.justification", function(v) end) function checkers.handler(head) - for current in traverse_id(hlist_code,tonut(head)) do + for current in nexthlist, head do if getattr(current,a_justification) == 1 then setattr(current,a_justification,0) -- kind of reset local width = getwidth(current) diff --git a/tex/context/base/mkiv/trac-par.lua b/tex/context/base/mkiv/trac-par.lua index 56291f8c8..f16078483 100644 --- a/tex/context/base/mkiv/trac-par.lua +++ b/tex/context/base/mkiv/trac-par.lua @@ -125,7 +125,7 @@ end builders.paragraphs.expansion = builders.paragraphs.expansion or { } function builders.paragraphs.expansion.trace(head) - colorize(tonut(head),true) + colorize(head,true) return head end diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua index 91ee1cf7d..e744f84f2 100644 --- a/tex/context/base/mkiv/trac-vis.lua +++ b/tex/context/base/mkiv/trac-vis.lua @@ -74,11 +74,12 @@ local copy_list = nuts.copy_list local flush_node_list = nuts.flush_list local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after -local traverse_nodes = nuts.traverse local apply_to_nodes = nuts.apply local find_tail = nuts.tail local effectiveglue = nuts.effective_glue +local nextnode = nuts.traversers.node + local hpack_string = nuts.typesetters.tohpack local texgetattribute = tex.getattribute @@ -188,7 +189,8 @@ end -- we can preset a bunch of bits -local userrule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") +local userrule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") +local outlinerule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") local function enable() if not usedfont then @@ -233,6 +235,9 @@ local function enable() if not userrule then userrule = nuts.rules.userrule end + if not outlinerule then + outlinerule = nuts.pool.outlinerule + end end local function setvisual(n,a,what,list) -- this will become more efficient when we have the bit lib linked in @@ -700,7 +705,7 @@ local ruledbox do local wd, ht, dp = getwhd(current) if wd ~= 0 then local shift = getshift(current) - local dir = getdir(current) + -- local dir = getdir(current) -- if dir == "LTL" or dir == "RRT" then -- wd, ht, dp = ht + dp, wd, 0 -- end @@ -761,7 +766,7 @@ local ruledbox do -- local info = setlink( this and copy_list(this) or nil, - userrule { + (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { width = wd, height = ht, depth = dp, @@ -772,7 +777,7 @@ local ruledbox do ) -- setlisttransparency(info,c_text) - info = new_hlist(info) + -- info = new_hlist(info) -- setattr(info,a_layer,layer) if vertical then @@ -849,10 +854,10 @@ local ruledglyph do -- local wd = chardata[getfont(current)][getchar(current)].width if wd ~= 0 then local wd, ht, dp = getwhd(current) - -- local dir = getdir(current) - -- if dir == "LTL" or dir = "RTT" then - -- wd, ht, dp = ht + dp, wd, 0 - -- end + -- local dir = getdir(current) + -- if dir == "LTL" or dir = "RTT" then + -- wd, ht, dp = ht + dp, wd, 0 + -- end local next = getnext(current) local prev = previous setboth(current) @@ -895,7 +900,7 @@ local ruledglyph do -- userrules: -- info = setlink( - userrule { + (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { width = wd, height = ht, depth = dp, @@ -1198,6 +1203,8 @@ do local listcodes = nodes.listcodes local line_code = listcodes.line + local cache + local function visualize(head,vertical,forced,parent) local trace_hbox = false local trace_vbox = false @@ -1225,6 +1232,58 @@ do local prev_trace_fontkern = nil local prev_trace_italic = nil local prev_trace_expansion = nil + + -- local function setthem(t,k) + -- local v_trace_hbox = band(k, 1) ~= 0 + -- local v_trace_vbox = band(k, 2) ~= 0 + -- local v_trace_vtop = band(k, 4) ~= 0 + -- local v_trace_kern = band(k, 8) ~= 0 + -- local v_trace_glue = band(k, 16) ~= 0 + -- local v_trace_penalty = band(k, 32) ~= 0 + -- local v_trace_fontkern = band(k, 64) ~= 0 + -- local v_trace_strut = band(k, 128) ~= 0 + -- local v_trace_whatsit = band(k, 256) ~= 0 + -- local v_trace_glyph = band(k, 512) ~= 0 + -- local v_trace_simple = band(k, 1024) ~= 0 + -- local v_trace_user = band(k, 2048) ~= 0 + -- local v_trace_math = band(k, 4096) ~= 0 + -- local v_trace_italic = band(k, 8192) ~= 0 + -- local v_trace_origin = band(k, 16384) ~= 0 + -- local v_trace_discretionary = band(k, 32768) ~= 0 + -- local v_trace_expansion = band(k, 65536) ~= 0 + -- local v_trace_line = band(k,131072) ~= 0 + -- local v_trace_space = band(k,262144) ~= 0 + -- local v_trace_depth = band(k,524288) ~= 0 + -- local v = function() + -- trace_hbox = v_trace_hbox + -- trace_vbox = v_trace_vbox + -- trace_vtop = v_trace_vtop + -- trace_kern = v_trace_kern + -- trace_glue = v_trace_glue + -- trace_penalty = v_trace_penalty + -- trace_fontkern = v_trace_fontkern + -- trace_strut = v_trace_strut + -- trace_whatsit = v_trace_whatsit + -- trace_glyph = v_trace_glyph + -- trace_simple = v_trace_simple + -- trace_user = v_trace_user + -- trace_math = v_trace_math + -- trace_italic = v_trace_italic + -- trace_origin = v_trace_origin + -- trace_discretionary = v_trace_discretionary + -- trace_expansion = v_trace_expansion + -- trace_line = v_trace_line + -- trace_space = v_trace_space + -- trace_depth = v_trace_depth + -- end + -- t[k] = v + -- return v + -- end + -- + -- if not cache then + -- cache = setmetatableindex(setthem) + -- end + while current do local id = getid(current) local a = forced or getattr(current,a_visual) or unsetvalue @@ -1254,6 +1313,7 @@ do trace_space = false trace_depth = false else -- dead slow: + -- cache[a]() trace_hbox = band(a, 1) ~= 0 trace_vbox = band(a, 2) ~= 0 trace_vtop = band(a, 4) ~= 0 @@ -1390,9 +1450,9 @@ do local function handler(head) if usedfont then starttiming(visualizers) - head = visualize(tonut(head),true) + head = visualize(head,true) stoptiming(visualizers) - return tonode(head), true + return head, true else return head, false end @@ -1433,7 +1493,7 @@ do } local function markfonts(list) - for n, id in traverse_nodes(list) do + for n, id in nextnode, list do if id == glyph_code then local font = getfont(n) local okay = used[font] diff --git a/tex/context/base/mkiv/typo-bld.lua b/tex/context/base/mkiv/typo-bld.lua index 8d349f3a6..d3dddc990 100644 --- a/tex/context/base/mkiv/typo-bld.lua +++ b/tex/context/base/mkiv/typo-bld.lua @@ -264,19 +264,18 @@ end -- do -- --- local nuts = nodes.nuts --- local tonut = nodes.tonut --- local tonode = nuts.tonode --- local getglue = tex.getglue --- local getwhd = nuts.getwhd --- local new_b_skip = nuts.pool.baselineskip --- local new_l_skip = nuts.pool.lineskip --- local find_tail = nuts.tail --- local setlink = nuts.setlink +-- local nuts = nodes.nuts +-- local getglue = tex.getglue +-- local getwhd = nuts.getwhd +-- local new_b_skip = nuts.pool.baselineskip +-- local new_l_skip = nuts.pool.lineskip +-- local find_tail = nuts.tail +-- local setlink = nuts.setlink +-- local is_mirrored = nodes.is_mirrored -- --- function nodes.setprevdepth(box,prevdepth) -- this will become a helper --- local head = tonut(box) +-- function nuts.setprevdepth(head,prevdepth) -- this will become a helper -- local wd, ht, dp = getwhd(head) +-- local mirrored = false -- getid(box) == hlist_code and is_mirrored(getdir(box)) -- never mirrored -- if prevdepth > -65536000 then -- local b_width, b_stretch, b_shrink = getglue("baselineskip") -- local l_width, l_stretch, l_shrink = getglue("lineskip") @@ -287,7 +286,16 @@ end -- head = setlink(new_b_skip(correction,b_stretch,b_shrink),head) -- end -- end --- return tonode(head), mirrored and ht or dp +-- return head, mirrored and ht or dp +-- end +-- +-- function nodes.setprevdepth(box,prevdepth) +-- local h, p = nodes.prepend_prevdepth(box,prevdepth) +-- if h then +-- return h, p +-- else +-- return head, prevdepth +-- end -- end -- -- end diff --git a/tex/context/base/mkiv/typo-brk.lua b/tex/context/base/mkiv/typo-brk.lua index 51760bbf4..34d4071aa 100644 --- a/tex/context/base/mkiv/typo-brk.lua +++ b/tex/context/base/mkiv/typo-brk.lua @@ -23,7 +23,6 @@ local settings_to_array = utilities.parsers.settings_to_array local nuts = nodes.nuts local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev @@ -241,10 +240,9 @@ end function breakpoints.handler(head) local done = false - local nead = tonut(head) local attr = nil local map = nil - local current = nead + local current = head while current do local char, id = isglyph(current) if char then @@ -313,7 +311,7 @@ function breakpoints.handler(head) end end if not done then - return head, false + return head end -- we have hits local numbers = languages.numbers @@ -383,13 +381,13 @@ function breakpoints.handler(head) if nright == cright then local method = methods[smap.type] if method then - nead, start = method(nead,start,stop,smap,kern) + head, start = method(head,start,stop,smap,kern) end end -- end end end - return tonode(nead), true + return head end local enabled = false diff --git a/tex/context/base/mkiv/typo-cap.lua b/tex/context/base/mkiv/typo-cap.lua index 4dffd1c49..4383dc6b9 100644 --- a/tex/context/base/mkiv/typo-cap.lua +++ b/tex/context/base/mkiv/typo-cap.lua @@ -18,8 +18,6 @@ local report_casing = logs.reporter("typesetting","casing") local nodes, node = nodes, node local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut local getnext = nuts.getnext local getprev = nuts.getprev @@ -37,10 +35,11 @@ local setfont = nuts.setfont local copy_node = nuts.copy local end_of_math = nuts.end_of_math -local traverse_id = nuts.traverse_id local insert_after = nuts.insert_after local find_attribute = nuts.find_attribute +local nextglyph = nuts.traversers.glyph + local nodecodes = nodes.nodecodes local skipcodes = nodes.skipcodes local kerncodes = nodes.kerncodes @@ -149,13 +148,11 @@ local function replacer(start,codes) insert_after(start,start,g) end end - return start, true elseif ifc[dc] then setchar(start,dc) - return start, true end end - return start, false + return start end local registered, n = { }, 0 @@ -191,9 +188,9 @@ local function Words(start,attr,lastfont,n,count,where,first) -- looks quite com end if count == 1 and where ~= "post" then replacer(first or start,uccodes) - return start, true, true + return start, true else - return start, false, true + return start, true end end @@ -203,9 +200,9 @@ local function Word(start,attr,lastfont,n,count,where,first) end local function camel(start,attr,lastfont,n,count,where,first) - local _, done_1 = word(start,attr,lastfont,n,count,where,first) - local _, done_2 = Words(start,attr,lastfont,n,count,where,first) - return start, done_1 or done_2, true + word(start,attr,lastfont,n,count,where,first) + Words(start,attr,lastfont,n,count,where,first) + return start, true end -- local function mixed(start,attr,lastfont,n,count,where,first) @@ -216,19 +213,16 @@ end -- local char = getchar(first) -- local dc = uccodes[char] -- if not dc then --- return start, false, true +-- -- quit -- elseif dc == char then -- local lfa = lastfont[n] -- if lfa then -- setfont(first,lfa) --- return start, true, true --- else --- return start, false, true -- end -- else -- replacer(first or start,uccodes) --- return start, true, true -- end +-- return start, true -- end local function mixed(start,attr,lastfont,n,count,where,first) @@ -239,38 +233,33 @@ local function mixed(start,attr,lastfont,n,count,where,first) local char = getchar(used) local dc = uccodes[char] if not dc then - return start, false, true + -- quit elseif dc == char then local lfa = lastfont[n] if lfa then setfont(used,lfa) - return start, true, true - else - return start, false, true end - else - if check_kerns then - local p = getprev(used) - if p and getid(p) == glyph_code then - local c = lccodes[char] - local c = type(c) == "table" and c[1] or c - replacer(used,uccodes) - local fp = getfont(p) - local fc = getfont(used) - if fp ~= fc then - local k = fonts.getkern(fontdata[fp],getchar(p),c) - if k ~= 0 then - insert_after(p,p,newkern(k)) - end + elseif check_kerns then + local p = getprev(used) + if p and getid(p) == glyph_code then + local c = lccodes[char] + local c = type(c) == "table" and c[1] or c + replacer(used,uccodes) + local fp = getfont(p) + local fc = getfont(used) + if fp ~= fc then + local k = fonts.getkern(fontdata[fp],getchar(p),c) + if k ~= 0 then + insert_after(p,p,newkern(k)) end - else - replacer(used,uccodes) end else replacer(used,uccodes) end - return start, true, true + else + replacer(used,uccodes) end + return start, true end local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3 @@ -284,11 +273,11 @@ local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3 end end end - local s, d, c = replacer(first or start,uccodes) + local s, c = replacer(first or start,uccodes) if once then lastfont[n] = false -- here end - return start, d, c + return start, c end local function capital(start,attr,lastfont,n,where,count,first,count) -- 4 @@ -296,7 +285,7 @@ local function capital(start,attr,lastfont,n,where,count,first,count) -- 4 end local function none(start,attr,lastfont,n,count,where,first) - return start, false, true + return start, true end local function randomized(start,attr,lastfont,n,count,where,first) @@ -311,7 +300,7 @@ local function randomized(start,attr,lastfont,n,count,where,first) local n = getrandom("capital lu",0x41,0x5A) if tfm[n] then -- this also intercepts tables setchar(used,n) - return start, true + return start end end elseif kind == "ll" then @@ -319,11 +308,11 @@ local function randomized(start,attr,lastfont,n,count,where,first) local n = getrandom("capital ll",0x61,0x7A) if tfm[n] then -- this also intercepts tables setchar(used,n) - return start, true + return start end end end - return start, false + return start end register(variables.WORD, WORD) -- 1 @@ -341,10 +330,9 @@ register(variables.cap, variables.capital) -- clone register(variables.Cap, variables.Capital) -- clone function cases.handler(head) -- not real fast but also not used on much data - local start = tonut(head) + local start = head local lastfont = { } local lastattr = nil - local done = false local count = 0 local previd = nil local prev = nil @@ -367,10 +355,7 @@ function cases.handler(head) -- not real fast but also not used on much data end local action = actions[n] -- map back to low number if action then - start, ok = action(start,attr,lastfont,n,count) - if ok then - done = true - end + start = action(start,attr,lastfont,n,count) if trace_casing then report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,ok) end @@ -396,32 +381,38 @@ function cases.handler(head) -- not real fast but also not used on much data local pre, post, replace = getdisc(start) if replace then local cnt = count - for g in traverse_id(glyph_code,replace) do + for g in nextglyph, replace do cnt = cnt + 1 takeattr(g,a_cases) -- setattr(g,a_cases,unsetvalue) - local _, _, quit = action(start,attr,lastfont,n,cnt,"replace",g) - if quit then break end + local h, quit = action(start,attr,lastfont,n,cnt,"replace",g) + if quit then + break + end end end if pre then local cnt = count - for g in traverse_id(glyph_code,pre) do + for g in nextglyph, pre do cnt = cnt + 1 takeattr(g,a_cases) -- setattr(g,a_cases,unsetvalue) - local _, _, quit = action(start,attr,lastfont,n,cnt,"pre",g) - if quit then break end + local h, quit = action(start,attr,lastfont,n,cnt,"pre",g) + if quit then + break + end end end if post then local cnt = count - for g in traverse_id(glyph_code,post) do + for g in nextglyph, post do cnt = cnt + 1 takeattr(g,a_cases) -- setattr(g,a_cases,unsetvalue) - local _, _, quit = action(start,attr,lastfont,n,cnt,"post",g) - if quit then break end + local h, quit = action(start,attr,lastfont,n,cnt,"post",g) + if quit then + break + end end end end @@ -441,17 +432,16 @@ function cases.handler(head) -- not real fast but also not used on much data start = getnext(start) end end - return head, done + return head end -- function cases.handler(head) -- not real fast but also not used on much data --- local attr, start = find_attribute(tonut(head),a_cases) +-- local attr, start = find_attribute(head,a_cases) -- if not start then -- return head, false -- end -- local lastfont = { } -- local lastattr = nil --- local done = false -- local count = 0 -- local previd = nil -- local prev = nil @@ -475,10 +465,7 @@ end -- end -- local action = actions[n] -- map back to low number -- if action then --- start, ok = action(start,attr,lastfont,n,count) --- if ok then --- done = true --- end +-- start = action(start,attr,lastfont,n,count) -- if trace_casing then -- report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,ok) -- end @@ -504,32 +491,38 @@ end -- local pre, post, replace = getdisc(start) -- if replace then -- local cnt = count --- for g in traverse_id(glyph_code,replace) do +-- for g in glyph_code, replace do -- cnt = cnt + 1 -- takeattr(g,a_cases) -- -- setattr(g,a_cases,unsetvalue) --- local _, _, quit = action(start,attr,lastfont,n,cnt,"replace",g) --- if quit then break end +-- local h, quit = action(start,attr,lastfont,n,cnt,"replace",g) +-- if quit then +-- break +-- end -- end -- end -- if pre then -- local cnt = count --- for g in traverse_id(glyph_code,pre) do +-- for g in nextglyph, pre do -- cnt = cnt + 1 -- takeattr(g,a_cases) -- -- setattr(g,a_cases,unsetvalue) --- local _, _, quit = action(start,attr,lastfont,n,cnt,"pre",g) --- if quit then break end +-- local h, quit = action(start,attr,lastfont,n,cnt,"pre",g) +-- if quit then +-- break +-- end -- end -- end -- if post then -- local cnt = count --- for g in traverse_id(glyph_code,post) do +-- for g in nextglyph, post do -- cnt = cnt + 1 -- takeattr(g,a_cases) -- -- setattr(g,a_cases,unsetvalue) --- local _, _, quit = action(start,attr,lastfont,n,cnt,"post",g) --- if quit then break end +-- local h, quit = action(start,attr,lastfont,n,cnt,"post",g) +-- if quit then +-- break +-- end -- end -- end -- end @@ -555,26 +548,22 @@ end -- attr, start = find_attribute(start,a_cases) -- end -- end --- return head, done +-- return head -- end -- function cases.handler(head) -- let's assume head doesn't change ... no reason --- local done = false -- local lastfont = { } --- for first, last, size, attr in nuts.words(tonut(head),a_cases) do +-- for first, last, size, attr in nuts.words(head,a_cases) do -- local n, id, m = get(attr) -- if lastfont[n] == nil then -- lastfont[n] = id -- end -- local action = actions[n] -- if action then --- local _, ok = action(first,attr,lastfont,n) --- if ok then --- done = true --- end +-- action(first,attr,lastfont,n) -- end -- end --- return head, done +-- return head -- end local enabled = false diff --git a/tex/context/base/mkiv/typo-chr.lua b/tex/context/base/mkiv/typo-chr.lua index 80497a492..1aa84f5ab 100644 --- a/tex/context/base/mkiv/typo-chr.lua +++ b/tex/context/base/mkiv/typo-chr.lua @@ -17,16 +17,13 @@ if not modules then modules = { } end modules ['typo-chr'] = { -- local nuts = nodes.nuts -- local pool = nuts.pool -- --- local tonut = nuts.tonut --- local tonode = nuts.tonode -- local getid = nuts.getid -- local getprev = nuts.getprev --- local getsubtype = nuts.getsubtype -- local getchar = nuts.getchar -- local getfield = nuts.getfield -- -- local remove_node = nuts.remove --- local traverse_by_id = nuts.traverse_id +-- local nextwhatsit = nuts.traversers.whatsit -- -- local signal = pool.userids.signal -- @@ -36,10 +33,8 @@ if not modules then modules = { } end modules ['typo-chr'] = { -- removepunctuation = function(head,n) -- local prev = getprev(n) -- if prev then --- if getid(prev) == glyph_code then --- if is_punctuation[getchar(prev)] then --- head = remove_node(head,prev,true) --- end +-- if getid(prev) == glyph_code and is_punctuation[getchar(prev)] then +-- head = remove_node(head,prev,true) -- end -- end -- return head @@ -51,23 +46,18 @@ if not modules then modules = { } end modules ['typo-chr'] = { -- typesetters.signals = { } -- -- function typesetters.signals.handler(head) --- local h = tonut(head) -- local done = false --- for n in traverse_by_id(whatsit_code,h) do --- if getsubtype(n) == user_code and getfield(n,"user_id") == signal and getfield(n,"type") == 115 then +-- for n, subtype in nextwhatsit, head do +-- if subtype == user_code and getfield(n,"user_id") == signal and getfield(n,"type") == 115 then -- local action = actions[getfield(n,"value")] -- if action then --- h = action(h,n) +-- head = action(h,n) -- end --- h = remove_node(h,n,true) +-- head = remove_node(head,n,true) -- done = true -- end -- end --- if done then --- return tonode(h), true --- else --- return head --- end +-- return head, done -- end -- -- local enabled = false diff --git a/tex/context/base/mkiv/typo-cln.lua b/tex/context/base/mkiv/typo-cln.lua index b7187eaeb..0d5e3eb5e 100644 --- a/tex/context/base/mkiv/typo-cln.lua +++ b/tex/context/base/mkiv/typo-cln.lua @@ -31,7 +31,6 @@ local enableaction = nodes.tasks.enableaction local texsetattribute = tex.setattribute local nuts = nodes.nuts -local tonut = nuts.tonut local getchar = nuts.getchar local getattr = nuts.getattr @@ -39,7 +38,7 @@ local setattr = nuts.setattr local setchar = nuts.setchar -local traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph local unsetvalue = attributes.unsetvalue @@ -58,8 +57,8 @@ local resetter = { -- this will become an entry in char-def -- cleaning comes first. function cleaners.handler(head) - local inline, done = false, false - for n in traverse_id(glyph_code,tonut(head)) do + local inline = false + for n in nextglyph, head do local char = getchar(n) if resetter[char] then inline = false @@ -71,7 +70,6 @@ function cleaners.handler(head) -- some day, not much change that \SS ends up here else setchar(n,upper) - done = true if trace_autocase then report_autocase("") end @@ -80,7 +78,35 @@ function cleaners.handler(head) inline = true end end - return head, done + return head +end + +if LUATEXVERSION >= 1.090 then + + function cleaners.handler(head) + local inline = false + for n, font, char in nextglyph, head do + if resetter[char] then + inline = false + elseif not inline then + local a = getattr(n,a_cleaner) + if a == 1 then -- currently only one cleaner so no need to be fancy + local upper = uccodes[char] + if type(upper) == "table" then + -- some day, not much change that \SS ends up here + else + setchar(n,upper) + if trace_autocase then + report_autocase("") + end + end + end + inline = true + end + end + return head + end + end -- see typo-cap for a more advanced settings handler .. not needed now diff --git a/tex/context/base/mkiv/typo-dha.lua b/tex/context/base/mkiv/typo-dha.lua index af01f0f0d..c12541175 100644 --- a/tex/context/base/mkiv/typo-dha.lua +++ b/tex/context/base/mkiv/typo-dha.lua @@ -46,8 +46,6 @@ local trace_directions = false trackers.register("typesetters.directions.defa local report_directions = logs.reporter("typesetting","text directions") local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev @@ -136,7 +134,7 @@ end local function process(start) - local head = tonut(start) -- we have a global head + local head = start local current = head local autodir = 0 local embedded = 0 @@ -443,7 +441,7 @@ local function process(start) end end - return tonode(head), done + return head end diff --git a/tex/context/base/mkiv/typo-dig.lua b/tex/context/base/mkiv/typo-dig.lua index 61e96c6b6..51ed247fe 100644 --- a/tex/context/base/mkiv/typo-dig.lua +++ b/tex/context/base/mkiv/typo-dig.lua @@ -20,8 +20,6 @@ local report_digits = logs.reporter("typesetting","digits") local nodes, node = nodes, node local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev @@ -111,23 +109,21 @@ actions[1] = function(head,start,attr) attr%100,div(attr,100),char,unic,newwidth-oldwidth) end head, start = nodes.aligned(head,start,start,newwidth,"middle") - return head, start, true + return head, start end end - return head, start, false + return head, start end function digits.handler(head) - head = tonut(head) - local done, current, ok = false, head, false + local current = head while current do if getid(current) == glyph_code then local attr = takeattr(current,a_digits) if attr and attr > 0 then local action = actions[attr%100] -- map back to low number if action then - head, current, ok = action(head,current,attr) - done = done and ok + head, current = action(head,current,attr) elseif trace_digits then report_digits("unknown digit trigger %a",attr) end @@ -137,7 +133,7 @@ function digits.handler(head) current = getnext(current) end end - return tonode(head), done + return head end local m, enabled = 0, false -- a trick to make neighbouring ranges work diff --git a/tex/context/base/mkiv/typo-dir.lua b/tex/context/base/mkiv/typo-dir.lua index 7fbf5f6d3..e405a39e8 100644 --- a/tex/context/base/mkiv/typo-dir.lua +++ b/tex/context/base/mkiv/typo-dir.lua @@ -168,21 +168,21 @@ local stoptiming = statistics.stoptiming function directions.handler(head,_,_,_,direction) local only_one = not getnext(head) if only_one and not one_too then - return head, false + return head end local attr = getattr(head,a_directions) if not attr or attr == 0 then - return head, false + return head end local method = getmethod(attr) local handler = handlers[method] if not handler then - return head, false + return head end starttiming(directions) - local head, done = handler(head,direction,only_one) + head = handler(head,direction,only_one) stoptiming(directions) - return head, done + return head end statistics.register("text directions", function() diff --git a/tex/context/base/mkiv/typo-drp.lua b/tex/context/base/mkiv/typo-drp.lua index 1e142280f..33c5fbdc9 100644 --- a/tex/context/base/mkiv/typo-drp.lua +++ b/tex/context/base/mkiv/typo-drp.lua @@ -28,14 +28,11 @@ local enableaction = tasks.enableaction local disableaction = tasks.disableaction local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev local getchar = nuts.getchar local getid = nuts.getid -local getsubtype = nuts.getsubtype local getattr = nuts.getattr local getwhd = nuts.getwhd @@ -59,8 +56,9 @@ local new_kern = nodepool.kern local insert_before = nuts.insert_before local insert_after = nuts.insert_after local remove_node = nuts.remove -local traverse_id = nuts.traverse_id -local traverse = nuts.traverse + +local nextnode = nuts.traversers.node +local nextglyph = nuts.traversers.glyph local variables = interfaces.variables local v_default = variables.default @@ -139,7 +137,6 @@ interfaces.implement { -- a page so this has a low priority actions[v_default] = function(head,setting) - local done = false local id = getid(head) if id == localpar_code then -- begin of par @@ -173,7 +170,7 @@ actions[v_default] = function(head,setting) -- 1 char | n chars | skip first quote | ignore punct | keep punct -- if getattr(first,a_initial) then - for current in traverse(getnext(first)) do + for current in nextnode, getnext(first) do if getattr(current,a_initial) then last = current else @@ -189,10 +186,10 @@ actions[v_default] = function(head,setting) local next = getnext(first) if not next then -- don't start with a quote or so - return head, false + return head end last = nil - for current in traverse_id(glyph_code,next) do + for current in nextglyph, next do head, first = remove_node(head,first,true) first = current last = first @@ -200,21 +197,21 @@ actions[v_default] = function(head,setting) end if not last then -- no following glyph or so - return head, false + return head end else -- keep quote etc with initial local next = getnext(first) if not next then -- don't start with a quote or so - return head, false + return head end - for current in traverse_id(glyph_code,next) do + for current in nextglyph, next do last = current break end if last == first then - return head, false + return head end end elseif kind == "pf" then @@ -225,7 +222,7 @@ actions[v_default] = function(head,setting) -- maybe also: get all A. B. etc local next = getnext(first) if next then - for current in traverse_id(glyph_code,next) do + for current in nextglyph, next do local char = getchar(current) local kind = category(char) if kind == "po" then @@ -241,7 +238,7 @@ actions[v_default] = function(head,setting) end end else - for current in traverse_id(glyph_code,first) do + for current in nextglyph, first do last = current if length <= 1 then break @@ -265,12 +262,12 @@ actions[v_default] = function(head,setting) end -- apply font --- local g = nodes.copy(tonode(current)) +-- local g = nuts.copy(current) -- g.subtype = 0 -- nodes.handlers.characters(g) -- nodes.handlers.protectglyphs(g) -- setchar(current,g.char) --- nodes.flush_node(g) +-- nuts.flush_node(g) -- can be a helper if ca and ca > 0 then @@ -319,7 +316,7 @@ actions[v_default] = function(head,setting) end -- local hoffset = width + hoffset + distance + (indent and parindent or 0) - for current in traverse_id(glyph_code,first) do + for current in nextglyph, first do setoffsets(current,-hoffset,-voffset) -- no longer - height here if current == last then break @@ -347,14 +344,12 @@ actions[v_default] = function(head,setting) if indent then insert_after(first,first,new_kern(-parindent)) end - done = true end end - return head, done + return head end function initials.handler(head) - head = tonut(head) local start = head local attr = nil while start do @@ -377,9 +372,8 @@ function initials.handler(head) if trace_initials then report_initials("processing initials, alternative %a",alternative) end - local head, done = action(head,settings) - return tonode(head), done + return action(head,settings) end end - return tonode(head), false + return head end diff --git a/tex/context/base/mkiv/typo-dua.lua b/tex/context/base/mkiv/typo-dua.lua index 1e48dfb91..9aaa536c9 100644 --- a/tex/context/base/mkiv/typo-dua.lua +++ b/tex/context/base/mkiv/typo-dua.lua @@ -68,8 +68,6 @@ local directiondata = characters.directions local mirrordata = characters.mirrors local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getid = nuts.getid @@ -730,7 +728,6 @@ end local function apply_to_list(list,size,head,pardir) local index = 1 local current = head - local done = false while current do if index > size then report_directions("fatal error, size mismatch") @@ -760,7 +757,6 @@ local function apply_to_list(list,size,head,pardir) -- setattrlist(d,current) head = insert_node_before(head,current,d) enddir = false - done = true end elseif begindir then if id == localpar_code then @@ -770,7 +766,6 @@ local function apply_to_list(list,size,head,pardir) -- setattrlist(d,current) head, current = insert_node_after(head,current,d) begindir = nil - done = true end end if begindir then @@ -778,7 +773,6 @@ local function apply_to_list(list,size,head,pardir) setprop(d,"directions",true) -- setattrlist(d,current) head = insert_node_before(head,current,d) - done = true end local skip = entry.skip if skip and skip > 0 then @@ -792,24 +786,21 @@ local function apply_to_list(list,size,head,pardir) setprop(d,"directions",true) -- setattrlist(d,current) head, current = insert_node_after(head,current,d) - done = true end if not entry.remove then current = getnext(current) elseif remove_controls then -- X9 head, current = remove_node(head,current,true) - done = true else current = getnext(current) end index = index + 1 end - return head, done + return head end local function process(head) - head = tonut(head) local list, size = build_list(head) local baselevel, pardir, dirfound = get_baselevel(head,list,size) -- we always have an inline dir node in context if not dirfound and trace_details then @@ -825,8 +816,7 @@ local function process(head) report_directions("after : %s",show_list(list,size,"direction")) report_directions("result : %s",show_done(list,size)) end - local head, done = apply_to_list(list,size,head,pardir) - return tonode(head), done + return apply_to_list(list,size,head,pardir) end directions.installhandler(interfaces.variables.one,process) diff --git a/tex/context/base/mkiv/typo-dub.lua b/tex/context/base/mkiv/typo-dub.lua index d0747ae6c..206cfd9ae 100644 --- a/tex/context/base/mkiv/typo-dub.lua +++ b/tex/context/base/mkiv/typo-dub.lua @@ -55,8 +55,6 @@ local mirrordata = characters.mirrors local textclassdata = characters.textclasses local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getid = nuts.getid @@ -930,7 +928,6 @@ end local function apply_to_list(list,size,head,pardir) local index = 1 local current = head - local done = false if trace_list then report_directions("start run") end @@ -973,7 +970,6 @@ local function apply_to_list(list,size,head,pardir) -- setattrlist(d,current) head = insert_node_before(head,current,d) enddir = false - done = true end elseif begindir then if id == localpar_code then @@ -983,7 +979,6 @@ local function apply_to_list(list,size,head,pardir) -- setattrlist(d,current) head, current = insert_node_after(head,current,d) begindir = nil - done = true end end if begindir then @@ -991,7 +986,6 @@ local function apply_to_list(list,size,head,pardir) setprop(d,"directions",true) -- setattrlist(d,current) head = insert_node_before(head,current,d) - done = true end local skip = entry.skip if skip and skip > 0 then @@ -1005,14 +999,12 @@ local function apply_to_list(list,size,head,pardir) setprop(d,"directions",true) -- setattrlist(d,current) head, current = insert_node_after(head,current,d) - done = true end if not entry.remove then current = getnext(current) elseif remove_controls then -- X9 head, current = remove_node(head,current,true) - done = true else current = getnext(current) end @@ -1021,11 +1013,10 @@ local function apply_to_list(list,size,head,pardir) if trace_list then report_directions("stop run") end - return head, done + return head end local function process(head) - head = tonut(head) -- for the moment a whole paragraph property local attr = getattr(head,a_directions) local analyze_fences = getfences(attr) @@ -1045,8 +1036,7 @@ local function process(head) report_directions("after : %s",show_list(list,size,"direction")) report_directions("result : %s",show_done(list,size)) end - local head, done = apply_to_list(list,size,head,pardir) - return tonode(head), done + return apply_to_list(list,size,head,pardir) end directions.installhandler(interfaces.variables.two,process) diff --git a/tex/context/base/mkiv/typo-duc.lua b/tex/context/base/mkiv/typo-duc.lua index 520740190..60191bf83 100644 --- a/tex/context/base/mkiv/typo-duc.lua +++ b/tex/context/base/mkiv/typo-duc.lua @@ -58,8 +58,6 @@ local mirrordata = characters.mirrors local textclassdata = characters.textclasses local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getid = nuts.getid @@ -977,7 +975,6 @@ end local function apply_to_list(list,size,head,pardir) local index = 1 local current = head - local done = false if trace_list then report_directions("start run") end @@ -1020,7 +1017,6 @@ local function apply_to_list(list,size,head,pardir) -- setattrlist(d,current) head = insert_node_before(head,current,d) enddir = false - done = true end elseif begindir then if id == localpar_code then @@ -1030,7 +1026,6 @@ local function apply_to_list(list,size,head,pardir) -- setattrlist(d,current) head, current = insert_node_after(head,current,d) begindir = nil - done = true end end if begindir then @@ -1038,7 +1033,6 @@ local function apply_to_list(list,size,head,pardir) local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end -- setattrlist(d,current) head = insert_node_before(head,current,d) - done = true end local skip = entry.skip if skip and skip > 0 then @@ -1052,14 +1046,12 @@ local function apply_to_list(list,size,head,pardir) local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end -- setattrlist(d,current) head, current = insert_node_after(head,current,d) - done = true end if not entry.remove then current = getnext(current) elseif remove_controls then -- X9 head, current = remove_node(head,current,true) - done = true else current = getnext(current) end @@ -1068,7 +1060,7 @@ local function apply_to_list(list,size,head,pardir) if trace_list then report_directions("stop run") end - return head, done + return head end -- If needed we can optimize for only_one. There is no need to do anything @@ -1078,7 +1070,6 @@ end -- do have a glyph! local function process(head,direction,only_one) - head = tonut(head) -- for the moment a whole paragraph property local attr = getattr(head,a_directions) local analyze_fences = getfences(attr) @@ -1096,8 +1087,7 @@ local function process(head,direction,only_one) report_directions("after : %s",show_list(list,size,"direction")) report_directions("result : %s",show_done(list,size)) end - local head, done = apply_to_list(list,size,head,pardir) - return tonode(head), done + return apply_to_list(list,size,head,pardir) end directions.installhandler(interfaces.variables.three,process) diff --git a/tex/context/base/mkiv/typo-fkr.lua b/tex/context/base/mkiv/typo-fkr.lua index a1135d0f3..7fe848ade 100644 --- a/tex/context/base/mkiv/typo-fkr.lua +++ b/tex/context/base/mkiv/typo-fkr.lua @@ -7,7 +7,6 @@ if not modules then modules = { } end modules ['typo-fkr'] = { } local nuts = nodes.nuts -local tonut = nuts.tonut local getid = nuts.getid local getnext = nuts.getnext local getchar = nuts.getchar @@ -32,13 +31,10 @@ local a_extrakern = attributes.private("extrafontkern") typesetters.fontkerns = { } function typesetters.fontkerns.handler(head) - local kepthead = head - local head = tonut(head) local current = head local lastfont = nil local lastchar = nil local lastdata = nil - local done = false while current do local id = getid(current) if id == glyph_code then @@ -64,7 +60,6 @@ function typesetters.fontkerns.handler(head) end if kern ~= 0 then head, current = insert_before(head,current,new_kern(kern)) - done = true end lastdata = data else @@ -77,7 +72,6 @@ function typesetters.fontkerns.handler(head) local kern = getkernpair(lastdata,lastchar,char) if kern ~= 0 then head, current = insert_before(head,current,new_kern(kern)) - done = true end end lastchar = char @@ -94,7 +88,7 @@ function typesetters.fontkerns.handler(head) end current = getnext(current) end - return kepthead, done + return head end if context then diff --git a/tex/context/base/mkiv/typo-fln.lua b/tex/context/base/mkiv/typo-fln.lua index 4fb82ce44..e105b5a11 100644 --- a/tex/context/base/mkiv/typo-fln.lua +++ b/tex/context/base/mkiv/typo-fln.lua @@ -30,7 +30,6 @@ local context = context local implement = interfaces.implement local nuts = nodes.nuts -local tonut = nuts.tonut local tonode = nuts.tonode local getnext = nuts.getnext @@ -38,7 +37,6 @@ local getprev = nuts.getprev local getboth = nuts.getboth local setboth = nuts.setboth local getid = nuts.getid -local getsubtype = nuts.getsubtype local getwidth = nuts.getwidth local getlist = nuts.getlist local setlist = nuts.setlist @@ -58,7 +56,9 @@ local glue_code = nodecodes.glue local spaceskip_code = nodes.gluecodes.spaceskip -local traverse_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph +local nextdisc = nuts.traversers.disc + local flush_node_list = nuts.flush_list local flush_node = nuts.flush_node local copy_node_list = nuts.copy_list @@ -136,7 +136,7 @@ actions[v_line] = function(head,setting) local linebreaks = { } local function set(head) - for g in traverse_id(glyph_code,head) do + for g in nextglyph, head do if dynamic > 0 then setattr(g,0,dynamic) end @@ -146,7 +146,7 @@ actions[v_line] = function(head,setting) set(temp) - for g in traverse_id(disc_code,temp) do + for g in nextdisc, temp do local pre, post, replace = getdisc(g) if pre then set(pre) @@ -173,14 +173,12 @@ actions[v_line] = function(head,setting) local function list_dimensions(list,start) local temp = copy_node_list(list,start) - temp = tonode(temp) temp = nodes.handlers.characters(temp) temp = nodes.injections.handler(temp) -- temp = typesetters.fontkerns.handler(temp) -- maybe when enabled - -- nodes.handlers.protectglyphs(temp) -- not needed as we discard + -- nodes.handlers.protectglyphs(temp) -- not needed as we discard -- temp = typesetters.spacings.handler(temp) -- maybe when enabled -- temp = typesetters.kerns.handler(temp) -- maybe when enabled - temp = tonut(temp) temp = hpack_node_list(temp) local width = getwidth(temp) flush_node_list(temp) @@ -264,7 +262,7 @@ actions[v_line] = function(head,setting) if linebreak == n then local p, n = getboth(start) if pre then - for current in traverse_id(glyph_code,pre) do + for current in nextglyph, pre do update(current) end setlink(pretail,n) @@ -284,7 +282,7 @@ actions[v_line] = function(head,setting) else local p, n = getboth(start) if replace then - for current in traverse_id(glyph_code,replace) do + for current in nextglyph, replace do update(current) end setlink(replacetail,n) @@ -314,7 +312,7 @@ actions[v_line] = function(head,setting) end end - return head, true + return head end actions[v_word] = function(head,setting) @@ -359,13 +357,12 @@ actions[v_word] = function(head,setting) end start = getnext(start) end - return head, true + return head end actions[v_default] = actions[v_line] function firstlines.handler(head) - head = tonut(head) local start = head local attr = nil while start do @@ -388,11 +385,10 @@ function firstlines.handler(head) if trace_firstlines then report_firstlines("processing firstlines, alternative %a",alternative) end - local head, done = action(head,settings) - return tonode(head), done + return action(head,settings) end end - return tonode(head), false + return head end -- goodie @@ -401,7 +397,7 @@ local function applytofirstcharacter(box,what) local tbox = getbox(box) -- assumes hlist local list = getlist(tbox) local done = nil - for n in traverse_id(glyph_code,list) do + for n in nextglyph, list do list = remove_node(list,n) done = n break diff --git a/tex/context/base/mkiv/typo-itc.lua b/tex/context/base/mkiv/typo-itc.lua index 328bf1406..b85a2847e 100644 --- a/tex/context/base/mkiv/typo-itc.lua +++ b/tex/context/base/mkiv/typo-itc.lua @@ -29,9 +29,6 @@ local enableaction = nodes.tasks.enableaction local nuts = nodes.nuts local nodepool = nuts.pool -local tonode = nuts.tonode -local tonut = nuts.tonut - local getprev = nuts.getprev local getnext = nuts.getnext local getid = nuts.getid @@ -177,7 +174,7 @@ local textokay = false local enablemath = false local enabletext = false -local function domath(head,current, done) +local function domath(head,current) current = end_of_math(current) local next = getnext(current) if next then @@ -212,7 +209,6 @@ local function domath(head,current, done) report_italics("%s italic between math %C and punctuation %C","removing",i,c,char) end setkern(kern,0) -- or maybe a small value or half the ic - done = true end elseif i == 0 then local d = chardata[f][c] @@ -226,7 +222,6 @@ local function domath(head,current, done) if trace_italics then report_italics("%s italic %p between math %C and punctuation %C","setting",i,c,char) end - done = true end elseif trace_italics then report_italics("%s italic %p between math %C and punctuation %C","keeping",k,c,char) @@ -251,34 +246,31 @@ local function domath(head,current, done) report_italics("%s italic %p between math %C and non punctuation %C","adding",a,getchar(glyph),char) end insert_node_after(head,glyph,correction_kern(a,glyph)) - done = true end end end end end end - return current, done + return current end local function mathhandler(head) - local nuthead = tonut(head) - local current = nuthead - local done = false + local current = head while current do if getid(current) == math_code then - current, done = domath(nuthead,current,done) + current = domath(head,current) end current = getnext(current) end - return head, done + return head end local function texthandler(head) local prev = nil local prevchar = nil - local prevhead = tonut(head) + local prevhead = head local previtalic = 0 local previnserted = nil @@ -300,7 +292,6 @@ local function texthandler(head) local replaceinserted = nil local current = prevhead - local done = false local lastfont = nil local lastattr = nil @@ -313,7 +304,6 @@ local function texthandler(head) if previtalic ~= 0 then if okay(data,current,font,prevchar,previtalic,char,"glyph") then insert_node_after(prevhead,prev,correction_kern(previtalic,current)) - done = true end elseif previnserted and data then if trace_italics then @@ -325,7 +315,6 @@ local function texthandler(head) if replaceitalic ~= 0 then if okay(data,replace,font,replacechar,replaceitalic,char,"replace") then insert_node_after(replacehead,replace,correction_kern(replaceitalic,current)) - done = true end replaceitalic = 0 elseif replaceinserted and data then @@ -338,7 +327,6 @@ local function texthandler(head) if postitalic ~= 0 then if okay(data,post,font,postchar,postitalic,char,"post") then insert_node_after(posthead,post,correction_kern(postitalic,current)) - done = true end postitalic = 0 elseif postinserted and data then @@ -479,7 +467,6 @@ local function texthandler(head) end previnserted = correction_glue(previtalic,current) -- maybe just add ? else problem with penalties previtalic = 0 - done = true insert_node_after(prevhead,prev,previnserted) else if replaceitalic ~= 0 then @@ -488,7 +475,6 @@ local function texthandler(head) end replaceinserted = correction_kern(replaceitalic,current) -- needs to be a kern replaceitalic = 0 - done = true insert_node_after(replacehead,replace,replaceinserted) end if postitalic ~= 0 then @@ -497,7 +483,6 @@ local function texthandler(head) end postinserted = correction_kern(postitalic,current) -- needs to be a kern postitalic = 0 - done = true insert_node_after(posthead,post,postinserted) end end @@ -510,7 +495,7 @@ local function texthandler(head) postinserted = nil postitalic = 0 if mathokay then - current, done = domath(head,current,done) + current = domath(head,current) else current = end_of_math(current) end @@ -526,7 +511,6 @@ local function texthandler(head) replaceitalic = 0 postinserted = nil postitalic = 0 - done = true else if replaceitalic ~= 0 then if trace_italics then @@ -539,7 +523,6 @@ local function texthandler(head) replaceitalic = 0 postinserted = nil postitalic = 0 - done = true end if postitalic ~= 0 then if trace_italics then @@ -552,7 +535,6 @@ local function texthandler(head) replaceitalic = 0 postinserted = nil postitalic = 0 - done = true end end end @@ -564,25 +546,22 @@ local function texthandler(head) report_italics("inserting %p between %s italic %C and end of list",previtalic,"glyph",prevchar) end insert_node_after(prevhead,prev,correction_kern(previtalic,current)) - done = true else if replaceitalic ~= 0 then if trace_italics then report_italics("inserting %p between %s italic %C and end of list",replaceitalic,"replace",replacechar) end insert_node_after(replacehead,replace,correction_kern(replaceitalic,current)) - done = true end if postitalic ~= 0 then if trace_italics then report_italics("inserting %p between %s italic %C and end of list",postitalic,"post",postchar) end insert_node_after(posthead,post,correction_kern(postitalic,current)) - done = true end end end - return head, done + return head end function italics.handler(head) diff --git a/tex/context/base/mkiv/typo-krn.lua b/tex/context/base/mkiv/typo-krn.lua index 71d9736a4..5e4792f62 100644 --- a/tex/context/base/mkiv/typo-krn.lua +++ b/tex/context/base/mkiv/typo-krn.lua @@ -21,9 +21,6 @@ local enableaction = nodes.tasks.enableaction local nuts = nodes.nuts local nodepool = nuts.pool -local tonode = nuts.tonode -local tonut = nuts.tonut - -- check what is used local find_node_tail = nuts.tail @@ -364,9 +361,7 @@ local function closest_bound(b,get) end function kerns.handler(head) - local head = tonut(head) local start = head - local done = false local lastfont = nil local keepligature = kerns.keepligature local keeptogether = kerns.keeptogether @@ -418,7 +413,6 @@ function kerns.handler(head) if inject then -- not yet ok, as injected kerns can be overlays (from node-inj.lua) setkern(prev,getkern(prev) + quaddata[font]*krn,userkern_code) - done = true end end elseif previd == glyph_code then @@ -430,11 +424,9 @@ function kerns.handler(head) local kerns = data and data.kerns local kern = (kerns and kerns[char] or 0) + quaddata[font]*krn insert_node_before(head,start,kern_injector(fillup,kern)) - done = true end else insert_node_before(head,start,kern_injector(fillup,quaddata[font]*krn)) - done = true end end prev = start @@ -514,7 +506,6 @@ function kerns.handler(head) end if indeed then setdisc(start,pre,post,replace) - done = true end bound = false elseif id == kern_code then @@ -536,7 +527,6 @@ function kerns.handler(head) -- shrink_order = 1 ? end setglue(start,w,stretch,shrink,stretch_order,shrink_order) - done = true end end bound = false @@ -547,12 +537,10 @@ function kerns.handler(head) local b, f = closest_bound(start,getprev) if b then insert_node_before(head,start,kern_injector(fillup,quaddata[f]*krn)) - done = true end local b, f = closest_bound(start,getnext) if b then insert_node_after(head,start,kern_injector(fillup,quaddata[f]*krn)) - done = true end end bound = false @@ -573,7 +561,7 @@ function kerns.handler(head) start = getnext(start) end end - return tonode(head), done + return head end local enabled = false diff --git a/tex/context/base/mkiv/typo-lin.lua b/tex/context/base/mkiv/typo-lin.lua index ebf748a82..9d7ee359e 100644 --- a/tex/context/base/mkiv/typo-lin.lua +++ b/tex/context/base/mkiv/typo-lin.lua @@ -73,7 +73,7 @@ local parfillskip_code = gluecodes.parfillskip local tonut = nodes.tonut local tonode = nodes.tonode -local traverse_id = nuts.traverse_id +local nexthlist = nuts.traversers.hlist local insert_before = nuts.insert_before local insert_after = nuts.insert_after local find_tail = nuts.tail @@ -252,7 +252,7 @@ function paragraphs.normalize(head,islocal) if l_width ~= 0 or l_stretch ~= 0 or l_shrink ~= 0 then local last = nil -- a nut local done = false - for line in traverse_id(hlist_code,tonut(head)) do + for line in nexthlist, head do -- LUATEXVERSION >= 1.090 if getsubtype(line) == line_code and not getprop(line,"line") then if done then last = line @@ -280,7 +280,7 @@ function paragraphs.normalize(head,islocal) end end -- normalizer - for line in traverse_id(hlist_code,tonut(head)) do + for line in nexthlist, head do -- LUATEXVERSION >= 1.090 if getsubtype(line) == line_code and not getprop(line,"line") then normalize(line) if done then diff --git a/tex/context/base/mkiv/typo-mar.lua b/tex/context/base/mkiv/typo-mar.lua index bc9c408c1..813993a99 100644 --- a/tex/context/base/mkiv/typo-mar.lua +++ b/tex/context/base/mkiv/typo-mar.lua @@ -62,7 +62,6 @@ local nuts = nodes.nuts local nodepool = nuts.pool local tonode = nuts.tonode -local tonut = nuts.tonut local hpack_nodes = nuts.hpack local traverse_id = nuts.traverse_id @@ -113,7 +112,7 @@ local texgetcount = tex.getcount local texget = tex.get local isleftpage = layouts.status.isleftpage -local registertogether = builders.paragraphs.registertogether -- tonode +local registertogether = builders.paragraphs.registertogether local paragraphs = typesetters.paragraphs local addtoline = paragraphs.addtoline @@ -812,9 +811,8 @@ local function handler(scope,head,group) if trace_margindata then report_margindata("flushing stage one, stored %s, scope %s, delayed %s, group %a",nofstored,scope,nofdelayed,group) end - head = tonut(head) local current = head - local done = false + local done = false -- for tracing only while current do local id = getid(current) if (id == vlist_code or id == hlist_code) and getprop(current,"margindata") == nil then @@ -839,11 +837,9 @@ local function handler(scope,head,group) report_margindata("flushing stage one, nothing done, %s left",nofstored) end end -resetstacked() - return tonode(head), done - else - return head, false + resetstacked() end + return head end local trialtypesetting = context.trialtypesetting @@ -854,7 +850,7 @@ local trialtypesetting = context.trialtypesetting function margins.localhandler(head,group) -- sometimes group is "" which is weird if trialtypesetting() then - return head, false + return head end local inhibit = conditionals.inhibitmargindata @@ -862,15 +858,15 @@ function margins.localhandler(head,group) -- sometimes group is "" which is weir if trace_margingroup then report_margindata("ignored 3, group %a, stored %s, inhibit %a",group,nofstored,inhibit) end - return head, false - elseif nofstored > 0 then + return head + end + if nofstored > 0 then return handler(v_local,head,group) - else - if trace_margingroup then - report_margindata("ignored 4, group %a, stored %s, inhibit %a",group,nofstored,inhibit) - end - return head, false end + if trace_margingroup then + report_margindata("ignored 4, group %a, stored %s, inhibit %a",group,nofstored,inhibit) + end + return head end function margins.globalhandler(head,group) -- check group @@ -884,7 +880,7 @@ function margins.globalhandler(head,group) -- check group if trace_margingroup then report_margindata("ignored 1, group %a, stored %s, inhibit %a",group,nofstored,inhibit) end - return head, false + return head elseif group == "hmode_par" then return handler(v_global,head,group) elseif group == "vmode_par" then -- experiment (for alignments) @@ -899,22 +895,20 @@ function margins.globalhandler(head,group) -- check group if trace_margingroup then report_margindata("ignored 2, group %a, stored %s, inhibit %a",group,nofstored,inhibit) end - return head, false + return head end end local function finalhandler(head) if nofdelayed > 0 then local current = head - local done = false - while current and nofdelayed > 0 do + while current and nofdelayed > 0 do -- traverse_list local id = getid(current) if id == hlist_code then -- only lines? local a = getprop(current,"margindata") if not a then finalhandler(getlist(current)) elseif realigned(current,a) then - done = true if nofdelayed == 0 then return head, true end @@ -924,10 +918,8 @@ local function finalhandler(head) end current = getnext(current) end - return head, done - else - return head, false end + return head end function margins.finalhandler(head) @@ -935,16 +927,12 @@ function margins.finalhandler(head) if trace_margindata then report_margindata("flushing stage two, instore: %s, delayed: %s",nofstored,nofdelayed) end - head = tonut(head) - local head, done = finalhandler(head) --- resetstacked(true) -resetstacked(nofdelayed==0) - head = tonode(head) - return head, done + head = finalhandler(head) + resetstacked(nofdelayed==0) else resetstacked() - return head, false end + return head end -- Somehow the vbox builder (in combinations) gets pretty confused and decides to diff --git a/tex/context/base/mkiv/typo-pag.lua b/tex/context/base/mkiv/typo-pag.lua index b5759a097..05513e20c 100644 --- a/tex/context/base/mkiv/typo-pag.lua +++ b/tex/context/base/mkiv/typo-pag.lua @@ -26,7 +26,6 @@ local unsetvalue = attributes.unsetvalue local a_keeptogether = attributes.private("keeptogether") local nuts = nodes.nuts -local tonut = nuts.tonut local getnext = nuts.getnext local getprev = nuts.getprev @@ -187,8 +186,8 @@ end -- also look at first non glue/kern node e.g for a dropped caps function parbuilders.keeptogether(head) - local done = false - local current = tonut(head) + local done = false + local current = head while current do if getid(current) == hlist_code then local a = takeattr(current,a_keeptogether) diff --git a/tex/context/base/mkiv/typo-pnc.lua b/tex/context/base/mkiv/typo-pnc.lua index 1ed8d9940..1ffff991f 100644 --- a/tex/context/base/mkiv/typo-pnc.lua +++ b/tex/context/base/mkiv/typo-pnc.lua @@ -9,7 +9,6 @@ if not modules then modules = { } end modules ['typo-pnc'] = { local nodes = nodes local fonts = fonts -local prependaction = nodes.tasks.prependaction local enableaction = nodes.tasks.enableaction local nuts = nodes.nuts @@ -23,7 +22,8 @@ local spaceskip_code = gluecodes.spaceskip local new_kern = nuts.pool.kern local insert_after = nuts.insert_after -local traverse_id = nuts.traverse_id + +local nextglyph = nuts.traversers.glyph local getchar = nuts.getchar local getfont = nuts.getfont @@ -68,9 +68,7 @@ local mapping = periodkerns.mapping local factors = periodkerns.factors function periodkerns.handler(head) - local done = false - local hnut = tonut(head) - for current in traverse_id(glyph_code,tonut(hnut)) do + for current in nextglyph, head do if getchar(current) == period then local a = getattr(current,a_periodkern) if a then @@ -91,11 +89,10 @@ function periodkerns.handler(head) if factor ~= 0 then fontspace = parameters[getfont(current)].space -- can be sped up inserted = factor * fontspace - insert_after(hnut,current,new_kern(inserted)) + insert_after(head,current,new_kern(inserted)) if trace then report("inserting space at %C . [%p] %C .",pchar,inserted,nchar) end - done = true end local next3 = getnext(next2) if next3 and getid(next3) == glue_code and getsubtype(next3) == spaceskip_code then @@ -115,7 +112,6 @@ function periodkerns.handler(head) end end setwidth(next3,space) - done = true else if trace then if inserted then @@ -136,7 +132,80 @@ function periodkerns.handler(head) end end end - return head, done + return head +end + +if LUATEXVERSION >= 1.090 then + + function periodkerns.handler(head) + for current, font, char in nextglyph, head do + if char == period then + local a = getattr(current,a_periodkern) + if a then + local factor = mapping[a] + if factor then + local prev, next = getboth(current) + if prev and next and getid(prev) == glyph_code and getid(next) == glyph_code then + local pchar = getchar(prev) + local pcode = categories[getchar(prev)] + if pcode == "lu" or pcode == "ll" then + local nchar = getchar(next) + local ncode = categories[getchar(next)] + if ncode == "lu" or ncode == "ll" then + local next2 = getnext(next) + if next2 and getid(next2) == glyph_code and getchar(next2) == period then + -- A.B. + local fontspace, inserted + if factor ~= 0 then + fontspace = parameters[getfont(current)].space -- can be sped up + inserted = factor * fontspace + insert_after(head,current,new_kern(inserted)) + if trace then + report("inserting space at %C . [%p] %C .",pchar,inserted,nchar) + end + end + local next3 = getnext(next2) + if next3 and getid(next3) == glue_code and getsubtype(next3) == spaceskip_code then + local width = getwidth(next3) + local space = fontspace or parameters[getfont(current)].space -- can be sped up + if width > space then -- space + extraspace + local next4 = getnext(next3) + if next4 and getid(next4) == glyph_code then + local fchar = getchar(next4) + if categories[fchar] ~= "lu" then + -- A.B.<glue>X + if trace then + if inserted then + report("reverting space at %C . [%p] %C . [%p->%p] %C",pchar,inserted,nchar,width,space,fchar) + else + report("reverting space at %C . %C . [%p->%p] %C",pchar,nchar,width,space,fchar) + end + end + setwidth(next3,space) + else + if trace then + if inserted then + report("keeping space at %C . [%p] %C . [%p] %C",pchar,inserted,nchar,width,fchar) + else + report("keeping space at %C . %C . [%p] %C",pchar,nchar,width,fchar) + end + end + end + end + end + end + end + end + end + end + end + end + end + end + return head + end + + end local enabled = false @@ -144,7 +213,6 @@ local enabled = false function periodkerns.set(factor) factor = tonumber(factor) or 0 if not enabled then - prependaction("processors","normalizers","typesetters.periodkerns.handler") enableaction("processors","typesetters.periodkerns.handler") enabled = true end diff --git a/tex/context/base/mkiv/typo-rep.lua b/tex/context/base/mkiv/typo-rep.lua index b6aae0cae..d29eb17b8 100644 --- a/tex/context/base/mkiv/typo-rep.lua +++ b/tex/context/base/mkiv/typo-rep.lua @@ -21,8 +21,6 @@ local nodes = nodes local enableaction = nodes.tasks.enableaction local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getchar = nuts.getchar @@ -81,9 +79,8 @@ local function process(what,head,current,char) return head, current end -function nodes.handlers.stripping(head) - head = tonut(head) - local current, done = head, false +function nodes.handlers.stripping(head) -- use loop + local current = head while current do local char, id = isglyph(current) if char then @@ -93,7 +90,6 @@ function nodes.handlers.stripping(head) local what = glyphs[char] if what then head, current = process(what,head,current,char) - done = true else -- handling of spacing etc has to be done elsewhere current = getnext(current) end @@ -104,7 +100,7 @@ function nodes.handlers.stripping(head) current = getnext(current) end end - return tonode(head), done + return head end local enabled = false diff --git a/tex/context/base/mkiv/typo-rub.lua b/tex/context/base/mkiv/typo-rub.lua index 8c41a5611..f1f3f0403 100644 --- a/tex/context/base/mkiv/typo-rub.lua +++ b/tex/context/base/mkiv/typo-rub.lua @@ -33,8 +33,6 @@ local v_auto = variables.auto local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode local getid = nuts.getid local getsubtype = nuts.getsubtype local getattr = nuts.getattr @@ -53,7 +51,9 @@ local setwidth = nuts.setwidth local hpack = nuts.hpack local insert_after = nuts.insert_after local takebox = nuts.takebox -local traverse_id = nuts.traverse_id + +local nexthlist = nuts.traversers.hlist +local nextvlist = nuts.traversers.vlist local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph @@ -194,7 +194,6 @@ do end function rubies.check(head) - local head = tonut(head) local current = head local start = nil local stop = nil @@ -260,7 +259,7 @@ function rubies.check(head) if found then flush("flush 5") end - return tonode(head), true + return head, true end local attach @@ -371,20 +370,17 @@ local function whatever(current) end end -attach = function(head) - for current in traverse_id(hlist_code,head) do +attach = function(head) -- traverse_list + for current in nexthlist, head do whatever(current) end - for current in traverse_id(vlist_code,head) do + for current in nextvlist, head do whatever(current) end - return head, true + return head end -function rubies.attach(head) - local h, d = attach(tonut(head)) - return tonode(h), d -end +rubies.attach = attach -- for now there is no need to be compact diff --git a/tex/context/base/mkiv/typo-spa.lua b/tex/context/base/mkiv/typo-spa.lua index bda139719..c49897f87 100644 --- a/tex/context/base/mkiv/typo-spa.lua +++ b/tex/context/base/mkiv/typo-spa.lua @@ -23,8 +23,6 @@ local unsetvalue = attributes.unsetvalue local v_reset = interfaces.variables.reset local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev @@ -73,8 +71,6 @@ end -- todo cache lastattr function spacings.handler(head) - head = tonut(head) - local done = false local start = head -- head is always begin of par (whatsit), so we have at least two prev nodes -- penalty followed by glue @@ -122,7 +118,6 @@ function spacings.handler(head) end insert_node_before(head,start,new_penalty(10000)) insert_node_before(head,start,new_glue(left*quad)) - done = true end end local next = getnext(start) @@ -159,7 +154,6 @@ function spacings.handler(head) end insert_node_after(head,start,new_glue(right*quad)) insert_node_after(head,start,new_penalty(10000)) - done = true end end end @@ -172,7 +166,7 @@ function spacings.handler(head) start = getnext(start) end end - return tonode(head), done + return head end local enabled = false diff --git a/tex/context/base/mkiv/typo-sus.lua b/tex/context/base/mkiv/typo-sus.lua index 2d3037bdc..6c02b9291 100644 --- a/tex/context/base/mkiv/typo-sus.lua +++ b/tex/context/base/mkiv/typo-sus.lua @@ -40,8 +40,6 @@ local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode local getid = nuts.getid local getprev = nuts.getprev @@ -164,7 +162,6 @@ local colors = { local found = 0 function typesetters.marksuspects(head) - local head = tonut(head) local current = head local lastdone = nil while current do @@ -254,7 +251,7 @@ function typesetters.marksuspects(head) current = getnext(current) end end - return tonode(head), found > 0 + return head end local function showsuspects(head) @@ -289,9 +286,9 @@ end function typesetters.showsuspects(head) if found > 0 then - return tonode(showsuspects(tonut(head))), true + return showsuspects(head) else - return head, false + return head end end diff --git a/tex/context/base/mkiv/typo-tal.lua b/tex/context/base/mkiv/typo-tal.lua index 870d006cc..413c249fa 100644 --- a/tex/context/base/mkiv/typo-tal.lua +++ b/tex/context/base/mkiv/typo-tal.lua @@ -34,7 +34,6 @@ local v_number = variables.number local nuts = nodes.nuts local tonut = nuts.tonut -local tonode = nuts.tonode local getnext = nuts.getnext local getprev = nuts.getprev @@ -50,7 +49,7 @@ local setchar = nuts.setchar local insert_node_before = nuts.insert_before local insert_node_after = nuts.insert_after -local traverse_list_by_id = nuts.traverse_id +local nextglyph = nuts.traversers.glyph local list_dimensions = nuts.dimensions local first_glyph = nuts.first_glyph @@ -171,23 +170,22 @@ local function traced_kern(w) return tracedrule(w,nil,nil,"darkgray") end -function characteralign.handler(originalhead,where) +function characteralign.handler(head,where) if not datasets then - return originalhead, false + return head end - local head = tonut(originalhead) -- local first = first_glyph(head) -- we could do that once local first - for n in traverse_list_by_id(glyph_code,head) do + for n in nextglyph, head do first = n break end if not first then - return originalhead, false + return head end local a = getattr(first,a_characteralign) if not a or a == 0 then - return originalhead, false + return head end local column = div(a,0xFFFF) local row = a % 0xFFFF @@ -336,7 +334,7 @@ function characteralign.handler(originalhead,where) before = before, after = after, } - return tonode(head), true + return head, true end if not dataset.collected then -- print("[maxbefore] [maxafter]") @@ -404,5 +402,5 @@ function characteralign.handler(originalhead,where) insert_node_after(head,c,new_kern(maxafter)) end end - return tonode(head), true + return head end diff --git a/tex/context/base/mkiv/typo-wrp.lua b/tex/context/base/mkiv/typo-wrp.lua index 07e34cd6c..13bb5a0cc 100644 --- a/tex/context/base/mkiv/typo-wrp.lua +++ b/tex/context/base/mkiv/typo-wrp.lua @@ -16,8 +16,6 @@ local parfill_skip_code = nodes.gluecodes.parfillskip local user_penalty_code = nodes.penaltycodes.userpenalty local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode local find_node_tail = nuts.tail local getprev = nuts.getprev @@ -51,22 +49,20 @@ local function remove_dangling_crlf(head,tail) report("removing a probably unwanted end-of-par break in line %s (guess)",tex.inputlineno) end remove(head,tail,true) - return head, tail, true + return head, tail end end end end - return head, tail, false + return head, tail end function wrappers.handler(head) - local head = tonut(head) if head then local tail = find_node_tail(head) - local done = false - head, tail, done = remove_dangling_crlf(head,tail) -- will be action chain + head, tail = remove_dangling_crlf(head,tail) -- will be action chain end - return head, true + return head end interfaces.implement { diff --git a/tex/context/base/mkiv/util-seq.lua b/tex/context/base/mkiv/util-seq.lua index ec6ed2ceb..08f762b6a 100644 --- a/tex/context/base/mkiv/util-seq.lua +++ b/tex/context/base/mkiv/util-seq.lua @@ -27,6 +27,15 @@ local allocate = utilities.storage.allocate local formatters = string.formatters local replacer = utilities.templates.replacer +local trace_used = false +local trace_detail = false +local report = logs.reporter("sequencer") +local usedcount = 0 +local usednames = { } + +trackers.register("sequencers.used", function(v) trace_used = true end) +trackers.register("sequencers.detail",function(v) trace_detail = true end) + local sequencers = { } utilities.sequencers = sequencers @@ -38,6 +47,8 @@ local replacevalue = tables.replacevalue local insertaftervalue = tables.insertaftervalue local insertbeforevalue = tables.insertbeforevalue +local usedsequences = { } + local function validaction(action) if type(action) == "string" then local g = _G @@ -211,9 +222,19 @@ local function localize(str) end local function construct(t) - local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip - local arguments, returnvalues, results = t.arguments or "...", t.returnvalues, t.results - local variables, calls, n = { }, { }, 0 + local list = t.list + local order = t.order + local kind = t.kind + local gskip = t.gskip + local askip = t.askip + local name = t.name or "?" + local arguments = t.arguments or "..." + local returnvalues = t.returnvalues + local results = t.results + local variables = { } + local calls = { } + local n = 0 + usedcount = usedcount + 1 for i=1,#order do local group = order[i] if not gskip[group] then @@ -221,6 +242,11 @@ local function construct(t) for i=1,#actions do local action = actions[i] if not askip[action] then + if trace_used then + local action = tostring(action) + report("%02i: category %a, group %a, action %a",usedcount,name,group,action) + usednames[action] = true + end local localized if type(action) == "function" then local name = localize(tostring(action)) @@ -261,17 +287,16 @@ end sequencers.tostring = construct sequencers.localize = localize -compile = function(t,compiler,n) -- already referred to in sequencers.new +compile = function(t,compiler,...) -- already referred to in sequencers.new local compiled if not t or type(t) == "string" then - -- weird ... t.compiled = t .. so return false end if compiler then - compiled = compiler(t,n) + compiled = compiler(t,...) t.compiled = compiled else - compiled = construct(t,n) + compiled = construct(t,...) end local runner if compiled == "" then @@ -285,114 +310,46 @@ end sequencers.compile = compile --- we used to deal with tail as well but now that the lists are always --- double linked and the kernel function no longer expect tail as --- argument we stick to head and done (done can probably also go --- as luatex deals with return values efficiently now .. in the --- past there was some copying involved, but no longer) - --- todo: use sequencer (can have arguments and returnvalues etc now) - -local template_yes_state = [[ -%s -return function(head%s) - local ok, done = false, false -%s - return head, done -end]] - -local template_yes_nostate = [[ -%s -return function(head%s) -%s - return head, true -end]] - -local template_nop = [[ -return function() - return false, false -end]] - -local function nodeprocessor(t,nofarguments) -- todo: handle 'kind' in plug into tostring - local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip - local nostate = t.nostate - local vars, calls, args, n = { }, { }, nil, 0 - if nofarguments == 0 then - args = "" - elseif nofarguments == 1 then - args = ",one" - elseif nofarguments == 2 then - args = ",one,two" - elseif nofarguments == 3 then -- from here on probably slower than ... - args = ",one,two,three" - elseif nofarguments == 4 then - args = ",one,two,three,four" - elseif nofarguments == 5 then - args = ",one,two,three,four,five" - else - args = ",..." - end - for i=1,#order do - local group = order[i] - if not gskip[group] then - local actions = list[group] - for i=1,#actions do - local action = actions[i] - if not askip[action] then - local localized = localize(action) - n = n + 1 - vars[n] = formatters["local %s = %s"](localized,action) - -- only difference with tostring is kind and rets (why no return) - if nostate then - if kind[action] == "nohead" then - calls[n] = formatters[" %s(head%s)"](localized,args) - else - calls[n] = formatters[" head = %s(head%s)"](localized,args) - end - else - if kind[action] == "nohead" then - calls[n] = formatters[" ok = %s(head%s) if ok then done = true end"](localized,args) - else - calls[n] = formatters[" head, ok = %s(head%s) if ok then done = true end"](localized,args) - end - end - end - end - end - end - local processor = #calls > 0 and formatters[nostate and template_yes_nostate or template_yes_state](concat(vars,"\n"),args,concat(calls,"\n")) or template_nop - -- print(processor) - return processor -end - function sequencers.nodeprocessor(t,nofarguments) - local kind = type(nofarguments) - if kind == "number" then - return nodeprocessor(t,nofarguments) - elseif kind ~= "table" then - return - end -- local templates = nofarguments - local process = templates.process - local step = templates.step -- - if not process or not step then + if type(templates) ~= "table" then + return "" + end + -- + local replacers = { } + for k, v in next, templates do + replacers[k] = replacer(v) + end + -- + local construct = replacers.process + local step = replacers.step + if not construct or not step then return "" end -- - local construct = replacer(process) - local newaction = replacer(step) local calls = { } local aliases = { } - local n = 0 + local ncalls = 0 + local naliases = 0 + local f_alias = formatters["local %s = %s"] -- local list = t.list local order = t.order local kind = t.kind local gskip = t.gskip local askip = t.askip + local name = t.name or "?" + local steps = 0 + usedcount = usedcount + 1 -- + if trace_detail then + naliases = naliases + 1 + aliases[naliases] = formatters["local report = logs.reporter('sequencer',%q)"](name) + ncalls = ncalls + 1 + calls[ncalls] = [[report("start")]] + end for i=1,#order do local group = order[i] if not gskip[group] then @@ -400,20 +357,48 @@ function sequencers.nodeprocessor(t,nofarguments) for i=1,#actions do local action = actions[i] if not askip[action] then + steps = steps + 1 + if trace_used or trace_detail then + local action = tostring(action) + report("%02i: category %a, group %a, action %a",usedcount,name,group,action) + usednames[action] = true + end + if trace_detail then + ncalls = ncalls + 1 + calls[ncalls] = formatters[ [[report(" step %a, action %a")]] ](steps,tostring(action)) + end local localized = localize(action) - n = n + 1 - aliases[n] = formatters["local %s = %s"](localized,action) - calls[n] = newaction { action = localized } + local onestep = replacers[kind[action]] or step + naliases = naliases + 1 + ncalls = ncalls + 1 + aliases[naliases] = f_alias(localized,action) + calls [ncalls] = onestep { action = localized } end end end end - if n == 0 then - return templates.default or construct { } + local processor + if steps == 0 then + processor = templates.default or construct { } + else + if trace_detail then + ncalls = ncalls + 1 + calls[ncalls] = [[report("stop")]] + end + processor = construct { + localize = concat(aliases,"\n"), + actions = concat(calls,"\n"), + } end - local processor = construct { - localize = concat(aliases,"\n"), - actions = concat(calls,"\n"), - } + + -- processor = "print('running : " .. (t.name or "?") .. "')\n" .. processor + -- print(processor) + return processor end + +statistics.register("used sequences",function() + if next(usednames) then + return table.concat(table.sortedkeys(usednames)," ") + end +end) diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua index 56c5b011c..42f126687 100644 --- a/tex/context/base/mkiv/util-str.lua +++ b/tex/context/base/mkiv/util-str.lua @@ -869,7 +869,12 @@ local format_L = function() return format("(a%s and 'TRUE' or 'FALSE')",n) end -local format_N = function() -- strips leading zeros +local format_n = function() -- strips leading and trailing zeros and removes .0 + n = n + 1 + return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n) +end + +local format_N = function() -- strips leading and trailing zeros (also accepst string) n = n + 1 return format("tostring(tonumber(a%s) or a%s)",n,n) end @@ -999,6 +1004,7 @@ local builder = Cs { "start", + V("C") + V("S") -- new + V("Q") -- new + + V("n") -- new + V("N") -- new + V("k") -- new -- @@ -1042,7 +1048,8 @@ local builder = Cs { "start", -- ["S"] = (prefix_any * P("S")) / format_S, -- %S => %s (tostring) ["Q"] = (prefix_any * P("Q")) / format_Q, -- %Q => %q (tostring) - ["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading zeros) + ["n"] = (prefix_any * P("n")) / format_n, -- %n => tonumber (strips leading and trailing zeros, as well as .0, expects number) + ["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading and trailing zeros, also takes string) ["k"] = (prefix_sub * P("k")) / format_k, -- %k => like f but with n.m ["c"] = (prefix_any * P("c")) / format_c, -- %c => utf character (extension to regular) ["C"] = (prefix_any * P("C")) / format_C, -- %c => U+.... utf character diff --git a/tex/context/interface/mkiv/context-en.xml b/tex/context/interface/mkiv/context-en.xml index 67d229f4e..1d66d20df 100644 --- a/tex/context/interface/mkiv/context-en.xml +++ b/tex/context/interface/mkiv/context-en.xml @@ -22423,6 +22423,9 @@ <cd:parameter name="method"> <cd:constant type="auto"/> </cd:parameter> + <cd:parameter name="size"> + <cd:constant type="cd:number"/> + </cd:parameter> <cd:parameter name="factor"> <cd:constant type="none"/> <cd:constant type="auto"/> @@ -33091,6 +33094,12 @@ <cd:parameter name="pagecolor"> <cd:constant type="cd:color"/> </cd:parameter> + <cd:parameter name="pageleft"> + <cd:resolve name="cd:command"/> + </cd:parameter> + <cd:parameter name="pageright"> + <cd:constant type="cd:command"/> + </cd:parameter> <cd:parameter name="n"> <cd:constant type="cd:number"/> </cd:parameter> diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf Binary files differindex 30f792944..38ba5c02c 100644 --- a/tex/context/interface/mkiv/i-context.pdf +++ b/tex/context/interface/mkiv/i-context.pdf diff --git a/tex/context/interface/mkiv/i-mathfence.xml b/tex/context/interface/mkiv/i-mathfence.xml index 76151fae4..5e1abec2b 100644 --- a/tex/context/interface/mkiv/i-mathfence.xml +++ b/tex/context/interface/mkiv/i-mathfence.xml @@ -43,6 +43,9 @@ <cd:parameter name="method"> <cd:constant type="auto"/> </cd:parameter> + <cd:parameter name="size"> + <cd:constant type="cd:number"/> + </cd:parameter> <cd:parameter name="factor"> <cd:constant type="none"/> <cd:constant type="auto"/> diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf Binary files differindex d0e8abe4a..d776f503d 100644 --- a/tex/context/interface/mkiv/i-readme.pdf +++ b/tex/context/interface/mkiv/i-readme.pdf diff --git a/tex/context/interface/mkiv/i-register.xml b/tex/context/interface/mkiv/i-register.xml index 4d8010559..66570dd3b 100644 --- a/tex/context/interface/mkiv/i-register.xml +++ b/tex/context/interface/mkiv/i-register.xml @@ -162,6 +162,12 @@ <cd:parameter name="pagecolor"> <cd:constant type="cd:color"/> </cd:parameter> + <cd:parameter name="pageleft"> + <cd:resolve name="cd:command"/> + </cd:parameter> + <cd:parameter name="pageright"> + <cd:constant type="cd:command"/> + </cd:parameter> <cd:parameter name="n"> <cd:constant type="cd:number"/> </cd:parameter> @@ -544,7 +550,7 @@ </cd:keywords> <cd:index list="yes"/> </cd:arguments> - </cd:command> + </cd:command> <cd:command name="stopregister" level="document" category="structure" file="strc-reg.mkiv"> <cd:arguments> @@ -664,4 +670,4 @@ </cd:arguments> </cd:command> -</cd:interface>
\ No newline at end of file +</cd:interface> diff --git a/tex/context/modules/mkiv/m-scite.mkiv b/tex/context/modules/mkiv/m-scite.mkiv index 48f1022ad..92a498b37 100644 --- a/tex/context/modules/mkiv/m-scite.mkiv +++ b/tex/context/modules/mkiv/m-scite.mkiv @@ -332,6 +332,7 @@ visualizers.register("sql", visualizer) {\scitespaceskip\interwordspace % \fontcharwd\font`0\relax % brrrrr \let\slxb\gobbleoneargument \let\slxe\space + \let\slxbreak\relax \let\installscitecommandsinline\relax} \unexpanded\def\installscitecommandsdisplay @@ -342,10 +343,12 @@ visualizers.register("sql", visualizer) \clf_sciteinstallcommands -\installscitecommandsinline +\let\slxb \gobbleoneargument +\let\slxe \space +\let\slxbreak\relax -\let\slxS\buff_scite_slxs -\let\slxF\buff_scite_slxf +\let\slxS \buff_scite_slxs +\let\slxF \buff_scite_slxf \def\module_scite_inherit_typing {\buff_verbatim_initialize_typing_one diff --git a/tex/context/modules/mkiv/s-fonts-effects.mkiv b/tex/context/modules/mkiv/s-fonts-effects.mkiv new file mode 100644 index 000000000..9b712938b --- /dev/null +++ b/tex/context/modules/mkiv/s-fonts-effects.mkiv @@ -0,0 +1,59 @@ +%D \module +%D [ file=s-fonts-basics, % was s-fnt-01, +%D version=2006.10.10, % guess +%D title=\CONTEXT\ Style File, +%D subtitle=Listing Glyphs in Large Fonts, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This module is just a check for \type {luatex-basics-prepare}. + +\startmodule[fonts-effects] + +\startluacode +moduledata.fonts = moduledata.fonts or { } +moduledata.fonts.effects = moduledata.fonts.effects or { } + +function moduledata.fonts.effects.showfonteffect() + local effect = fonts.hashes.properties[true].effect + if effect then + local context = context + local BC, NC, EQ, NR = context.BC, context.NC, context.EQ, context.NR + context.starttabulate { "||||||||" } + BC() context("id") EQ() context(font.current()) + BC() context("factor") EQ() context(effect.factor) + BC() context("wdelta") EQ() context(effect.wdelta) + NC() NR() + BC() context("effect") EQ() context(effect.effect) + BC() context("hfactor") EQ() context(effect.hfactor) + BC() context("hdelta") EQ() context(effect.hdelta) + NC() NR() + BC() context("width") EQ() context(effect.width) + BC() context("vfactor") EQ() context(effect.vfactor) + BC() context("ddelta") EQ() context(effect.ddelta) + NC() NR() + context.stoptabulate() + end +end +\stopluacode + +\installmodulecommandluasingle \showfonteffect {moduledata.fonts.effects.showfonteffect} + +\stopmodule + +\continueifinputfile{s-fonts-effects.mkiv} + +\usemodule[art-01] + +\starttext + + \definedfont[Serif*default,boldened] An example. + + \showfonteffect + +\stopmodule diff --git a/tex/context/modules/mkiv/s-fonts-shapes.lua b/tex/context/modules/mkiv/s-fonts-shapes.lua index 748c5a92a..2c4cd445f 100644 --- a/tex/context/modules/mkiv/s-fonts-shapes.lua +++ b/tex/context/modules/mkiv/s-fonts-shapes.lua @@ -107,220 +107,177 @@ end local descriptions = nil local characters = nil + local function showglyphshape(specification) - specification = interfaces.checkedspecification(specification) - local id, cs = fonts.definers.internal(specification,"<module:fonts:shapes:font>") - local tfmdata = fontdata[id] - local charnum = tonumber(specification.character) or fonts.helpers.nametoslot(specification.character) - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - local parameters = tfmdata.parameters - local c = characters[charnum] - local d = descriptions[charnum] - if d then - local factor = (parameters.size/parameters.units)*((7200/7227)/65536) - local llx, lly, urx, ury = unpack(d.boundingbox) - llx, lly, urx, ury = llx*factor, lly*factor, urx*factor, ury*factor - local width, italic = (d.width or 0)*factor, (d.italic or 0)*factor - local top_accent, bot_accent = (d.top_accent or 0)*factor, (d.bot_accent or 0)*factor - local anchors, math = d.anchors, d.math - context.start() - context.dontleavehmode() - context.obeyMPboxdepth() - context.startMPcode() - context("numeric lw ; lw := .125bp ;") - context("pickup pencircle scaled lw ;") - if width < 0.01 then - -- catches zero width marks - context('picture p ; p := textext.drt("\\hskip5sp\\getuvalue{%s}\\gray\\char%s"); draw p ;',cs,charnum) - else - context('picture p ; p := textext.drt("\\getuvalue{%s}\\gray\\char%s"); draw p ;',cs,charnum) - end - context('draw (%s,%s)--(%s,%s)--(%s,%s)--(%s,%s)--cycle withcolor green ;',llx,lly,urx,lly,urx,ury,llx,ury) - context('draw (%s,%s)--(%s,%s) withcolor green ;',llx,0,urx,0) - context('draw boundingbox p withcolor .2white withpen pencircle scaled .065bp ;') - context("defaultscale := 0.05 ; ") - -- inefficient but non critical - local slant = { - function(v,dx,dy,txt,xsign,ysign,loc,labloc) - local n = #v - if n > 0 then - local l = { } - for i=1,n do - local c = v[i] - local h = c.height or 0 - local k = c.kern or 0 - l[i] = formatters["((%s,%s) shifted (%s,%s))"](xsign*k*factor,ysign*h*factor,dx,dy) - end - context("draw ((%s,%s) shifted (%s,%s))--%s dashed (evenly scaled 1/16) withcolor .5white;", xsign*v[1].kern*factor,lly,dx,dy,l[1]) --- context("draw laddered (%s) withcolor .5white ;",table.concat(l,"..")) - context("draw laddered (%..t) withcolor .5white ;",l) - context("draw ((%s,%s) shifted (%s,%s))--%s dashed (evenly scaled 1/16) withcolor .5white;", xsign*v[#v].kern*factor,ury,dx,dy,l[#l]) - for i=1,n do - context("draw %s withcolor blue withpen pencircle scaled 2lw ;",l[i]) - end - end - end, - function(v,dx,dy,txt,xsign,ysign,loc,labloc) - local n = #v - if n > 0 then - local l = { } - for i=1,n do - local c = v[i] - local h = c.height or 0 - local k = c.kern or 0 - l[i] = formatters["((%s,%s) shifted (%s,%s))"](xsign*k*factor,ysign*h*factor,dx,dy) - end - if loc == "top" then - context('label.%s("\\type{%s}",%s shifted (0,-1bp)) ;',loc,txt,l[n]) - else - context('label.%s("\\type{%s}",%s shifted (0,2bp)) ;',loc,txt,l[1]) - end - for i=1,n do - local c = v[i] - local h = c.height or 0 - local k = c.kern or 0 - context('label.top("(%s,%s)",%s shifted (0,-2bp));',k,h,l[i]) + -- + local specification = interfaces.checkedspecification(specification) + local id, cs = fonts.definers.internal(specification,"<module:fonts:shapes:font>") + local tfmdata = fontdata[id] + local characters = tfmdata.characters + local descriptions = tfmdata.descriptions + local parameters = tfmdata.parameters + local anchors = fonts.helpers.collectanchors(tfmdata) + + local function showonecharacter(unicode) + local c = characters [unicode] + local d = descriptions[unicode] + if c and d then + local factor = (parameters.size/parameters.units)*((7200/7227)/65536) + local llx, lly, urx, ury = unpack(d.boundingbox) + llx, lly, urx, ury = llx*factor, lly*factor, urx*factor, ury*factor + local width = (d.width or 0)*factor + context.start() + context.dontleavehmode() + context.obeyMPboxdepth() + context.startMPcode() + context("numeric lw ; lw := .125bp ;") + context("pickup pencircle scaled lw ;") + if width < 0.01 then + -- catches zero width marks + context('picture p ; p := textext.drt("\\hskip5sp\\getuvalue{%s}\\gray\\char%s"); draw p ;',cs,unicode) + else + context('picture p ; p := textext.drt("\\getuvalue{%s}\\gray\\char%s"); draw p ;',cs,unicode) + end + context('draw (%s,%s)--(%s,%s)--(%s,%s)--(%s,%s)--cycle withcolor green ;',llx,lly,urx,lly,urx,ury,llx,ury) + context('draw (%s,%s)--(%s,%s) withcolor green ;',llx,0,urx,0) + context('draw boundingbox p withcolor .2white withpen pencircle scaled .065bp ;') + context("defaultscale := 0.05 ; ") + -- inefficient but non critical + local slant = { + function(v,dx,dy,txt,xsign,ysign,loc,labloc) + local n = #v + if n > 0 then + local l = { } + for i=1,n do + local c = v[i] + local h = c.height or 0 + local k = c.kern or 0 + l[i] = formatters["((%s,%s) shifted (%s,%s))"](xsign*k*factor,ysign*h*factor,dx,dy) + end + context("draw ((%s,%s) shifted (%s,%s))--%s dashed (evenly scaled 1/16) withcolor .5white;", xsign*v[1].kern*factor,lly,dx,dy,l[1]) + context("draw laddered (%..t) withcolor .5white ;",l) + context("draw ((%s,%s) shifted (%s,%s))--%s dashed (evenly scaled 1/16) withcolor .5white;", xsign*v[#v].kern*factor,ury,dx,dy,l[#l]) + for i=1,n do + context("draw %s withcolor blue withpen pencircle scaled 2lw ;",l[i]) + end end - end - end, - } - if math then - local kerns = math.kerns - if kerns then - for i=1,#slant do - local s = slant[i] - for k, v in next, kerns do - if k == "topright" then - s(v,width+italic,0,k,1,1,"top","ulft") - elseif k == "bottomright" then - s(v,width,0,k,1,1,"bot","lrt") - elseif k == "topleft" then - s(v,0,0,k,-1,1,"top","ulft") - elseif k == "bottomleft" then - s(v,0,0,k,-1,1,"bot","lrt") + end, + function(v,dx,dy,txt,xsign,ysign,loc,labloc) + local n = #v + if n > 0 then + local l = { } + for i=1,n do + local c = v[i] + local h = c.height or 0 + local k = c.kern or 0 + l[i] = formatters["((%s,%s) shifted (%s,%s))"](xsign*k*factor,ysign*h*factor,dx,dy) + end + if loc == "top" then + context('label.%s("\\type{%s}",%s shifted (0,-1bp)) ;',loc,txt,l[n]) + else + context('label.%s("\\type{%s}",%s shifted (0,2bp)) ;',loc,txt,l[1]) + end + for i=1,n do + local c = v[i] + local h = c.height or 0 + local k = c.kern or 0 + context('label.top("(%s,%s)",%s shifted (0,-2bp));',k,h,l[i]) end end - end - end - end - local function show(x,y,txt) - local xx, yy = x*factor, y*factor - context("draw (%s,%s) withcolor blue withpen pencircle scaled 2lw ;",xx,yy) - context('label.top("\\type{%s}",(%s,%s-2bp)) ;',txt,xx,yy) - context('label.bot("(%s,%s)",(%s,%s+2bp)) ;',x,y,xx,yy) - end - if anchors then - local a = anchors.baselig - if a then - for k, v in next, a do - for i=1,#v do - local p = v[i] - show(p[1],p[2],k .. ":" .. i) + end, + } + -- + local math = d.math + if math then + local kerns = math.kerns + if kerns then + for i=1,#slant do + local s = slant[i] + for k, v in next, kerns do + if k == "topright" then + -- s(v,width+italic,0,k,1,1,"top","ulft") + s(v,width,0,k,1,1,"top","ulft") + elseif k == "bottomright" then + s(v,width,0,k,1,1,"bot","lrt") + elseif k == "topleft" then + s(v,0,0,k,-1,1,"top","ulft") + elseif k == "bottomleft" then + s(v,0,0,k,-1,1,"bot","lrt") + end + end end end - end - local a = anchors.mark - if a then - for k, v in next, a do - show(v[1],v[2],k) - end - end - local a = anchors.basechar - if a then - for k, v in next, a do - show(v[1],v[2],k) + local accent = math.accent + if accent and accent ~= 0 then + local a = accent * factor + context('draw (%s,%s+1bp)--(%s,%s-1bp) withcolor blue;',a,ury,a,ury) + context('label.bot("\\type{%s}",(%s,%s+1bp));',"accent",a,ury) + context('label.top("%s",(%s,%s-1bp));',math.accent,a,ury) end end - local ba = anchors.centry - if a then - for k, v in next, a do - show(v[1],v[2],k) + -- + local anchordata = anchors[unicode] + if anchordata then + local function show(txt,list) + if list then + for i=1,#list do + local li = list[i] + local x, y = li[1], li[2] + local xx, yy = x*factor, y*factor + context("draw (%s,%s) withcolor blue withpen pencircle scaled 2lw ;",xx,yy) + context('label.top("\\infofont %s",(%s,%s-2.75bp)) ;',txt .. i,xx,yy) + context('label.bot("\\infofont (%s,%s)",(%s,%s+2.75bp)) ;',x,y,xx,yy) + end + end end + -- + show("b",anchordata.base) + show("m",anchordata.mark) + show("l",anchordata.ligature) + show("e",anchordata.entry) + show("x",anchordata.exit) end - local a = anchors.cexit - if a then - for k, v in next, a do - show(v[1],v[2],k) - end + -- + local italic = d.italic + if italic and italic ~= 0 then + local i = italic * factor + context('draw (%s,%s-1bp)--(%s,%s-0.5bp) withcolor blue ;',width,ury,width,ury) + context('draw (%s,%s-1bp)--(%s,%s-0.5bp) withcolor blue ;',width+i,ury,width+i,ury) + context('draw (%s,%s-1bp)--(%s,%s-1bp) withcolor blue ;',width,ury,width+i,ury) + context('label.lft("\\type{%s}",(%s+2bp,%s-1bp));',"italic",width,ury) + context('label.rt("%s",(%s-2bp,%s-1bp));',italic,width+i,ury) end + context('draw origin withcolor red withpen pencircle scaled 2lw;') + context("setbounds currentpicture to boundingbox currentpicture enlarged 1bp ;") + context("currentpicture := currentpicture scaled 8 ;") + context.stopMPcode() + context.stop() end - if italic ~= 0 then - context('draw (%s,%s-1bp)--(%s,%s-0.5bp) withcolor blue ;',width,ury,width,ury) - context('draw (%s,%s-1bp)--(%s,%s-0.5bp) withcolor blue ;',width+italic,ury,width+italic,ury) - context('draw (%s,%s-1bp)--(%s,%s-1bp) withcolor blue ;',width,ury,width+italic,ury) - context('label.lft("\\type{%s}",(%s+2bp,%s-1bp));',"italic",width,ury) - context('label.rt("%s",(%s-2bp,%s-1bp));',d.italic,width+italic,ury) - end - if top_accent ~= 0 then - context('draw (%s,%s+1bp)--(%s,%s-1bp) withcolor blue;',top_accent,ury,top_accent,ury) - context('label.bot("\\type{%s}",(%s,%s+1bp));',"top_accent",top_accent,ury) - context('label.top("%s",(%s,%s-1bp));',d.top_accent,top_accent,ury) - end - if bot_accent ~= 0 then - context('draw (%s,%s+1bp)--(%s,%s-1bp) withcolor blue;',bot_accent,lly,bot_accent,lly) - context('label.top("\\type{%s}",(%s,%s-1bp));',"bot_accent",top_accent,ury) - context('label.bot("%s",(%s,%s+1bp));',d.bot_accent,bot_accent,lly) - end - context('draw origin withcolor red withpen pencircle scaled 2lw;') - context("setbounds currentpicture to boundingbox currentpicture enlarged 1bp ;") - context("currentpicture := currentpicture scaled 8 ;") - context.stopMPcode() - context.stop() - -- elseif c then - -- lastdata, lastunicode = nil, nil - -- local factor = (7200/7227)/65536 - -- context.startMPcode() - -- context("pickup pencircle scaled .25bp ; ") - -- context('picture p ; p := image(draw textext.drt("\\gray\\char%s");); draw p ;',charnum) - -- context('draw boundingbox p withcolor .2white withpen pencircle scaled .065bp ;') - -- context("defaultscale := 0.05 ; ") - -- local italic, top_accent, bot_accent = (c.italic or 0)*factor, (c.top_accent or 0)*factor, (c.bot_accent or 0)*factor - -- local width, height, depth = (c.width or 0)*factor, (c.height or 0)*factor, (c.depth or 0)*factor - -- local ury = height - -- if italic ~= 0 then - -- context('draw (%s,%s-1bp)--(%s,%s-0.5bp) withcolor blue;',width,ury,width,ury) - -- context('draw (%s,%s-1bp)--(%s,%s-0.5bp) withcolor blue;',width+italic,ury,width+italic,ury) - -- context('draw (%s,%s-1bp)--(%s,%s-1bp) withcolor blue;',width,ury,width+italic,height) - -- context('label.lft("\\type{%s}",(%s+2bp,%s-1bp));',"italic",width,height) - -- context('label.rt("%6.3f bp",(%s-2bp,%s-1bp));',italic,width+italic,height) - -- end - -- if top_accent ~= 0 then - -- context('draw (%s,%s+1bp)--(%s,%s-1bp) withcolor blue;',top_accent,ury,top_accent,height) - -- context('label.bot("\\type{%s}",(%s,%s+1bp));',"top_accent",top_accent,height) - -- context('label.top("%6.3f bp",(%s,%s-1bp));',top_accent,top_accent,height) - -- end - -- if bot_accent ~= 0 then - -- context('draw (%s,%s+1bp)--(%s,%s-1bp) withcolor blue;',bot_accent,lly,bot_accent,height) - -- context('label.top("\\type{%s}",(%s,%s-1bp));',"bot_accent",top_accent,height) - -- context('label.bot("%6.3f bp",(%s,%s+1bp));',bot_accent,bot_accent,height) - -- end - -- context('draw origin withcolor red withpen pencircle scaled 1bp;') - -- context("setbounds currentpicture to boundingbox currentpicture enlarged 1bp ;") - -- context("currentpicture := currentpicture scaled 8 ;") - -- context.stopMPcode() - else - -- lastdata, lastunicode = nil, nil - -- context("no such shape: 0x%05X",charnum) end -end -moduledata.fonts.shapes.showglyphshape = showglyphshape + local unicode = tonumber(specification.character) or + fonts.helpers.nametoslot(specification.character) -function moduledata.fonts.shapes.showallglypshapes(specification) - specification = interfaces.checkedspecification(specification) - local id, cs = fonts.definers.internal(specification,"<module:fonts:shapes:font>") - local descriptions = fontdata[id].descriptions - for unicode, description in fonts.iterators.descriptions(tfmdata) do - if unicode >= 0x110000 then - break + if unicode then + showonecharacter(unicode) + else + context.modulefontsstartshowglyphshapes() + for unicode, description in fonts.iterators.descriptions(tfmdata) do + if unicode >= 0x110000 then + break + end + context.modulefontsstartshowglyphshape(unicode,description.name or "",description.index or 0) + showonecharacter(unicode) + context.modulefontsstopshowglyphshape() end - context.modulefontsstartshowglyphshape(unicode,description.name or "",description.index or 0) - showglyphshape { number = id, character = unicode } - context.modulefontsstopshowglyphshape() + context.modulefontsstopshowglyphshapes() end + end +moduledata.fonts.shapes.showglyphshape = showglyphshape +moduledata.fonts.shapes.showallglypshapes = showglyphshape + function moduledata.fonts.shapes.showlastglyphshapefield(unicode,name) if not descriptions then -- bad news diff --git a/tex/context/modules/mkiv/s-fonts-shapes.mkiv b/tex/context/modules/mkiv/s-fonts-shapes.mkiv index 53ed1b426..d05438f3d 100644 --- a/tex/context/modules/mkiv/s-fonts-shapes.mkiv +++ b/tex/context/modules/mkiv/s-fonts-shapes.mkiv @@ -30,7 +30,7 @@ \startsetups module:showallglyphshapes:start \unexpanded\def\modulefontsstartshowglyphshape##1##2##3{ - \startTEXpage[\c!offset=\exheight] + \startTEXpage[\c!offset=\exheight,\c!frame=\v!on] \edef\lastshownglyphshapefieldunicode{##1}% \edef\lastshownglyphshapefieldname {##2}% \edef\lastshownglyphshapefieldindex {##3}% @@ -58,6 +58,15 @@ \stopsetups +\startsetups module:showallglyphshapes:stop + + % nothing + +\stopsetups + +\unexpanded\def\modulefontsstartshowglyphshapes{\setups[module:showallglyphshapes:start]} +\unexpanded\def\modulefontsstopshowglyphshapes {\setups[module:showallglyphshapes:stop]} + \protect % downward compatibility: @@ -109,10 +118,12 @@ % \startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{50bp}{0x1D45D}\stopTEXpage % \page -\startTEXpage[offset=0pt]\ShowGlyphShape{file:husayninotebold.ttf}{50bp}{0xF034A}\stopTEXpage -\startTEXpage[offset=0pt]\ShowGlyphShape{file:husayninotebold.ttf}{50bp}{0x006DD}\stopTEXpage +% \startTEXpage[offset=0pt]\ShowGlyphShape{file:husayninotebold.ttf}{50bp}{0xF034A}\stopTEXpage +% \startTEXpage[offset=0pt]\ShowGlyphShape{file:husayninotebold.ttf}{50bp}{0x006DD}\stopTEXpage +\startTEXpage[offset=0pt]\ShowGlyphShape{file:arabtype.ttf}{50bp}{0x0FCA1}\stopTEXpage % \showallglyphshapes[name=name:cambria-math,size=100bp] +% \showallglyphshapes[name=name:arabtype,size=100bp] % \showallglyphshapes[name=file:husayninotebold.ttf,size=100bp] % \showallglyphshapes[name=name:dejavuserif,size=100bp] diff --git a/tex/context/modules/mkiv/s-languages-hyphenation.lua b/tex/context/modules/mkiv/s-languages-hyphenation.lua index 6d3cf3d3e..65fd1ab14 100644 --- a/tex/context/modules/mkiv/s-languages-hyphenation.lua +++ b/tex/context/modules/mkiv/s-languages-hyphenation.lua @@ -29,7 +29,8 @@ local newrule = nodepool.rule local newglue = nodepool.glue local insert_node_after = nuts.insert_after -local traverse_by_id = nuts.traverse_id + +local nextglyph = nuts.traversers.glyph local tonut = nodes.tonut local tonode = nodes.tonode @@ -129,7 +130,7 @@ end local function getlanguage(head,l,left,right) local t = { } - for n in traverse_by_id(glyph_code,tonut(head)) do + for n in nextglyph, tonut(head) do t[n] = { getlang(n), getfield(n,"left"), @@ -148,7 +149,7 @@ function moduledata.languages.hyphenation.showhyphens(head) local marked = { } local cached = { } -- somehow assigning -1 fails - for n in traverse_by_id(glyph_code,tonut(head)) do + for n in nextglyph, tonut(head) do cached[n] = { getlang(n), getfield(n,"left"), diff --git a/tex/generic/context/luatex/luatex-basics-nod.lua b/tex/generic/context/luatex/luatex-basics-nod.lua index 40fb9ee4e..462b665fb 100644 --- a/tex/generic/context/luatex/luatex-basics-nod.lua +++ b/tex/generic/context/luatex/luatex-basics-nod.lua @@ -11,8 +11,9 @@ if context then os.exit() end --- Don't depend on code here as it is only needed to complement the --- font handler code. +-- Don't depend on code here as it is only needed to complement the font handler +-- code. I will move some to another namespace as I don't see other macro packages +-- use the context logic. It's a subset anyway. -- Attributes: @@ -74,8 +75,8 @@ local flush_node = node.flush_node local remove_node = node.remove local traverse_id = node.traverse_id -nodes.handlers.protectglyphs = node.protect_glyphs -nodes.handlers.unprotectglyphs = node.unprotect_glyphs +nodes.handlers.protectglyphs = node.protect_glyphs -- beware: nodes! +nodes.handlers.unprotectglyphs = node.unprotect_glyphs -- beware: nodes! local math_code = nodecodes.math local end_of_math = node.end_of_math @@ -285,6 +286,7 @@ nuts.end_of_math = direct.end_of_math nuts.traverse = direct.traverse nuts.traverse_id = direct.traverse_id nuts.traverse_char = direct.traverse_char +nuts.traverse_glyph = direct.traverse_glyph nuts.ligaturing = direct.ligaturing nuts.kerning = direct.kerning nuts.new = direct.new @@ -480,3 +482,23 @@ if not nuts.uses_font then end end +-- +do + + -- another poor mans substitute ... i will move these to a more protected + -- namespace .. experimental hack + + local dummy = tonut(node.new("glyph")) + + nuts.traversers = { + glyph = nuts.traverse_id(nodecodes.glyph,dummy), + glue = nuts.traverse_id(nodecodes.glue,dummy), + disc = nuts.traverse_id(nodecodes.disc,dummy), + boundary = nuts.traverse_id(nodecodes.boundary,dummy), + + char = nuts.traverse_char(dummy), + + node = nuts.traverse(dummy), + } + +end diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index f2cbe59d8..6b530e252 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 : 04/19/18 15:53:45 +-- merge date : 05/12/18 00:07:56 do -- begin closure to overcome local limits and interference @@ -2011,12 +2011,19 @@ end local function sequenced(t,sep,simple) if not t then return "" + elseif type(t)=="string" then + return t end local n=#t local s={} if n>0 then for i=1,n do - s[i]=tostring(t[i]) + local v=t[i] + if type(v)=="table" then + s[i]="{"..sequenced(v,sep,simple).."}" + else + s[i]=tostring(t[i]) + end end else n=0 @@ -4324,6 +4331,10 @@ local format_L=function() n=n+1 return format("(a%s and 'TRUE' or 'FALSE')",n) end +local format_n=function() + n=n+1 + return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n) +end local format_N=function() n=n+1 return format("tostring(tonumber(a%s) or a%s)",n,n) @@ -4424,6 +4435,7 @@ local builder=Cs { "start", +V("s")+V("q")+V("i")+V("d")+V("f")+V("F")+V("g")+V("G")+V("e")+V("E")+V("x")+V("X")+V("o") +V("c")+V("C")+V("S") +V("Q") ++V("n") +V("N") +V("k") +V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("T")+V("l")+V("L")+V("I")+V("w") @@ -4453,6 +4465,7 @@ local builder=Cs { "start", ["o"]=(prefix_any*P("o"))/format_o, ["S"]=(prefix_any*P("S"))/format_S, ["Q"]=(prefix_any*P("Q"))/format_Q, + ["n"]=(prefix_any*P("n"))/format_n, ["N"]=(prefix_any*P("N"))/format_N, ["k"]=(prefix_sub*P("k"))/format_k, ["c"]=(prefix_any*P("c"))/format_c, @@ -5350,8 +5363,8 @@ nodes.disccodes=disccodes local flush_node=node.flush_node local remove_node=node.remove local traverse_id=node.traverse_id -nodes.handlers.protectglyphs=node.protect_glyphs -nodes.handlers.unprotectglyphs=node.unprotect_glyphs +nodes.handlers.protectglyphs=node.protect_glyphs +nodes.handlers.unprotectglyphs=node.unprotect_glyphs local math_code=nodecodes.math local end_of_math=node.end_of_math function node.end_of_math(n) @@ -5527,6 +5540,7 @@ nuts.end_of_math=direct.end_of_math nuts.traverse=direct.traverse nuts.traverse_id=direct.traverse_id nuts.traverse_char=direct.traverse_char +nuts.traverse_glyph=direct.traverse_glyph nuts.ligaturing=direct.ligaturing nuts.kerning=direct.kerning nuts.new=direct.new @@ -5694,6 +5708,17 @@ if not nuts.uses_font then return false end end +do + local dummy=tonut(node.new("glyph")) + nuts.traversers={ + glyph=nuts.traverse_id(nodecodes.glyph,dummy), + glue=nuts.traverse_id(nodecodes.glue,dummy), + disc=nuts.traverse_id(nodecodes.disc,dummy), + boundary=nuts.traverse_id(nodecodes.boundary,dummy), + char=nuts.traverse_char(dummy), + node=nuts.traverse(dummy), + } +end end -- closure @@ -9570,10 +9595,13 @@ function constructors.scale(tfmdata,specification) local t={} for i=1,#vv do local vvi=vv[i] - t[i]={ - ["start"]=(vvi["start"] or 0)*vdelta, - ["end"]=(vvi["end"] or 0)*vdelta, - ["advance"]=(vvi["advance"] or 0)*vdelta, + local s=vvi["start"] or 0 + local e=vvi["end"] or 0 + local a=vvi["advance"] or 0 + t[i]={ + ["start"]=s==0 and 0 or s*vdelta, + ["end"]=e==0 and 0 or e*vdelta, + ["advance"]=a==0 and 0 or a*vdelta, ["extender"]=vvi["extender"], ["glyph"]=vvi["glyph"], } @@ -9585,10 +9613,13 @@ function constructors.scale(tfmdata,specification) local t={} for i=1,#hv do local hvi=hv[i] - t[i]={ - ["start"]=(hvi["start"] or 0)*hdelta, - ["end"]=(hvi["end"] or 0)*hdelta, - ["advance"]=(hvi["advance"] or 0)*hdelta, + local s=hvi["start"] or 0 + local e=hvi["end"] or 0 + local a=hvi["advance"] or 0 + t[i]={ + ["start"]=s==0 and 0 or s*hdelta, + ["end"]=e==0 and 0 or e*hdelta, + ["advance"]=a==0 and 0 or a*hdelta, ["extender"]=hvi["extender"], ["glyph"]=hvi["glyph"], } @@ -9699,7 +9730,6 @@ function constructors.scale(tfmdata,specification) else chr.commands=vc end - chr.index=nil end end targetcharacters[unicode]=chr @@ -11061,7 +11091,7 @@ function helpers.appendcommands(commands,...) return commands end local char=setmetatableindex(function(t,k) - local v={ "char",k } + local v={ "slot",0,k } t[k]=v return v end) @@ -16011,11 +16041,12 @@ local reversed=table.reversed local sort=table.sort local insert=table.insert local round=math.round -local settings_to_hash_colon_too=table.settings_to_hash_colon_too +local settings_to_hash=utilities.parsers.settings_to_hash_colon_too local setmetatableindex=table.setmetatableindex local formatters=string.formatters local sortedkeys=table.sortedkeys local sortedhash=table.sortedhash +local sequenced=table.sequenced local report=logs.reporter("otf reader") local readers=fonts.handlers.otf.readers local streamreader=readers.streamreader @@ -16171,7 +16202,7 @@ local lookupflags=setmetatableindex(function(t,k) return v end) local function axistofactors(str) - local t=settings_to_hash_colon_too(str) + local t=settings_to_hash(str) for k,v in next,t do t[k]=tonumber(v) or v end @@ -16190,9 +16221,6 @@ helpers.cleanname=cleanname function helpers.normalizedaxis(str) return hash[str] or str end -local function axistofactors(str) - return settings_to_hash_colon_too(str) -end local function getaxisscale(segments,minimum,default,maximum,user) if not minimum or not default or not maximum then return false @@ -22624,8 +22652,8 @@ local setkern=nuts.setkern local setlink=nuts.setlink local setwidth=nuts.setwidth local getwidth=nuts.getwidth -local traverse_id=nuts.traverse_id -local traverse_char=nuts.traverse_char +local nextchar=nuts.traversers.char +local nextglue=nuts.traversers.glue local insert_node_before=nuts.insert_before local insert_node_after=nuts.insert_after local properties=nodes.properties.data @@ -23033,7 +23061,7 @@ local function show(n,what,nested,symbol) end local function showsub(n,what,where) report_injections("begin subrun: %s",where) - for n in traverse_char(n) do + for n in nextchar,n do showchar(n,where) show(n,what,where," ") end @@ -23092,7 +23120,6 @@ local function show_result(head) report_injections() end local function inject_kerns_only(head,where) - head=tonut(head) if trace_injections then trace(head,"kerns") end @@ -23161,7 +23188,7 @@ local function inject_kerns_only(head,where) pre,post,replace,pretail,posttail,replacetail=getdisc(current,true) local done=false if pre then - for n in traverse_char(pre) do + for n in nextchar,pre do local p=rawget(properties,n) if p then local i=p.injections or p.preinjections @@ -23176,7 +23203,7 @@ local function inject_kerns_only(head,where) end end if post then - for n in traverse_char(post) do + for n in nextchar,post do local p=rawget(properties,n) if p then local i=p.injections or p.postinjections @@ -23191,7 +23218,7 @@ local function inject_kerns_only(head,where) end end if replace then - for n in traverse_char(replace) do + for n in nextchar,replace do local p=rawget(properties,n) if p then local i=p.injections or p.replaceinjections @@ -23223,10 +23250,9 @@ local function inject_kerns_only(head,where) if trace_injections then show_result(head) end - return tonode(head),true + return head end local function inject_positions_only(head,where) - head=tonut(head) if trace_injections then trace(head,"positions") end @@ -23324,7 +23350,7 @@ local function inject_positions_only(head,where) pre,post,replace,pretail,posttail,replacetail=getdisc(current,true) local done=false if pre then - for n in traverse_char(pre) do + for n in nextchar,pre do local p=rawget(properties,n) if p then local i=p.injections or p.preinjections @@ -23348,7 +23374,7 @@ local function inject_positions_only(head,where) end end if post then - for n in traverse_char(post) do + for n in nextchar,post do local p=rawget(properties,n) if p then local i=p.injections or p.postinjections @@ -23372,7 +23398,7 @@ local function inject_positions_only(head,where) end end if replace then - for n in traverse_char(replace) do + for n in nextchar,replace do local p=rawget(properties,n) if p then local i=p.injections or p.replaceinjections @@ -23443,7 +23469,7 @@ local function inject_positions_only(head,where) if trace_injections then show_result(head) end - return tonode(head),true + return head end local function showoffset(n,flag) local x,y=getoffsets(n) @@ -23452,7 +23478,6 @@ local function showoffset(n,flag) end end local function inject_everything(head,where) - head=tonut(head) if trace_injections then trace(head,"everything") end @@ -23691,7 +23716,7 @@ local function inject_everything(head,where) pre,post,replace,pretail,posttail,replacetail=getdisc(current,true) local done=false if pre then - for n in traverse_char(pre) do + for n in nextchar,pre do local p=rawget(properties,n) if p then local i=p.injections or p.preinjections @@ -23721,7 +23746,7 @@ local function inject_everything(head,where) end end if post then - for n in traverse_char(post) do + for n in nextchar,post do local p=rawget(properties,n) if p then local i=p.injections or p.postinjections @@ -23751,7 +23776,7 @@ local function inject_everything(head,where) end end if replace then - for n in traverse_char(replace) do + for n in nextchar,replace do local p=rawget(properties,n) if p then local i=p.injections or p.replaceinjections @@ -23852,7 +23877,7 @@ local function inject_everything(head,where) if trace_injections then show_result(head) end - return tonode(head),true + return head end local triggers=false function nodes.injections.setspacekerns(font,sequence) @@ -23899,7 +23924,7 @@ function injections.installgetspaceboth(gb) end local function injectspaces(head) if not triggers then - return head,false + return head end local lastfont=nil local spacekerns=nil @@ -23909,7 +23934,6 @@ local function injectspaces(head) local threshold=0 local leftkern=false local rightkern=false - local nuthead=tonut(head) local function updatefont(font,trig) leftkerns=trig.left rightkerns=trig.right @@ -23917,7 +23941,7 @@ local function injectspaces(head) threshold, factor=getthreshold(font) end - for n in traverse_id(glue_code,nuthead) do + for n in nextglue,head do local prev,next=getspaceboth(n) local prevchar=prev and ischar(prev) local nextchar=next and ischar(next) @@ -23955,12 +23979,8 @@ local function injectspaces(head) if trace_spaces then report_spaces("%C [%p + %p + %p] %C",prevchar,lnew,old,rnew,nextchar) end - local h=insert_node_before(nuthead,n,italickern(lnew)) - if h==nuthead then - head=tonode(h) - nuthead=h - end - insert_node_after(nuthead,n,italickern(rnew)) + head=insert_node_before(head,n,italickern(lnew)) + insert_node_after(head,n,italickern(rnew)) else local new=old+(leftkern+rightkern)*factor if trace_spaces then @@ -23975,7 +23995,7 @@ local function injectspaces(head) if trace_spaces then report_spaces("%C [%p + %p]",prevchar,old,new) end - insert_node_after(nuthead,n,italickern(new)) + insert_node_after(head,n,italickern(new)) else local new=old+leftkern*factor if trace_spaces then @@ -23994,7 +24014,7 @@ local function injectspaces(head) if trace_spaces then report_spaces("%C [%p + %p]",nextchar,old,new) end - insert_node_after(nuthead,n,italickern(new)) + insert_node_after(head,n,italickern(new)) else local new=old+rightkern*factor if trace_spaces then @@ -24007,7 +24027,7 @@ local function injectspaces(head) end end triggers=false - return head,true + return head end function injections.handler(head,where) if triggers then @@ -24029,7 +24049,7 @@ function injections.handler(head,where) end return inject_kerns_only(head,where) else - return head,false + return head end end @@ -24066,7 +24086,6 @@ local getfont=nuts.getfont local getsubtype=nuts.getsubtype local getchar=nuts.getchar local ischar=nuts.is_char -local traverse_id=nuts.traverse_id local end_of_math=nuts.end_of_math local nodecodes=nodes.nodecodes local disc_code=nodecodes.disc @@ -24475,8 +24494,6 @@ registertracker("otf.actions","otf.substitutions","otf.positions") registertracker("otf.sample","otf.steps","otf.substitutions","otf.positions","otf.analyzing") registertracker("otf.sample.silent","otf.steps=silent","otf.substitutions","otf.positions","otf.analyzing") local nuts=nodes.nuts -local tonode=nuts.tonode -local tonut=nuts.tonut local getfield=nuts.getfield local getnext=nuts.getnext local setnext=nuts.setnext @@ -24511,7 +24528,6 @@ local find_node_tail=nuts.tail local flush_node_list=nuts.flush_list local flush_node=nuts.flush_node local end_of_math=nuts.end_of_math -local traverse_nodes=nuts.traverse local set_components=nuts.set_components local take_components=nuts.take_components local count_components=nuts.count_components @@ -24519,6 +24535,7 @@ local copy_no_components=nuts.copy_no_components local copy_only_glyphs=nuts.copy_only_glyphs local setmetatable=setmetatable local setmetatableindex=table.setmetatableindex +local nextnode=nuts.traversers.node local nodecodes=nodes.nodecodes local glyphcodes=nodes.glyphcodes local disccodes=nodes.disccodes @@ -27183,7 +27200,7 @@ local function k_run_single(sub,injection,last,font,attr,lookupcache,step,datase a=getattr(sub,0) end if not a or (a==attr) then - for n in traverse_nodes(sub) do + for n in nextnode,sub do if n==last then break end @@ -27336,7 +27353,7 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase a=getattr(sub,0) end if not a or (a==attr) then - for n in traverse_nodes(sub) do + for n in nextnode,sub do if n==last then break end @@ -27436,12 +27453,10 @@ do nesting=nesting-1 return head,false end - local head=tonut(head) if trace_steps then checkstep(head) end local initialrl=direction=="TRT" and -1 or 0 - local done=false local datasets=otfdataset(tfmdata,font,attr) local dirstack={} sweephead={} @@ -27459,10 +27474,7 @@ do local nofsteps=sequence.nofsteps local skiphash=sequence.skiphash if not steps then - local h,ok=handler(head,dataset,sequence,initialrl,font,attr) - if ok then - done=true - end + local h,ok=handler(head,dataset,sequence,initialrl,font,attr) if h and h~=head then head=h end @@ -27488,7 +27500,6 @@ do local ok head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) if ok then - done=true break end end @@ -27531,9 +27542,6 @@ do if a then local ok head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) - if ok then - done=true - end if start then start=getnext(start) end @@ -27556,9 +27564,6 @@ do else start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,skiphash,handler) end - if ok then - done=true - end else start=getnext(start) end @@ -27599,7 +27604,6 @@ do local ok head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step) if ok then - done=true break elseif not start then break @@ -27628,9 +27632,6 @@ do else start,ok=comprun(start,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,skiphash,handler) end - if ok then - done=true - end else start=getnext(start) end @@ -27651,8 +27652,7 @@ do end end nesting=nesting-1 - head=tonode(head) - return head,done + return head end function otf.datasetpositionprocessor(head,font,direction,dataset) currentfont=font @@ -27673,7 +27673,6 @@ do local handler=handlers[typ] local steps=sequence.steps local nofsteps=sequence.nofsteps - local head=tonut(head) local done=false local dirstack={} local start=head @@ -27725,7 +27724,7 @@ do start=getnext(start) end end - return tonode(head) + return head end end local plugins={} @@ -28011,8 +28010,6 @@ local methods=fonts.analyzers.methods local otffeatures=fonts.constructors.features.otf local registerotffeature=otffeatures.register local nuts=nodes.nuts -local tonode=nuts.tonode -local tonut=nuts.tonut local getnext=nuts.getnext local getprev=nuts.getprev local getboth=nuts.getboth @@ -28054,21 +28051,25 @@ replace_all_nbsp=function(head) end return replace_all_nbsp(head) end -local xprocesscharacters=nil +local processcharacters=nil if context then - xprocesscharacters=function(head,font) - xprocesscharacters=nodes.handlers.characters - return xprocesscharacters(head,font) + local fontprocesses=fonts.hashes.processes + function processcharacters(head,font) + local processors=fontprocesses[font] + for i=1,#processors do + head=processors[i](head,font,0) + end + return head end else - xprocesscharacters=function(head,font) - xprocesscharacters=nodes.handlers.nodepass - return xprocesscharacters(head,font) + function processcharacters(head,font) + local processors=fontdata[font].shared.processes + for i=1,#processors do + head=processors[i](head,font,0) + end + return head end end -local function processcharacters(head,font) - return tonut(xprocesscharacters(tonode(head))) -end local indicgroups=characters and characters.indicgroups if not indicgroups and characters then local indic={ @@ -29657,7 +29658,6 @@ local function analyze_next_chars_two(c,font) end end local function method_one(head,font,attr) - head=tonut(head) local current=head local start=true local done=false @@ -29836,10 +29836,9 @@ local function method_one(head,font,attr) if nbspaces>0 then head=replace_all_nbsp(head) end - return tonode(head),done + return head,done end local function method_two(head,font,attr) - head=tonut(head) local current=head local start=true local done=false @@ -29918,7 +29917,7 @@ local function method_two(head,font,attr) if nbspaces>0 then head=replace_all_nbsp(head) end - return tonode(head),done + return head,done end for i=1,nofscripts do methods[scripts_one[i]]=method_one @@ -33926,8 +33925,10 @@ local settings_to_hash=utilities.parsers.settings_to_hash_colon_too local helpers=fonts.helpers local prependcommands=helpers.prependcommands local charcommand=helpers.commands.char +local leftcommand=helpers.commands.left local rightcommand=helpers.commands.right local upcommand=helpers.commands.up +local downcommand=helpers.commands.down local dummycommand=helpers.commands.dummy local report_effect=logs.reporter("fonts","effect") local report_slant=logs.reporter("fonts","slant") @@ -34115,7 +34116,7 @@ local function setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze end end local character=characters[0x221A] - if character then + if character and character.next then local char=character local next=character.next wdpatch(char) @@ -34131,7 +34132,8 @@ local function setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze if v then local top=v[#v] if top then - htpatch(characters[top.glyph]) + local char=characters[top.glyph] + htpatch(char) end end end @@ -34152,7 +34154,7 @@ local function manipulateeffect(tfmdata) local ddelta=effect.ddelta*vfactor*multiplier local vshift=effect.vshift*vfactor*multiplier local squeeze=effect.squeeze - local hshift=wdelta + local hshift=wdelta/2 local dx=multiplier*vfactor local dy=vshift local factor=(1+effect.factor)*factor @@ -36369,8 +36371,8 @@ local setlink=nuts.setlink local setprev=nuts.setprev local n_ligaturing=node.ligaturing local n_kerning=node.kerning -local ligaturing=nuts.ligaturing -local kerning=nuts.kerning +local d_ligaturing=nuts.ligaturing +local d_kerning=nuts.kerning local basemodepass=true local function l_warning() texio.write_nl("warning: node.ligaturing called directly") l_warning=nil end local function k_warning() texio.write_nl("warning: node.kerning called directly") k_warning=nil end @@ -36386,13 +36388,24 @@ function node.kerning(...) end return n_kerning(...) end +function nuts.ligaturing(...) + if basemodepass and l_warning then + l_warning() + end + return d_ligaturing(...) +end +function nuts.kerning(...) + if basemodepass and k_warning then + k_warning() + end + return d_kerning(...) +end function nodes.handlers.setbasemodepass(v) basemodepass=v end -function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) +local function nodepass(head,groupcode,size,packtype,direction) local fontdata=fonts.hashes.identifiers if fontdata then - local nuthead=tonut(head) local usedfonts={} local basefonts={} local prevfont=nil @@ -36400,7 +36413,7 @@ function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) local variants=nil local redundant=nil local nofused=0 - for n in traverse_id(glyph_code,nuthead) do + for n in traverse_id(glyph_code,head) do local font=getfont(n) if font~=prevfont then if basefont then @@ -36461,8 +36474,8 @@ function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) for i=1,#redundant do local r=redundant[i] local p,n=getboth(r) - if r==nuthead then - nuthead=n + if r==head then + head=n setprev(n) else setlink(p,n) @@ -36481,7 +36494,7 @@ function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) flush_node(r) end end - for d in traverse_id(disc_code,nuthead) do + for d in traverse_id(disc_code,head) do local _,_,r=getdisc(d) if r then for n in traverse_id(glyph_code,r) do @@ -36519,16 +36532,16 @@ function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) local start=range[1] local stop=range[2] if start then - local front=nuthead==start + local front=head==start local prev,next if stop then next=getnext(stop) - start,stop=ligaturing(start,stop) - start,stop=kerning(start,stop) + start,stop=d_ligaturing(start,stop) + start,stop=d_kerning(start,stop) else prev=getprev(start) - start=ligaturing(start) - start=kerning(start) + start=d_ligaturing(start) + start=d_kerning(start) end if prev then setlink(prev,start) @@ -36536,40 +36549,57 @@ function nodes.handlers.nodepass(head,groupcode,size,packtype,direction) if next then setlink(stop,next) end - if front and nuthead~=start then - head=tonode(start) + if front and head~=start then + head=start end end end end - return head,true - else - return head,false end + return head end -function nodes.handlers.basepass(head) +local function basepass(head) if basemodepass then - head=n_ligaturing(head) - head=n_kerning(head) + head=d_ligaturing(head) + head=d_kerning(head) end - return head,true + return head end -local nodepass=nodes.handlers.nodepass -local basepass=nodes.handlers.basepass +local protectpass=node.direct.protect_glyphs local injectpass=nodes.injections.handler -local protectpass=nodes.handlers.protectglyphs +function nodes.handlers.nodepass(head,...) + if head then + return tonode(nodepass(tonut(head),...)) + end +end +function nodes.handlers.basepass(head) + if head then + return tonode(basepass(tonut(head))) + end +end +function nodes.handlers.injectpass(head) + if head then + return tonode(injectpass(tonut(head))) + end +end +function nodes.handlers.protectpass(head) + if head then + protectpass(tonut(head)) + return head + end +end function nodes.simple_font_handler(head,groupcode,size,packtype,direction) if head then + head=tonut(head) head=nodepass(head,groupcode,size,packtype,direction) head=injectpass(head) if not basemodepass then head=basepass(head) end protectpass(head) - return head,true - else - return head,false + head=tonode(head) end + return head end end -- closure diff --git a/tex/generic/context/luatex/luatex-test.tex b/tex/generic/context/luatex/luatex-test.tex index 2aa4f22d9..d472e8db6 100644 --- a/tex/generic/context/luatex/luatex-test.tex +++ b/tex/generic/context/luatex/luatex-test.tex @@ -147,6 +147,18 @@ $\sin{x}$ \egroup +\bgroup + + \font\boldera=lmroman10-regular:mode=node;liga=yes;kern=yes; + \font\bolderb=lmroman10-regular:mode=node;liga=yes;kern=yes;effect=0.1; + \font\bolderc=lmroman10-regular:mode=node;liga=yes;kern=yes;effect={width=0.1,auto=yes}; + + \boldera Just a line. \par + \bolderb Just a line. \par + \bolderc Just a line. \par + +\egroup + % \font\amiri=file:amiri-regular.ttf:% % mode=node;analyze=yes;language=dflt;script=arab;ccmp=yes;% % init=yes;medi=yes;fina=yes;isol=yes;% |