diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/spac-ver.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/spac-ver.lua | 802 |
1 files changed, 402 insertions, 400 deletions
diff --git a/Master/texmf-dist/tex/context/base/spac-ver.lua b/Master/texmf-dist/tex/context/base/spac-ver.lua index 66698a49e91..7d030ab1ac2 100644 --- a/Master/texmf-dist/tex/context/base/spac-ver.lua +++ b/Master/texmf-dist/tex/context/base/spac-ver.lua @@ -22,14 +22,14 @@ if not modules then modules = { } end modules ['spac-ver'] = { -- todo: strip baselineskip around display math local next, type, tonumber = next, type, tonumber -local format, gmatch, concat, match, rep = string.format, string.gmatch, table.concat, string.match, string.rep +local gmatch, concat = string.gmatch, table.concat local ceil, floor, max, min, round, abs = math.ceil, math.floor, math.max, math.min, math.round, math.abs local texlists, texdimen, texbox = tex.lists, tex.dimen, tex.box local lpegmatch = lpeg.match local unpack = unpack or table.unpack -local points = number.points local allocate = utilities.storage.allocate local todimen = string.todimen +local formatters = string.formatters local P, C, R, S, Cc = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc @@ -42,16 +42,18 @@ local stoptiming = statistics.stoptiming -- vertical space handler -local trace_vbox_vspacing = false trackers.register("builders.vbox_vspacing", function(v) trace_vbox_vspacing = v end) -local trace_page_vspacing = false trackers.register("builders.page_vspacing", function(v) trace_page_vspacing = v end) -local trace_collect_vspacing = false trackers.register("builders.collect_vspacing", function(v) trace_collect_vspacing = v end) -local trace_vspacing = false trackers.register("builders.vspacing", function(v) trace_vspacing = v end) -local trace_vsnapping = false trackers.register("builders.vsnapping", function(v) trace_vsnapping = v end) -local trace_vpacking = false trackers.register("builders.vpacking", function(v) trace_vpacking = v end) +local trace_vbox_vspacing = false trackers.register("vspacing.vbox", function(v) trace_vbox_vspacing = v end) +local trace_page_vspacing = false trackers.register("vspacing.page", function(v) trace_page_vspacing = v end) +local trace_page_builder = false trackers.register("builders.page", function(v) trace_page_builder = v end) +local trace_collect_vspacing = false trackers.register("vspacing.collect", function(v) trace_collect_vspacing = v end) +local trace_vspacing = false trackers.register("vspacing.spacing", function(v) trace_vspacing = v end) +local trace_vsnapping = false trackers.register("vspacing.snapping", function(v) trace_vsnapping = v end) +local trace_vpacking = false trackers.register("vspacing.packing", function(v) trace_vpacking = v end) local report_vspacing = logs.reporter("vspacing","spacing") local report_collapser = logs.reporter("vspacing","collapsing") local report_snapper = logs.reporter("vspacing","snapping") +local report_page_builder = logs.reporter("builders","page") local a_skipcategory = attributes.private('skipcategory') local a_skippenalty = attributes.private('skippenalty') @@ -60,11 +62,9 @@ local a_skiporder = attributes.private('skiporder') local a_snapmethod = attributes.private('snapmethod') local a_snapvbox = attributes.private('snapvbox') -local has_attribute = node.has_attribute -local unset_attribute = node.unset_attribute -local set_attribute = node.set_attribute local find_node_tail = node.tail local free_node = node.free +local free_node_list = node.flush_list local copy_node = node.copy local traverse_nodes = node.traverse local traverse_nodes_id = node.traverse_id @@ -98,12 +98,14 @@ local whatsit_code = nodecodes.whatsit local userskip_code = skipcodes.userskip -builders.vspacing = builders.vspacing or { } -local vspacing = builders.vspacing -vspacing.data = vspacing.data or { } +local vspacing = builders.vspacing or { } +builders.vspacing = vspacing -vspacing.data.snapmethods = vspacing.data.snapmethods or { } -local snapmethods = vspacing.data.snapmethods --maybe some older code can go +local vspacingdata = vspacing.data or { } +vspacing.data = vspacingdata + +vspacingdata.snapmethods = vspacingdata.snapmethods or { } +local snapmethods = vspacingdata.snapmethods --maybe some older code can go storage.register("builders/vspacing/data/snapmethods", snapmethods, "builders.vspacing.data.snapmethods") @@ -175,16 +177,16 @@ function vspacing.definesnapmethod(name,method) context(n) end ---~ local rule_id = nodecodes.rule ---~ local vlist_id = nodecodes.vlist ---~ function nodes.makevtop(n) ---~ if n.id == vlist_id then ---~ local list = n.list ---~ local height = (list and list.id <= rule_id and list.height) or 0 ---~ n.depth = n.depth - height + n.height ---~ n.height = height ---~ end ---~ end +-- local rule_id = nodecodes.rule +-- local vlist_id = nodecodes.vlist +-- function nodes.makevtop(n) +-- if n.id == vlist_id then +-- local list = n.list +-- local height = (list and list.id <= rule_id and list.height) or 0 +-- n.depth = n.depth - height + n.height +-- n.height = height +-- end +-- end local reference = nodes.reference @@ -206,14 +208,17 @@ local function validvbox(parentid,list) else done = n end - elseif id == penalty_code or id == glue_code then + elseif id == glue_code or id == penalty_code then -- go on else return nil -- whatever end end - if done and done.id == hlist_code then - return validvbox(done.id,done.list) + if done then + local id = done.id + if id == hlist_code then + return validvbox(id,done.list) + end end return done -- only one vbox end @@ -232,15 +237,15 @@ local function already_done(parentid,list,a_snapmethod) -- todo: done when only --~ local i = 0 for n in traverse_nodes(list) do local id = n.id ---~ i = i + 1 print(i,nodecodes[id],has_attribute(n,a_snapmethod)) +--~ i = i + 1 print(i,nodecodes[id],n[a_snapmethod]) if id == hlist_code or id == vlist_code then - local a = has_attribute(n,a_snapmethod) + local a = n[a_snapmethod] if not a then -- return true -- not snapped at all elseif a == 0 then return true -- already snapped end - elseif id == penalty_code or id == glue_code then -- whatsit is weak spot + elseif id == glue_code or id == penalty_code then -- whatsit is weak spot -- go on else return false -- whatever @@ -273,25 +278,24 @@ end local function snap_hlist(where,current,method,height,depth) -- method.strut is default local list = current.list ---~ print(table.serialize(method)) local t = trace_vsnapping and { } if t then - t[#t+1] = format("list content: %s",nodes.toutf(list)) - t[#t+1] = format("parent id: %s",reference(current)) - t[#t+1] = format("snap method: %s",method.name) - t[#t+1] = format("specification: %s",method.specification) + t[#t+1] = formatters["list content: %s"](nodes.toutf(list)) + t[#t+1] = formatters["parent id: %s"](reference(current)) + t[#t+1] = formatters["snap method: %s"](method.name) + t[#t+1] = formatters["specification: %s"](method.specification) end local snapht, snapdp if method["local"] then -- snapping is done immediately here snapht, snapdp = texdimen.bodyfontstrutheight, texdimen.bodyfontstrutdepth if t then - t[#t+1] = format("local: snapht %s snapdp %s",points(snapht),points(snapdp)) + t[#t+1] = formatters["local: snapht %p snapdp %p"](snapht,snapdp) end elseif method["global"] then snapht, snapdp = texdimen.globalbodyfontstrutheight, texdimen.globalbodyfontstrutdepth if t then - t[#t+1] = format("global: snapht %s snapdp %s",points(snapht),points(snapdp)) + t[#t+1] = formatters["global: snapht %p snapdp %p"](snapht,snapdp) end else -- maybe autolocal @@ -302,7 +306,7 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is snapht, snapdp = lsnapht, lsnapdp end if t then - t[#t+1] = format("auto: snapht %s snapdp %s",points(snapht),points(snapdp)) + t[#t+1] = formatters["auto: snapht %p snapdp %p"](snapht,snapdp) end end local h, d = height or current.height, depth or current.depth @@ -314,19 +318,19 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is if method.none then plusht, plusdp = 0, 0 if t then - t[#t+1] = format("none: plusht 0pt plusdp 0pt") + t[#t+1] = "none: plusht 0pt plusdp 0pt" end end if method.halfline then -- extra halfline plusht, plusdp = plusht + snaphtdp/2, plusdp + snaphtdp/2 if t then - t[#t+1] = format("halfline: plusht %s plusdp %s",points(plusht),points(plusdp)) + t[#t+1] = formatters["halfline: plusht %p plusdp %p"](plusht,plusdp) end end if method.line then -- extra line plusht, plusdp = plusht + snaphtdp, plusdp + snaphtdp if t then - t[#t+1] = format("line: plusht %s plusdp %s",points(plusht),points(plusdp)) + t[#t+1] = formatters["line: plusht %p plusdp %p"](plusht,plusdp) end end @@ -346,20 +350,18 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is if lh then local ht, dp = thebox.height, thebox.depth if t then - t[#t+1] = format("first line: height %s depth %s",points(lh),points(ld)) - t[#t+1] = format("dimensions: height %s depth %s",points(ht),points(dp)) + t[#t+1] = formatters["first line: height %p depth %p"](lh,ld) + t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) end local delta = h - lh ch, cd = lh, delta + d ---~ ch = ch + plusht ---~ cd = cd + plusdp -h, d = ch, cd + h, d = ch, cd local shifted = hpack_node(current.list) shifted.shift = delta current.list = shifted done = true if t then - t[#t+1] = format("first: height %s depth %s shift %s",points(ch),points(cd),points(delta)) + t[#t+1] = formatters["first: height %p depth %p shift %p"](ch,cd,delta) end elseif t then t[#t+1] = "first: not done, no content" @@ -382,20 +384,18 @@ h, d = ch, cd if lh then local ht, dp = thebox.height, thebox.depth if t then - t[#t+1] = format("last line: height %s depth %s",points(lh),points(ld)) - t[#t+1] = format("dimensions: height %s depth %s",points(ht),points(dp)) + t[#t+1] = formatters["last line: height %p depth %p" ](lh,ld) + t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) end local delta = d - ld cd, ch = ld, delta + h ---~ ch = ch + plusht ---~ cd = cd + plusdp -h, d = ch, cd + h, d = ch, cd local shifted = hpack_node(current.list) shifted.shift = delta current.list = shifted done = true if t then - t[#t+1] = format("last: height %s depth %s shift %s",points(ch),points(cd),points(delta)) + t[#t+1] = formatters["last: height %p depth %p shift %p"](ch,cd,delta) end elseif t then t[#t+1] = "last: not done, no content" @@ -404,59 +404,48 @@ h, d = ch, cd t[#t+1] = "last: not done, no vbox" end end - ---~ if done then ---~ -- first or last ---~ else if method.minheight then - -- ch = max(floor((h-hr*snapht)/snaphtdp),0)*snaphtdp + plusht ch = floored((h-hr*snapht)/snaphtdp)*snaphtdp + plusht if t then - t[#t+1] = format("minheight: %s",points(ch)) + t[#t+1] = formatters["minheight: %p"](ch) end elseif method.maxheight then - -- ch = max(ceil((h-hr*snapht)/snaphtdp),0)*snaphtdp + plusht ch = ceiled((h-hr*snapht)/snaphtdp)*snaphtdp + plusht if t then - t[#t+1] = format("maxheight: %s",points(ch)) + t[#t+1] = formatters["maxheight: %p"](ch) end else ch = plusht if t then - t[#t+1] = format("set height: %s",points(ch)) + t[#t+1] = formatters["set height: %p"](ch) end end ---~ if done then ---~ -- first or last ---~ else if method.mindepth then - -- cd = max(floor((d-dr*snapdp)/snaphtdp),0)*snaphtdp + plusdp cd = floored((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp if t then - t[#t+1] = format("mindepth: %s",points(cd)) + t[#t+1] = formatters["mindepth: %p"](cd) end elseif method.maxdepth then - -- cd = max(ceil((d-dr*snapdp)/snaphtdp),0)*snaphtdp + plusdp cd = ceiled((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp if t then - t[#t+1] = format("maxdepth: %s",points(cd)) + t[#t+1] = formatters["maxdepth: %p"](cd) end else cd = plusdp if t then - t[#t+1] = format("set depth: %s",points(cd)) + t[#t+1] = formatters["set depth: %p"](cd) end end if method.top then ch = ch + tlines * snaphtdp if t then - t[#t+1] = format("top height: %s",points(ch)) + t[#t+1] = formatters["top height: %p"](ch) end end if method.bottom then cd = cd + blines * snaphtdp if t then - t[#t+1] = format("bottom depth: %s",points(cd)) + t[#t+1] = formatters["bottom depth: %p"](cd) end end @@ -464,41 +453,39 @@ h, d = ch, cd if offset then -- we need to set the attr if t then - t[#t+1] = format("before offset: %s (width %s height %s depth %s)", - points(offset),points(current.width),points(current.height),points(current.depth)) + t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,current.width,current.height,current.depth) end local shifted = hpack_node(current.list) shifted.shift = offset current.list = shifted if t then - t[#t+1] = format("after offset: %s (width %s height %s depth %s)", - points(offset),points(current.width),points(current.height),points(current.depth)) + t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,current.width,current.height,current.depth) end - set_attribute(shifted,a_snapmethod,0) - set_attribute(current,a_snapmethod,0) + shifted[a_snapmethod] = 0 + current[a_snapmethod] = 0 end if not height then current.height = ch if t then - t[#t+1] = format("forced height: %s",points(ch)) + t[#t+1] = formatters["forced height: %p"](ch) end end if not depth then current.depth = cd if t then - t[#t+1] = format("forced depth: %s",points(cd)) + t[#t+1] = formatters["forced depth: %p"](cd) end end local lines = (ch+cd)/snaphtdp if t then local original = (h+d)/snaphtdp local whatever = (ch+cd)/(texdimen.globalbodyfontstrutheight + texdimen.globalbodyfontstrutdepth) - t[#t+1] = format("final lines: %s -> %s (%s)",original,lines,whatever) - t[#t+1] = format("final height: %s -> %s",points(h),points(ch)) - t[#t+1] = format("final depth: %s -> %s",points(d),points(cd)) + t[#t+1] = formatters["final lines: %s -> %s (%s)"](original,lines,whatever) + t[#t+1] = formatters["final height: %p -> %p"](h,ch) + t[#t+1] = formatters["final depth: %p -> %p"](d,cd) end if t then - report_snapper("trace: %s type %s\n\t%s",where,nodecodes[current.id],concat(t,"\n\t")) + report_snapper("trace: %s type %s\n\t%\n\tt",where,nodecodes[current.id],t) end return h, d, ch, cd, lines end @@ -548,18 +535,18 @@ function vspacing.tocategory(str) end end -vspacing.data.map = vspacing.data.map or { } -- allocate ? -vspacing.data.skip = vspacing.data.skip or { } -- allocate ? +vspacingdata.map = vspacingdata.map or { } -- allocate ? +vspacingdata.skip = vspacingdata.skip or { } -- allocate ? -storage.register("builders/vspacing/data/map", vspacing.data.map, "builders.vspacing.data.map") -storage.register("builders/vspacing/data/skip", vspacing.data.skip, "builders.vspacing.data.skip") +storage.register("builders/vspacing/data/map", vspacingdata.map, "builders.vspacing.data.map") +storage.register("builders/vspacing/data/skip", vspacingdata.skip, "builders.vspacing.data.skip") do -- todo: interface.variables vspacing.fixed = false - local map = vspacing.data.map - local skip = vspacing.data.skip + local map = vspacingdata.map + local skip = vspacingdata.skip local multiplier = C(S("+-")^0 * R("09")^1) * P("*") local category = P(":") * C(P(1)^1) @@ -571,45 +558,55 @@ do -- todo: interface.variables -- This will change: just node.write and we can store the values in skips which -- then obeys grouping + local fixedblankskip = context.fixedblankskip + local flexibleblankskip = context.flexibleblankskip + local setblankcategory = context.setblankcategory + local setblankorder = context.setblankorder + local setblankpenalty = context.setblankpenalty + local setblankhandling = context.setblankhandling + local flushblankhandling = context.flushblankhandling + local addpredefinedblankskip = context.addpredefinedblankskip + local addaskedblankskip = context.addaskedblankskip + local function analyze(str,oldcategory) -- we could use shorter names for s in gmatch(str,"([^ ,]+)") do local amount, keyword, detail = lpegmatch(splitter,s) -- the comma splitter can be merged if not keyword then - report_vspacing("unknown directive: %s",s) + report_vspacing("unknown directive %a",s) else local mk = map[keyword] if mk then category = analyze(mk,category) elseif keyword == k_fixed then - context.fixedblankskip() + fixedblankskip() elseif keyword == k_flexible then - context.flexibleblankskip() + flexibleblankskip() elseif keyword == k_category then local category = tonumber(detail) if category then - context.setblankcategory(category) + setblankcategory(category) if category ~= oldcategory then - context.flushblankhandling() + flushblankhandling() oldcategory = category end end elseif keyword == k_order and detail then local order = tonumber(detail) if order then - context.setblankorder(order) + setblankorder(order) end elseif keyword == k_penalty and detail then local penalty = tonumber(detail) if penalty then - context.setblankpenalty(penalty) + setblankpenalty(penalty) end else amount = tonumber(amount) or 1 local sk = skip[keyword] if sk then - context.addpredefinedblankskip(amount,keyword) + addpredefinedblankskip(amount,keyword) else -- no check - context.addaskedblankskip(amount,keyword) + addaskedblankskip(amount,keyword) end end end @@ -617,15 +614,22 @@ do -- todo: interface.variables return category end + local pushlogger = context.pushlogger + local startblankhandling = context.startblankhandling + local stopblankhandling = context.stopblankhandling + local poplogger = context.poplogger + function vspacing.analyze(str) if trace_vspacing then - context.pushlogger(report_vspacing) - end - context.startblankhandling() - analyze(str,1) - context.stopblankhandling() - if trace_vspacing then - context.poplogger() + pushlogger(report_vspacing) + startblankhandling() + analyze(str,1) + stopblankhandling() + poplogger() + else + startblankhandling() + analyze(str,1) + stopblankhandling() end end @@ -646,43 +650,19 @@ end -- implementation ---~ nodes.snapvalues = { } - ---~ function nodes.setsnapvalue(n,ht,dp) ---~ nodes.snapvalues[n] = { ht, dp, ht+dp } ---~ end - local trace_list, tracing_info, before, after = { }, false, "", "" -local stripzeros, topoints = utilities.formatters.stripzeros, number.topoints - -local function glue_to_string(glue) - local spec = glue.spec - local t = { points(spec.width) } - if spec.stretch_order and spec.stretch_order ~= 0 then - t[#t+1] = format("plus %s%s",spec.stretch/65536,fillcodes[spec.stretch_order]) - elseif spec.stretch and spec.stretch ~= 0 then - t[#t+1] = format("plus %s",stripzeros(topoints(spec.stretch))) - end - if spec.shrink_order and spec.shrink_order ~= 0 then - t[#t+1] = format("minus %s%s",spec.shrink/65536,fillcodes[spec.shrink_order]) - elseif spec.shrink and spec.shrink ~= 0 then - t[#t+1] = format("minus %s",stripzeros(topoints(spec.shrink))) - end - return concat(t," ") -end - local function nodes_to_string(head) local current, t = head, { } while current do local id = current.id local ty = nodecodes[id] if id == penalty_code then - t[#t+1] = format("%s:%s",ty,current.penalty) - elseif id == glue_code then - t[#t+1] = format("%s:%s",ty,glue_to_string(current)) -- stripzeros(topoints(current.spec.width))) + t[#t+1] = formatters["%s:%s"](ty,current.penalty) + elseif id == glue_code then -- or id == kern_code then -- to be tested + t[#t+1] = formatters["%s:%p"](ty,current) elseif id == kern_code then - t[#t+1] = format("%s:%s",ty,stripzeros(topoints(current.kern))) + t[#t+1] = formatters["%s:%p"](ty,current.kern) else t[#t+1] = ty end @@ -696,24 +676,24 @@ local function reset_tracing(head) end local function trace_skip(str,sc,so,sp,data) - trace_list[#trace_list+1] = { "skip", format("%s | %s | category %s | order %s | penalty %s", str, glue_to_string(data), sc or "-", so or "-", sp or "-") } + trace_list[#trace_list+1] = { "skip", formatters["%s | %p | category %s | order %s | penalty %s"](str, data, sc or "-", so or "-", sp or "-") } tracing_info = true end local function trace_natural(str,data) - trace_list[#trace_list+1] = { "skip", format("%s | %s", str, glue_to_string(data)) } + trace_list[#trace_list+1] = { "skip", formatters["%s | %p"](str, data) } tracing_info = true end local function trace_info(message, where, what) - trace_list[#trace_list+1] = { "info", format("%s: %s/%s",message,where,what) } + trace_list[#trace_list+1] = { "info", formatters["%s: %s/%s"](message,where,what) } end local function trace_node(what) local nt = nodecodes[what.id] local tl = trace_list[#trace_list] if tl and tl[1] == "node" then - trace_list[#trace_list] = { "node", tl[2] .. " + " .. nt } + trace_list[#trace_list] = { "node", formatters["%s + %s"](tl[2],nt) } else trace_list[#trace_list+1] = { "node", nt } end @@ -721,9 +701,9 @@ end local function trace_done(str,data) if data.id == penalty_code then - trace_list[#trace_list+1] = { "penalty", format("%s | %s", str, data.penalty) } + trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,data.penalty) } else - trace_list[#trace_list+1] = { "glue", format("%s | %s", str, glue_to_string(data)) } + trace_list[#trace_list+1] = { "glue", formatters["%s | %p"](str,data) } end tracing_info = true end @@ -762,14 +742,14 @@ local splittopskip_code = skipcodes.splittopskip local free_glue_node = free_node local discard, largest, force, penalty, add, disable, nowhite, goback, together = 0, 1, 2, 3, 4, 5, 6, 7, 8 ---~ local function free_glue_node(n) ---~ -- free_node(n.spec) ---~ print("before",n) ---~ logs.flush() ---~ free_node(n) ---~ print("after") ---~ logs.flush() ---~ end +-- local function free_glue_node(n) +-- -- free_node(n.spec) +-- print("before",n) +-- logs.flush() +-- free_node(n) +-- print("after") +-- logs.flush() +-- end function vspacing.snapbox(n,how) local sv = snapmethods[how] @@ -777,7 +757,7 @@ function vspacing.snapbox(n,how) local box = texbox[n] local list = box.list if list then - local s = has_attribute(list,a_snapmethod) + local s = list[a_snapmethod] if s == 0 then if trace_vsnapping then -- report_snapper("box list not snapped, already done") @@ -787,18 +767,18 @@ function vspacing.snapbox(n,how) if false then -- todo: already_done -- assume that the box is already snapped if trace_vsnapping then - report_snapper("box list already snapped at (%s,%s): %s", + report_snapper("box list already snapped at (%p,%p): %s", ht,dp,listtoutf(list)) end else local h, d, ch, cd, lines = snap_hlist("box",box,sv,ht,dp) box.height, box.depth = ch, cd if trace_vsnapping then - report_snapper("box list snapped from (%s,%s) to (%s,%s) using method '%s' (%s) for '%s' (%s lines): %s", + report_snapper("box list snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s", h,d,ch,cd,sv.name,sv.specification,"direct",lines,listtoutf(list)) end - set_attribute(box, a_snapmethod,0) -- - set_attribute(list,a_snapmethod,0) -- yes or no + box[a_snapmethod] = 0 -- + list[a_snapmethod] = 0 -- yes or no end end end @@ -818,11 +798,13 @@ local function forced_skip(head,current,width,where,trace) current = c end if trace then - report_vspacing("inserting forced skip of %s",width) + report_vspacing("inserting forced skip of %p",width) end return head, current end +-- penalty only works well when before skip + local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail if trace then reset_tracing(head) @@ -858,25 +840,25 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also parskip, ignore_parskip, ignore_following, ignore_whitespace = nil, false, false, false end if trace_vsnapping then - report_snapper("global ht/dp = %s/%s, local ht/dp = %s/%s", + report_snapper("global ht/dp = %p/%p, local ht/dp = %p/%p", texdimen.globalbodyfontstrutheight, texdimen.globalbodyfontstrutdepth, texdimen.bodyfontstrutheight, texdimen.bodyfontstrutdepth) end if trace then trace_info("start analyzing",where,what) end while current do - local id, subtype = current.id, current.subtype + local id = current.id if id == hlist_code or id == vlist_code then -- needs checking, why so many calls if snap then local list = current.list - local s = has_attribute(current,a_snapmethod) + local s = current[a_snapmethod] if not s then -- if trace_vsnapping then -- report_snapper("mvl list not snapped") -- end elseif s == 0 then if trace_vsnapping then - report_snapper("mvl %s not snapped, already done: %s",nodecodes[id],listtoutf(list)) + report_snapper("mvl %a not snapped, already done: %s",nodecodes[id],listtoutf(list)) end else local sv = snapmethods[s] @@ -886,19 +868,19 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also local ht, dp = current.height, current.depth -- assume that the box is already snapped if trace_vsnapping then - report_snapper("mvl list already snapped at (%s,%s): %s",ht,dp,listtoutf(list)) + report_snapper("mvl list already snapped at (%p,%p): %s",ht,dp,listtoutf(list)) end else local h, d, ch, cd, lines = snap_hlist("mvl",current,sv) if trace_vsnapping then - report_snapper("mvl %s snapped from (%s,%s) to (%s,%s) using method '%s' (%s) for '%s' (%s lines): %s", + report_snapper("mvl %a snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s", nodecodes[id],h,d,ch,cd,sv.name,sv.specification,where,lines,listtoutf(list)) end end elseif trace_vsnapping then - report_snapper("mvl %s not snapped due to unknown snap specification: %s",nodecodes[id],listtoutf(list)) + report_snapper("mvl %a not snapped due to unknown snap specification: %s",nodecodes[id],listtoutf(list)) end - set_attribute(current,a_snapmethod,0) + current[a_snapmethod] = 0 end else -- @@ -907,264 +889,265 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also flush("list") current = current.next elseif id == penalty_code then - --~ natural_penalty = current.penalty - --~ if trace then trace_done("removed penalty",current) end - --~ head, current = remove_node(head, current, true) + -- natural_penalty = current.penalty + -- if trace then trace_done("removed penalty",current) end + -- head, current = remove_node(head, current, true) current = current.next elseif id == kern_code then if snap and trace_vsnapping and current.kern ~= 0 then - --~ current.kern = 0 - report_snapper("kern of %s (kept)",current.kern) + report_snapper("kern of %p kept",current.kern) end flush("kern") current = current.next - elseif id ~= glue_code then - flush("something else") - current = current.next - elseif subtype == userskip_code then - local sc = has_attribute(current,a_skipcategory) -- has no default, no unset (yet) - local so = has_attribute(current,a_skiporder ) or 1 -- has 1 default, no unset (yet) - local sp = has_attribute(current,a_skippenalty ) -- has no default, no unset (yet) - if sp and sc == penalty then - if not penalty_data then - penalty_data = sp - elseif penalty_order < so then - penalty_order, penalty_data = so, sp - elseif penalty_order == so and sp > penalty_data then - penalty_data = sp - end - if trace then trace_skip('penalty in skip',sc,so,sp,current) end - head, current = remove_node(head, current, true) - elseif not sc then -- if not sc then - if glue_data then - if trace then trace_done("flush",glue_data) end - head = insert_node_before(head,current,glue_data) - if trace then trace_natural("natural",current) end - current = current.next - else - -- not look back across head - local previous = current.prev - if previous and previous.id == glue_code and previous.subtype == userskip_code then - local ps = previous.spec - if ps.writable then - local cs = current.spec - if cs.writable and ps.stretch_order == 0 and ps.shrink_order == 0 and cs.stretch_order == 0 and cs.shrink_order == 0 then - local pw, pp, pm = ps.width, ps.stretch, ps.shrink - local cw, cp, cm = cs.width, cs.stretch, cs.shrink ---~ ps = writable_spec(previous) -- no writable needed here ---~ ps.width, ps.stretch, ps.shrink = pw + cw, pp + cp, pm + cm -previous.spec = new_gluespec(pw + cw, pp + cp, pm + cm) -- else topskip can disappear - if trace then trace_natural("removed",current) end - head, current = remove_node(head, current, true) - -- current = previous - if trace then trace_natural("collapsed",previous) end - -- current = current.next + elseif id == glue_code then + local subtype = current.subtype + if subtype == userskip_code then + local sc = current[a_skipcategory] -- has no default, no unset (yet) + local so = current[a_skiporder] or 1 -- has 1 default, no unset (yet) + local sp = current[a_skippenalty] -- has no default, no unset (yet) + if sp and sc == penalty then + if not penalty_data then + penalty_data = sp + elseif penalty_order < so then + penalty_order, penalty_data = so, sp + elseif penalty_order == so and sp > penalty_data then + penalty_data = sp + end + if trace then trace_skip("penalty in skip",sc,so,sp,current) end + head, current = remove_node(head, current, true) + elseif not sc then -- if not sc then + if glue_data then + if trace then trace_done("flush",glue_data) end + head = insert_node_before(head,current,glue_data) + if trace then trace_natural("natural",current) end + current = current.next + else + -- not look back across head + local previous = current.prev + if previous and previous.id == glue_code and previous.subtype == userskip_code then + local ps = previous.spec + if ps.writable then + local cs = current.spec + if cs.writable and ps.stretch_order == 0 and ps.shrink_order == 0 and cs.stretch_order == 0 and cs.shrink_order == 0 then + local pw, pp, pm = ps.width, ps.stretch, ps.shrink + local cw, cp, cm = cs.width, cs.stretch, cs.shrink + -- ps = writable_spec(previous) -- no writable needed here + -- ps.width, ps.stretch, ps.shrink = pw + cw, pp + cp, pm + cm + previous.spec = new_gluespec(pw + cw, pp + cp, pm + cm) -- else topskip can disappear + if trace then trace_natural("removed",current) end + head, current = remove_node(head, current, true) + -- current = previous + if trace then trace_natural("collapsed",previous) end + -- current = current.next + else + if trace then trace_natural("filler",current) end + current = current.next + end else - if trace then trace_natural("filler",current) end + if trace then trace_natural("natural (no prev spec)",current) end current = current.next end else - if trace then trace_natural("natural (no prev spec)",current) end + if trace then trace_natural("natural (no prev)",current) end current = current.next end - else - if trace then trace_natural("natural (no prev)",current) end - current = current.next end - end - glue_order, glue_data = 0, nil - elseif sc == disable then - ignore_following = true - if trace then trace_skip("disable",sc,so,sp,current) end - head, current = remove_node(head, current, true) - elseif sc == together then - keep_together = true - if trace then trace_skip("together",sc,so,sp,current) end - head, current = remove_node(head, current, true) - elseif sc == nowhite then - ignore_whitespace = true - head, current = remove_node(head, current, true) - elseif sc == discard then - if trace then trace_skip("discard",sc,so,sp,current) end - head, current = remove_node(head, current, true) - elseif ignore_following then - if trace then trace_skip("disabled",sc,so,sp,current) end - head, current = remove_node(head, current, true) - elseif not glue_data then - if trace then trace_skip("assign",sc,so,sp,current) end - glue_order = so - head, current, glue_data = remove_node(head, current) - elseif glue_order < so then - if trace then trace_skip("force",sc,so,sp,current) end - glue_order = so - free_glue_node(glue_data) - head, current, glue_data = remove_node(head, current) - elseif glue_order == so then - -- is now exclusive, maybe support goback as combi, else why a set - if sc == largest then - local cs, gs = current.spec, glue_data.spec - local cw, gw = cs.width, gs.width - if cw > gw then - if trace then trace_skip('largest',sc,so,sp,current) end + glue_order, glue_data = 0, nil + elseif sc == disable then + ignore_following = true + if trace then trace_skip("disable",sc,so,sp,current) end + head, current = remove_node(head, current, true) + elseif sc == together then + keep_together = true + if trace then trace_skip("together",sc,so,sp,current) end + head, current = remove_node(head, current, true) + elseif sc == nowhite then + ignore_whitespace = true + head, current = remove_node(head, current, true) + elseif sc == discard then + if trace then trace_skip("discard",sc,so,sp,current) end + head, current = remove_node(head, current, true) + elseif ignore_following then + if trace then trace_skip("disabled",sc,so,sp,current) end + head, current = remove_node(head, current, true) + elseif not glue_data then + if trace then trace_skip("assign",sc,so,sp,current) end + glue_order = so + head, current, glue_data = remove_node(head, current) + elseif glue_order < so then + if trace then trace_skip("force",sc,so,sp,current) end + glue_order = so + free_glue_node(glue_data) + head, current, glue_data = remove_node(head, current) + elseif glue_order == so then + -- is now exclusive, maybe support goback as combi, else why a set + if sc == largest then + local cs, gs = current.spec, glue_data.spec + local cw, gw = cs.width, gs.width + if cw > gw then + if trace then trace_skip("largest",sc,so,sp,current) end + free_glue_node(glue_data) -- also free spec + head, current, glue_data = remove_node(head, current) + else + if trace then trace_skip("remove smallest",sc,so,sp,current) end + head, current = remove_node(head, current, true) + end + elseif sc == goback then + if trace then trace_skip("goback",sc,so,sp,current) end + free_glue_node(glue_data) -- also free spec + head, current, glue_data = remove_node(head, current) + elseif sc == force then + -- last one counts, some day we can provide an accumulator and largest etc + -- but not now + if trace then trace_skip("force",sc,so,sp,current) end free_glue_node(glue_data) -- also free spec head, current, glue_data = remove_node(head, current) + elseif sc == penalty then + if trace then trace_skip("penalty",sc,so,sp,current) end + free_glue_node(glue_data) -- also free spec + glue_data = nil + head, current = remove_node(head, current, true) + elseif sc == add then + if trace then trace_skip("add",sc,so,sp,current) end + -- local old, new = glue_data.spec, current.spec + local old, new = writable_spec(glue_data), current.spec + old.width = old.width + new.width + old.stretch = old.stretch + new.stretch + old.shrink = old.shrink + new.shrink + -- toto: order + head, current = remove_node(head, current, true) else - if trace then trace_skip('remove smallest',sc,so,sp,current) end + if trace then trace_skip("unknown",sc,so,sp,current) end head, current = remove_node(head, current, true) end - elseif sc == goback then - if trace then trace_skip('goback',sc,so,sp,current) end - free_glue_node(glue_data) -- also free spec - head, current, glue_data = remove_node(head, current) - elseif sc == force then - -- last one counts, some day we can provide an accumulator and largest etc - -- but not now - if trace then trace_skip('force',sc,so,sp,current) end - free_glue_node(glue_data) -- also free spec - head, current, glue_data = remove_node(head, current) - elseif sc == penalty then - -- ? ? ? ? - if trace then trace_skip('penalty',sc,so,sp,current) end - free_glue_node(glue_data) -- also free spec - glue_data = nil - head, current = remove_node(head, current, true) - elseif sc == add then - if trace then trace_skip('add',sc,so,sp,current) end - -- local old, new = glue_data.spec, current.spec - local old, new = writable_spec(glue_data), current.spec - old.width = old.width + new.width - old.stretch = old.stretch + new.stretch - old.shrink = old.shrink + new.shrink - -- toto: order - head, current = remove_node(head, current, true) else if trace then trace_skip("unknown",sc,so,sp,current) end head, current = remove_node(head, current, true) end - else - if trace then trace_skip("unknown",sc,so,sp,current) end - head, current = remove_node(head, current, true) - end - if sc == force then - force_glue = true - end - elseif subtype == lineskip_code then - if snap then - local s = has_attribute(current,a_snapmethod) - if s and s ~= 0 then - set_attribute(current,a_snapmethod,0) - if current.spec.writable then - local spec = writable_spec(current) - spec.width = 0 - if trace_vsnapping then - report_snapper("lineskip set to zero") + if sc == force then + force_glue = true + end + elseif subtype == lineskip_code then + if snap then + local s = current[a_snapmethod] + if s and s ~= 0 then + current[a_snapmethod] = 0 + if current.spec.writable then + local spec = writable_spec(current) + spec.width = 0 + if trace_vsnapping then + report_snapper("lineskip set to zero") + end end + else + if trace then trace_skip("lineskip",sc,so,sp,current) end + flush("lineskip") end else if trace then trace_skip("lineskip",sc,so,sp,current) end flush("lineskip") end - else - if trace then trace_skip("lineskip",sc,so,sp,current) end - flush("lineskip") - end - current = current.next - elseif subtype == baselineskip_code then - if snap then - local s = has_attribute(current,a_snapmethod) - if s and s ~= 0 then - set_attribute(current,a_snapmethod,0) - if current.spec.writable then - local spec = writable_spec(current) - spec.width = 0 - if trace_vsnapping then - report_snapper("baselineskip set to zero") + current = current.next + elseif subtype == baselineskip_code then + if snap then + local s = current[a_snapmethod] + if s and s ~= 0 then + current[a_snapmethod] = 0 + if current.spec.writable then + local spec = writable_spec(current) + spec.width = 0 + if trace_vsnapping then + report_snapper("baselineskip set to zero") + end end + else + if trace then trace_skip("baselineskip",sc,so,sp,current) end + flush("baselineskip") end else if trace then trace_skip("baselineskip",sc,so,sp,current) end flush("baselineskip") end - else - if trace then trace_skip("baselineskip",sc,so,sp,current) end - flush("baselineskip") - end - current = current.next - elseif subtype == parskip_code then - -- parskip always comes later - if ignore_whitespace then - if trace then trace_natural("ignored parskip",current) end - head, current = remove_node(head, current, true) - elseif glue_data then - local ps, gs = current.spec, glue_data.spec - if ps.writable and gs.writable and ps.width > gs.width then - glue_data.spec = copy_node(ps) - if trace then trace_natural("taking parskip",current) end + current = current.next + elseif subtype == parskip_code then + -- parskip always comes later + if ignore_whitespace then + if trace then trace_natural("ignored parskip",current) end + head, current = remove_node(head, current, true) + elseif glue_data then + local ps, gs = current.spec, glue_data.spec + if ps.writable and gs.writable and ps.width > gs.width then + glue_data.spec = copy_node(ps) + if trace then trace_natural("taking parskip",current) end + else + if trace then trace_natural("removed parskip",current) end + end + head, current = remove_node(head, current, true) else - if trace then trace_natural("removed parskip",current) end + if trace then trace_natural("honored parskip",current) end + head, current, glue_data = remove_node(head, current) end - head, current = remove_node(head, current, true) - else - if trace then trace_natural("honored parskip",current) end - head, current, glue_data = remove_node(head, current) - end - elseif subtype == topskip_code or subtype == splittopskip_code then - if snap then - local s = has_attribute(current,a_snapmethod) - if s and s ~= 0 then - set_attribute(current,a_snapmethod,0) - local sv = snapmethods[s] - local w, cw = snap_topskip(current,sv) - if trace_vsnapping then - report_snapper("topskip snapped from %s to %s for '%s'",w,cw,where) + elseif subtype == topskip_code or subtype == splittopskip_code then + if snap then + local s = current[a_snapmethod] + if s and s ~= 0 then + current[a_snapmethod] = 0 + local sv = snapmethods[s] + local w, cw = snap_topskip(current,sv) + if trace_vsnapping then + report_snapper("topskip snapped from %p to %p for %a",w,cw,where) + end + else + if trace then trace_skip("topskip",sc,so,sp,current) end + flush("topskip") end else if trace then trace_skip("topskip",sc,so,sp,current) end flush("topskip") end - else - if trace then trace_skip("topskip",sc,so,sp,current) end - flush("topskip") - end - current = current.next - elseif subtype == abovedisplayskip_code then - -- - if trace then trace_skip("above display skip (normal)",sc,so,sp,current) end - flush("above display skip (normal)") - current = current.next - -- - elseif subtype == belowdisplayskip_code then - -- - if trace then trace_skip("below display skip (normal)",sc,so,sp,current) end - flush("below display skip (normal)") - current = current.next - -- - elseif subtype == abovedisplayshortskip_code then - -- - if trace then trace_skip("above display skip (short)",sc,so,sp,current) end - flush("above display skip (short)") - current = current.next - -- - elseif subtype == belowdisplayshortskip_code then - -- - if trace then trace_skip("below display skip (short)",sc,so,sp,current) end - flush("below display skip (short)") - current = current.next - -- - else -- other glue - if snap and trace_vsnapping and current.spec.writable and current.spec.width ~= 0 then - report_snapper("%s of %s (kept)",skipcodes[subtype],current.spec.width) - --~ current.spec.width = 0 + current = current.next + elseif subtype == abovedisplayskip_code then + -- + if trace then trace_skip("above display skip (normal)",sc,so,sp,current) end + flush("above display skip (normal)") + current = current.next + -- + elseif subtype == belowdisplayskip_code then + -- + if trace then trace_skip("below display skip (normal)",sc,so,sp,current) end + flush("below display skip (normal)") + current = current.next + -- + elseif subtype == abovedisplayshortskip_code then + -- + if trace then trace_skip("above display skip (short)",sc,so,sp,current) end + flush("above display skip (short)") + current = current.next + -- + elseif subtype == belowdisplayshortskip_code then + -- + if trace then trace_skip("below display skip (short)",sc,so,sp,current) end + flush("below display skip (short)") + current = current.next + -- + else -- other glue + if snap and trace_vsnapping and current.spec.writable and current.spec.width ~= 0 then + report_snapper("glue %p of type %a kept",current.spec.width,skipcodes[subtype]) + --~ current.spec.width = 0 + end + if trace then trace_skip(formatted["glue of type %a"](subtype),sc,so,sp,current) end + flush("some glue") + current = current.next end - if trace then trace_skip(format("some glue (%s)",subtype),sc,so,sp,current) end - flush("some glue") + else + flush("something else") current = current.next end end if trace then trace_info("stop analyzing",where,what) end - --~ if natural_penalty and (not penalty_data or natural_penalty > penalty_data) then - --~ penalty_data = natural_penalty - --~ end + -- if natural_penalty and (not penalty_data or natural_penalty > penalty_data) then + -- penalty_data = natural_penalty + -- end if trace and (glue_data or penalty_data) then trace_info("start flushing",where,what) end @@ -1191,7 +1174,7 @@ previous.spec = new_gluespec(pw + cw, pp + cp, pm + cm) -- else topskip can disa end show_tracing(head) if oldhead ~= head then - trace_info("head has been changed from '%s' to '%s'",nodecodes[oldhead.id],nodecodes[head.id]) + trace_info("head has been changed from %a to %a",nodecodes[oldhead.id],nodecodes[head.id]) end end return head, true @@ -1216,24 +1199,21 @@ end function vspacing.pagehandler(newhead,where) -- local newhead = texlists.contrib_head if newhead then - -- starttiming(vspacing) - local newtail = find_node_tail(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 for n in traverse_nodes(newhead) do -- we could just look for glue nodes local id = n.id - if id == glue_code then - if n.subtype == userskip_code then - if has_attribute(n,a_skipcategory) then - stackhack = true - else - flush = true - end + if id ~= glue_code then + flush = true + elseif n.subtype == userskip_code then + if n[a_skipcategory] then + stackhack = true else - -- tricky + flush = true end else - flush = true + -- tricky end end if flush then @@ -1266,7 +1246,6 @@ function vspacing.pagehandler(newhead,where) -- texlists.contrib_head = nil newhead = nil end - -- stoptiming(vspacing) end return newhead end @@ -1316,28 +1295,51 @@ function builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direction) else nodes.processors.tracer("vpack","unchanged",head,groupcode,before,after,true) end - stoptiming(builders) else head, done = actions(head,groupcode) - stoptiming(builders) end + stoptiming(builders) end return head, done end --- This one is special in the sense that it has no head --- and we operate on the mlv. Also, we need to do the --- vspacing last as it removes items from the mvl. +-- This one is special in the sense that it has no head and we operate on the mlv. Also, +-- we need to do the vspacing last as it removes items from the mvl. local actions = nodes.tasks.actions("mvlbuilders") +local function report(groupcode,head) + report_page_builder("trigger: %s",groupcode) + report_page_builder(" vsize : %p",tex.vsize) + report_page_builder(" pagegoal : %p",tex.pagegoal) + report_page_builder(" pagetotal: %p",tex.pagetotal) + report_page_builder(" list : %s",head and nodeidstostring(head) or "<empty>") +end + function builders.buildpage_filter(groupcode) - starttiming(builders) - local head = texlists.contrib_head - local head, done = actions(head,groupcode) - texlists.contrib_head = head - stoptiming(builders) - return (done and head) or true + local head, done = texlists.contrib_head, false + -- if head and head.next and head.next.id == hlist_code and head.next.width == 1 then + -- report_page_builder("trigger otr calculations") + -- free_node_list(head) + -- head = nil + -- end + if head then + starttiming(builders) + if trace_page_builder then + report(groupcode,head) + end + head, done = actions(head,groupcode) + stoptiming(builders) + -- -- doesn't work here (not passed on?) + -- tex.pagegoal = tex.vsize - tex.dimen.d_page_floats_inserted_top - tex.dimen.d_page_floats_inserted_bottom + texlists.contrib_head = head + return done and head or true + else + if trace_page_builder then + report(groupcode) + end + return nil, false + end end callbacks.register('vpack_filter', builders.vpack_filter, "vertical spacing etc") |