diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua | 421 |
1 files changed, 188 insertions, 233 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua b/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua index b55f1ca7cae..969a195e1fe 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/spac-ver.lua @@ -116,8 +116,8 @@ local a_snapmethod = attributes.private('snapmethod') local a_snapvbox = attributes.private('snapvbox') local nuts = nodes.nuts -local tonut = nuts.tonut local tonode = nuts.tonode +local tonut = nuts.tonut local getnext = nuts.getnext local setlink = nuts.setlink @@ -147,16 +147,15 @@ 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 - -local nextnode = nuts.traversers.node -local nexthlist = nuts.traversers.hlist - +----- writable_spec = nuts.writable_spec local nodereference = nuts.reference local theprop = nuts.theprop @@ -171,9 +170,8 @@ local new_kern = nodepool.kern local new_rule = nodepool.rule local nodecodes = nodes.nodecodes -local gluecodes = nodes.gluecodes ------ penaltycodes = nodes.penaltycodes ------ listcodes = nodes.listcodes +local skipcodes = nodes.skipcodes +local penaltycodes = nodes.penaltycodes local penalty_code = nodecodes.penalty local kern_code = nodecodes.kern @@ -181,22 +179,21 @@ local glue_code = nodecodes.glue local insert_code = nodecodes.ins local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist -local rule_code = nodecodes.rule local localpar_code = nodecodes.localpar -local userskip_code = gluecodes.userskip -local lineskip_code = gluecodes.lineskip -local baselineskip_code = gluecodes.baselineskip -local parskip_code = gluecodes.parskip -local topskip_code = gluecodes.topskip -local splittopskip_code = gluecodes.splittopskip +local linebreak_code = penaltycodes.linebreakpenalty -local linelist_code = nodes.listcodes.line +local userskip_code = skipcodes.userskip +local lineskip_code = skipcodes.lineskip +local baselineskip_code = skipcodes.baselineskip +local parskip_code = skipcodes.parskip +local topskip_code = skipcodes.topskip +local splittopskip_code = skipcodes.splittopskip -local abovedisplayskip_code = gluecodes.abovedisplayskip -local belowdisplayskip_code = gluecodes.belowdisplayskip -local abovedisplayshortskip_code = gluecodes.abovedisplayshortskip -local belowdisplayshortskip_code = gluecodes.belowdisplayshortskip +local abovedisplayskip_code = skipcodes.abovedisplayskip +local belowdisplayskip_code = skipcodes.belowdisplayskip +local abovedisplayshortskip_code = skipcodes.abovedisplayshortskip +local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip local properties = nodes.properties.data @@ -211,93 +208,90 @@ vspacingdata.snapmethods = snapmethods storage.register("builders/vspacing/data/snapmethods", snapmethods, "builders.vspacing.data.snapmethods") -do +local default = { + [v_maxheight] = true, + [v_maxdepth] = true, + [v_strut] = true, + [v_hfraction] = 1, + [v_dfraction] = 1, + [v_bfraction] = 0.25, +} - local default = { - [v_maxheight] = true, - [v_maxdepth] = true, - [v_strut] = true, - [v_hfraction] = 1, - [v_dfraction] = 1, - [v_bfraction] = 0.25, - } +local fractions = { + [v_minheight] = v_hfraction, [v_maxheight] = v_hfraction, + [v_mindepth] = v_dfraction, [v_maxdepth] = v_dfraction, + [v_box] = v_bfraction, + [v_top] = v_tlines, [v_bottom] = v_blines, +} - local fractions = { - [v_minheight] = v_hfraction, [v_maxheight] = v_hfraction, - [v_mindepth] = v_dfraction, [v_maxdepth] = v_dfraction, - [v_box] = v_bfraction, - [v_top] = v_tlines, [v_bottom] = v_blines, - } +local values = { + offset = "offset" +} - local values = { - offset = "offset" - } +local colonsplitter = lpeg.splitat(":") - local colonsplitter = lpeg.splitat(":") - - local function listtohash(str) - local t = { } - for s in gmatch(str,"[^, ]+") do - local key, detail = lpegmatch(colonsplitter,s) - local v = variables[key] - if v then - t[v] = true - if detail then - local k = fractions[key] +local function listtohash(str) + local t = { } + for s in gmatch(str,"[^, ]+") do + local key, detail = lpegmatch(colonsplitter,s) + local v = variables[key] + if v then + t[v] = true + if detail then + local k = fractions[key] + if k then + detail = tonumber("0" .. detail) + if detail then + t[k] = detail + end + else + k = values[key] if k then - detail = tonumber("0" .. detail) + detail = todimen(detail) if detail then t[k] = detail end - else - k = values[key] - if k then - detail = todimen(detail) - if detail then - t[k] = detail - end - end end end - else - detail = tonumber("0" .. key) - if detail then - t[v_hfraction] = detail - t[v_dfraction] = detail - end end - end - if next(t) then - t[v_hfraction] = t[v_hfraction] or 1 - t[v_dfraction] = t[v_dfraction] or 1 - return t else - return default + detail = tonumber("0" .. key) + if detail then + t[v_hfraction] = detail + t[v_dfraction] = detail + end end end - - function vspacing.definesnapmethod(name,method) - local n = #snapmethods + 1 - local t = listtohash(method) - snapmethods[n] = t - t.name = name -- not interfaced - t.specification = method -- not interfaced - context(n) + if next(t) then + t[v_hfraction] = t[v_hfraction] or 1 + t[v_dfraction] = t[v_dfraction] or 1 + return t + else + return default end +end +function vspacing.definesnapmethod(name,method) + local n = #snapmethods + 1 + local t = listtohash(method) + snapmethods[n] = t + t.name = name -- not interfaced + t.specification = method -- not interfaced + context(n) end local function validvbox(parentid,list) if parentid == hlist_code then local id = getid(list) - if id == localpar_code and getsubtype(list) == 0 then + if id == localpar_code then -- check for initial par subtype list = getnext(list) if not next then return nil end end local done = nil - for n, id in nextnode, list do + for n in traverse_nodes(list) do + local id = getid(n) if id == vlist_code or id == hlist_code then if done then return nil @@ -326,13 +320,14 @@ local function already_done(parentid,list,a_snapmethod) -- todo: done when only -- problem: any snapped vbox ends up in a line if list and parentid == hlist_code then local id = getid(list) - if id == localpar_code and getsubtype(list) == 0 then + if id == localpar_code then -- check for initial par subtype list = getnext(list) if not list then return false end end - for n, id in nextnode, list do + for n in traverse_nodes(list) do + local id = getid(n) if id == hlist_code or id == vlist_code then -- local a = getattr(n,a_snapmethod) -- if not a then @@ -541,7 +536,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 nexthlist, list do + for n in traverse_nodes_id(hlist_code,list) do lw, lh, ld = getwhd(n) break end @@ -577,7 +572,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 nexthlist, list do + for n in traverse_nodes_id(hlist_code,list) do lw, lh, ld = getwhd(n) end if lh then @@ -877,15 +872,14 @@ end local trace_list, tracing_info, before, after = { }, false, "", "" local function nodes_to_string(head) - local current = head - local t = { } + local current, t = head, { } while current do local id = getid(current) local ty = nodecodes[id] if id == penalty_code then t[#t+1] = formatters["%s:%s"](ty,getpenalty(current)) elseif id == glue_code then - t[#t+1] = formatters["%s:%s:%p"](ty,gluecodes[getsubtype(current)],getwidth(current)) + t[#t+1] = formatters["%s:%s:%p"](ty,skipcodes[getsubtype(current)],getwidth(current)) elseif id == kern_code then t[#t+1] = formatters["%s:%p"](ty,getkern(current)) else @@ -1267,26 +1261,17 @@ do if trace then reset_tracing(head) end - local current = head - local oldhead = head - local glue_order = 0 - local glue_data - local force_glue = false - local penalty_order = 0 - local penalty_data - local natural_penalty - local special_penalty - local parskip - local ignore_parskip = false - local ignore_following = false - local ignore_whitespace = false - local keep_together = false - local lastsnap - local pagehead - local pagetail + local current, oldhead = head, head + local glue_order, glue_data, force_glue = 0, nil, false + local penalty_order, penalty_data, natural_penalty, special_penalty = 0, nil, nil, nil + local parskip, ignore_parskip, ignore_following, ignore_whitespace, keep_together = nil, false, false, false, false + local lastsnap = nil -- -- todo: keep_together: between headers -- + local pagehead = nil + local pagetail = nil + local function getpagelist() if not pagehead then pagehead = texlists.page_head @@ -1411,7 +1396,7 @@ do end head = insert_node_before(head,current,glue_data) else - -- report_vspacing("needs checking (%s): %p",gluecodes[getsubtype(glue_data)],w) + -- report_vspacing("needs checking (%s): %p",skipcodes[getsubtype(glue_data)],w) flush_node(glue_data) end end @@ -1829,7 +1814,7 @@ do if snap and trace_vsnapping then local w = getwidth(current) if w ~= 0 then - report_snapper("glue %p of type %a kept",w,gluecodes[subtype]) + report_snapper("glue %p of type %a kept",w,skipcodes[subtype]) end end if trace then @@ -1896,7 +1881,7 @@ do trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)]) end end - return head + return head, true end -- alignment after_output end box new_graf vmode_par hmode_par insert penalty before_display after_display @@ -1924,47 +1909,43 @@ do -- ugly code: we get partial lists (check if this stack is still okay) ... and we run -- into temp nodes (sigh) - local forceflush = false - 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, subtype in nextnode, newhead do -- we could just look for glue nodes + for n in traverse_nodes(newhead) do -- we could just look for glue nodes + local id = getid(n) if id ~= glue_code then flush = true - 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 + 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 end end end texsetcount("c_spac_vspacing_ignore_parskip",0) - - if forceflush then - forceflush = false - flush = true - end - if flush then if stackhead then if trace_collect_vspacing then report("%s > appending %s nodes to stack (final): %s",where,newhead) end setlink(stacktail,newhead) - newhead = stackhead - stackhead = nil - stacktail = nil + newhead = stackhead + stackhead, stacktail = nil, nil end if stackhack then stackhack = false @@ -1975,7 +1956,7 @@ do if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end -- texlists.contrib_head = newhead end - return newhead + return tonode(newhead) else if stackhead then if trace_collect_vspacing then report("%s > appending %s nodes to stack (intermediate): %s",where,newhead) end @@ -1985,43 +1966,13 @@ do stackhead = newhead end stacktail = newtail + -- texlists.contrib_head = nil + -- newhead = nil end end return nil end - -- function vspacing.flushpagestack() - -- if stackhead then - -- local head = texlists.contrib_head - -- if head then - -- local tail = find_node_tail(head) - -- setlink(tail,stackhead) - -- else - -- texlists.contrib_head = tonode(stackhead) - -- end - -- stackhead, stacktail = nil, nil - -- end - -- - -- end - - function vspacing.pageoverflow() - local h = 0 - if stackhead then - for n, id in nextnode, stackhead do - if id == glue_code then - h = h + getwidth(n) - elseif id == kern_code then - h = h + getkern(n) - end - end - end - return h - end - - function vspacing.forcepageflush() - forceflush = true - end - local ignore = table.tohash { "split_keep", "split_off", @@ -2029,10 +1980,11 @@ do } function vspacing.vboxhandler(head,where) - 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 + 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) end end return head @@ -2063,6 +2015,7 @@ do local outer = texnest[0] local enabled = true + local count = true local trace = false local report = logs.reporter("vspacing") @@ -2071,84 +2024,96 @@ do end) directives.register("vspacing.synchronizepage",function(v) - enabled = v + if v == true or v == "count" then + enabled = true + count = true + elseif v == "first" then + enabled = true + count = false + else + enabled = false + count = false + end end) - local ignoredepth = -65536000 + -- hm, check the old one - -- A previous version analyzed the number of lines moved to the next page in - -- synchronizepage because prevgraf is unreliable in that case. However, we cannot - -- tweak that parameter because it is also used in postlinebreak and hangafter, so - -- there is a danger for interference. Therefore we now do it dynamically. + -- function vspacing.synchronizepage() + -- if enabled then + -- local head = texlists.hold_head + -- local skip = 0 + -- while head and head.id == insert_code do + -- head = head.next + -- skip = skip + 1 + -- end + -- if head then + -- outer.prevdepth = 0 + -- end + -- if trace then + -- report("prevdepth %s at page %i, skipped %i, value %p", + -- head and "reset" or "kept",texgetcount("realpageno"),skip,outer.prevdepth) + -- end + -- end + -- end - -- We can also support other lists but there prevgraf probably is ok. + local ignoredepth = -65536000 - function vspacing.getnofpreviouslines(head) + function vspacing.synchronizepage() if enabled then - if not thead then - head = texlists.page_head - end - local noflines = 0 + local newdepth = outer.prevdepth + local olddepth = newdepth + local oldlines = outer.prevgraf + local newlines = 0 + local boxfound = false + local head = texlists.contrib_head if head then local tail = find_node_tail(tonut(head)) while tail do local id = getid(tail) if id == hlist_code then - if getsubtype(tail) == linelist_code then - noflines = noflines + 1 - else + if not boxfound then + newdepth = getdepth(tail) + boxfound = true + end + newlines = newlines + 1 + if not count then break end elseif id == vlist_code then + if not boxfound then + newdepth = getdepth(tail) + boxfound = true + end break elseif id == glue_code then local subtype = getsubtype(tail) - if subtype == baselineskip_code or subtype == lineskip_code then - -- we're ok - elseif subtype == parskip_code then - if getwidth(tail) > 0 then - break - else - -- we assume we're ok - end + if not (subtype == baselineskip_code or subtype == lineskip_code) then + break + elseif boxfound and not count then + break end elseif id == penalty_code then - -- we're probably ok - elseif id == rule_code or id == kern_code then - break + if boxfound and not count then + break + end else - -- ins, mark, boundary, whatsit + -- ins, mark, kern, rule, boundary, whatsit + break end tail = getprev(tail) end end - return noflines - end - end - - interfaces.implement { - name = "getnofpreviouslines", - public = true, - actions = vspacing.getnofpreviouslines, - } - - function vspacing.synchronizepage() - if enabled then - if trace then - local newdepth = outer.prevdepth - local olddepth = newdepth - if not texlists.page_head then - newdepth = ignoredepth - texset("prevdepth",ignoredepth) - outer.prevdepth = ignoredepth - end - report("page %i, prevdepth %p => %p",texgetcount("realpageno"),olddepth,newdepth) - -- report("list %s",nodes.idsandsubtypes(head)) + if boxfound then + -- what if newdepth ... else - if not texlists.page_head then - texset("prevdepth",ignoredepth) - outer.prevdepth = ignoredepth - end + texset("prevdepth",ignoredepth) + outer.prevdepth = ignoredepth + end + texset("prevgraf", newlines) + outer.prevgraf = newlines + if trace then + report("page %i, prevdepth %p (last depth %p), prevgraf %i (from %i), %sboxes", + texgetcount("realpageno"),olddepth,newdepth,oldlines,newlines,boxfound and "" or "no ") end end end @@ -2261,7 +2226,7 @@ do -- end -- } - implement { + interfaces.implement { name = "removelastline", actions = function() local head = texlists.page_head @@ -2277,7 +2242,7 @@ do end } - implement { + interfaces.implement { name = "showpagelist", -- will improve actions = function() local head = texlists.page_head @@ -2291,14 +2256,4 @@ do end } - implement { - name = "pageoverflow", - actions = { vspacing.pageoverflow, context } - } - - implement { - name = "forcepageflush", - actions = vspacing.forcepageflush - } - end |