summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/node-ltp.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/node-ltp.lua')
-rw-r--r--tex/context/base/mkiv/node-ltp.lua1537
1 files changed, 798 insertions, 739 deletions
diff --git a/tex/context/base/mkiv/node-ltp.lua b/tex/context/base/mkiv/node-ltp.lua
index ae17ab9ef..22a4799ad 100644
--- a/tex/context/base/mkiv/node-ltp.lua
+++ b/tex/context/base/mkiv/node-ltp.lua
@@ -21,6 +21,7 @@ if not modules then modules = { } end modules ['node-par'] = {
-- todo: check and improve protrusion
-- todo: arabic etc (we could use pretty large scales there) .. marks and cursive
-- todo: see: we need to check this with the latest patches to the tex kernel
+-- todo: adapt math glue spacing to new model (left/right)
-- todo: optimize a bit more (less par.*)
@@ -135,21 +136,20 @@ if not modules then modules = { } end modules ['node-par'] = {
local utfchar = utf.char
local write, write_nl = texio.write, texio.write_nl
-local sub, format = string.sub, string.format
+local sub, formatters = string.sub, string.formatters
local round, floor = math.round, math.floor
local insert, remove = table.insert, table.remove
-local fonts, nodes, node = fonts, nodes, node
+-- local fonts, nodes, node = fonts, nodes, node -- too many locals
local trace_basic = false trackers.register("builders.paragraphs.basic", function(v) trace_basic = v end)
local trace_lastlinefit = false trackers.register("builders.paragraphs.lastlinefit", function(v) trace_lastlinefit = v end)
local trace_adjusting = false trackers.register("builders.paragraphs.adjusting", function(v) trace_adjusting = v end)
local trace_protruding = false trackers.register("builders.paragraphs.protruding", function(v) trace_protruding = v end)
local trace_expansion = false trackers.register("builders.paragraphs.expansion", function(v) trace_expansion = v end)
-local trace_quality = false trackers.register("builders.paragraphs.quality", function(v) trace_quality = v end)
local report_parbuilders = logs.reporter("nodes","parbuilders")
-local report_hpackers = logs.reporter("nodes","hpackers")
+----- report_hpackers = logs.reporter("nodes","hpackers")
local calculate_badness = tex.badness
local texnest = tex.nest
@@ -185,7 +185,6 @@ local constructors = parbuilders.constructors
local setmetatableindex = table.setmetatableindex
local fonthashes = fonts.hashes
-local fontdata = fonthashes.identifiers
local chardata = fonthashes.characters
local quaddata = fonthashes.quads
local parameters = fonthashes.parameters
@@ -206,6 +205,16 @@ local getchar = nuts.getchar
local getdisc = nuts.getdisc
local getattr = nuts.getattr
local getdisc = nuts.getdisc
+local getglue = nuts.getglue
+local getwhd = nuts.getwhd
+local getcomponents = nuts.getcomponents
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local getdir = nuts.getdir
+local getshift = nuts.getshift
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
local isglyph = nuts.isglyph
@@ -217,22 +226,26 @@ local setnext = nuts.setnext
local setprev = nuts.setprev
local setdisc = nuts.setdisc
local setsubtype = nuts.setsubtype
-
-local slide_nodelist = nuts.slide -- get rid of this, probably ok > 78.2
+local setglue = nuts.setglue
+local setwhd = nuts.setwhd
+local setkern = nuts.setkern
+local setdir = nuts.setdir
+local setshift = nuts.setshift
+local setwidth = nuts.setwidth
+----- getheight = nuts.getheight
+----- getdepth = nuts.getdepth
+
+local slide_node_list = nuts.slide -- get rid of this, probably ok > 78.2
local find_tail = nuts.tail
-local new_node = nuts.new
local copy_node = nuts.copy
-local copy_nodelist = nuts.copy_list
-local flush_node = nuts.free
-local flush_nodelist = nuts.flush_list
-local hpack_nodes = nuts.hpack
+local flush_node = nuts.flush
+local flush_node_list = nuts.flush_list
+----- hpack_nodes = nuts.hpack
local xpack_nodes = nuts.hpack
local replace_node = nuts.replace
local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
-local traverse_by_id = nuts.traverse_id
-
-local setnodecolor = nodes.tracers.colors.set
+local is_zero_glue = nuts.is_zero_glue
local nodepool = nuts.pool
@@ -278,7 +291,7 @@ local ligature_code = glyphcodes.ligature
local stretch_orders = nodes.fillcodes
local leftmargin_code = margincodes.left
-local rightmargin_code = margincodes.right
+----- rightmargin_code = margincodes.right
local automatic_disc_code = disccodes.automatic
local regular_disc_code = disccodes.regular
@@ -318,6 +331,7 @@ local new_lineskip = nodepool.lineskip
local new_baselineskip = nodepool.baselineskip
local new_temp = nodepool.temp
local new_rule = nodepool.rule
+local new_hlist = nodepool.hlist
local is_rotated = nodes.is_rotated
local is_parallel = nodes.textdir_is_parallel
@@ -342,7 +356,7 @@ local function new_dir_stack(dir) -- also use elsewhere
end
-- The next function checks a dir node and returns the new dir state. By
--- using s static table we are quite efficient. This function is used
+-- using a static table we are quite efficient. This function is used
-- in the parbuilder.
local function checked_line_dir(stack,current)
@@ -350,12 +364,12 @@ local function checked_line_dir(stack,current)
local n = stack.n + 1
stack.n = n
stack[n] = current
- return getfield(current,"dir")
+ return getdir(current)
elseif n > 0 then
local n = stack.n
local dirnode = stack[n]
dirstack.n = n - 1
- return getfield(dirnode,"dir")
+ return getdir(dirnode)
else
report_parbuilders("warning: missing pop node (%a)",1) -- in line ...
end
@@ -372,7 +386,7 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop)
while start and start ~= stop do
local id = getid(start)
if id == dir_code then
- if not dir_pops[getfield(start,"dir")] then -- weird, what is this #
+ if not dir_pops[getdir(start)] then -- weird, what is this #
n = n + 1
stack[n] = start
elseif n > 0 then
@@ -384,7 +398,7 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop)
start = getnext(start)
end
for i=n,1,-1 do
- h, current = insert_node_after(current,current,new_dir(dir_negations[getfield(stack[i],"dir")]))
+ h, current = insert_node_after(current,current,new_dir(dir_negations[getdir(stack[i])]))
end
stack.n = n
return current
@@ -616,12 +630,16 @@ local function find(head) -- do we really want to recurse into an hlist?
else
head = getnext(head)
end
- elseif id == protrusion_code then
- local v = getfield(head,"value")
- if v == 1 or v == 3 then
- head = getnext(head)
- if head then
+ elseif id == boundary_code then
+ if getsubtype(head) == protrusion_code then
+ local v = getfield(head,"value")
+ if v == 1 or v == 3 then
head = getnext(head)
+ if head then
+ head = getnext(head)
+ end
+ else
+ return head
end
else
return head
@@ -666,12 +684,16 @@ local function find(head,tail)
else
tail = getprev(tail)
end
- elseif id == protrusion_code then
- local v = getfield(tail,"value")
- if v == 2 or v == 3 then
- tail = getprev(tail)
- if tail then
+ elseif id == boundary_code then
+ if getsubtype(head) == protrusion_code then
+ local v = getfield(tail,"value")
+ if v == 2 or v == 3 then
tail = getprev(tail)
+ if tail then
+ tail = getprev(tail)
+ end
+ else
+ return tail
end
else
return tail
@@ -726,10 +748,11 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
while s do
local char, id = isglyph(s)
if char then
+ local wd, ht, dp = getwhd(s)
if is_rotated[line_break_dir] then -- can be shared
- size = size + getfield(s,"height") + getfield(s,"depth")
+ size = size + ht + dp
else
- size = size + getfield(s,"width")
+ size = size + wd
end
if checked_expansion then
local data = checked_expansion[getfont(s)]
@@ -742,13 +765,14 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
end
end
elseif id == hlist_code or id == vlist_code then
- if is_parallel[getfield(s,"dir")][line_break_dir] then
- size = size + getfield(s,"width")
+ local wd, ht, dp = getwhd(s)
+ if is_parallel[getdir(s)][line_break_dir] then
+ size = size + wd
else
- size = size + getfield(s,"height") + getfield(s,"depth")
+ size = size + ht + dp
end
elseif id == kern_code then
- local kern = getfield(s,"kern")
+ local kern = getkern(s)
if kern ~= 0 then
if checked_expansion and expand_kerns and (getsubtype(s) == kerning_code or getattr(a_fontkern)) then
local stretch, shrink = kern_stretch_shrink(s,kern)
@@ -764,7 +788,7 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
size = size + kern
end
elseif id == rule_code then
- size = size + getfield(s,"width")
+ size = size + getwidth(s)
elseif trace_unsupported then
report_parbuilders("unsupported node at location %a",6)
end
@@ -809,21 +833,28 @@ local function compute_break_width(par,break_type,p) -- split in two
if id == glyph_code then
return -- happens often
elseif id == glue_code then
- local order = stretch_orders[getfield(p,"stretch_order")]
- break_width.size = break_width.size - getfield(p,"width")
- break_width[order] = break_width[order] - getfield(p,"stretch")
- break_width.shrink = break_width.shrink - getfield(p,"shrink")
+ local wd, stretch, shrink, stretch_order = getglue(p)
+ local order = stretch_orders[stretch_order]
+ break_width.size = break_width.size - wd
+ break_width[order] = break_width[order] - stretch
+ break_width.shrink = break_width.shrink - shrink
elseif id == penalty_code then
-- do nothing
elseif id == kern_code then
local s = getsubtype(p)
if s == userkern_code or s == italickern_code then
- break_width.size = break_width.size - getfield(p,"kern")
+ break_width.size = break_width.size - getkern(p)
else
return
end
elseif id == math_code then
- break_width.size = break_width.size - getfield(p,"surround")
+ break_width.size = break_width.size - getkern(p) -- surround
+ -- new in luatex
+ local wd, stretch, shrink, stretch_order = getglue(p)
+ local order = stretch_orders[stretch_order]
+ break_width.size = break_width.size - wd
+ break_width[order] = break_width[order] - stretch
+ break_width.shrink = break_width.shrink - shrink
else
return
end
@@ -833,29 +864,37 @@ end
local function append_to_vlist(par, b)
local prev_depth = par.prev_depth
+ local head_field = par.head_field
+ local tail_field = head_field and slide_node_list(head_field) -- todo: find_tail
+ local is_hlist = getid(b) == hlist_code
-- if prev_depth > par.ignored_dimen then
if prev_depth > ignore_depth then
- if getid(b) == hlist_code then
- local d = getfield(par.baseline_skip,"width") - prev_depth - getfield(b,"height") -- deficiency of space between baselines
- local s = d < par.line_skip_limit and new_lineskip(par.lineskip) or new_baselineskip(d)
- local head_field = par.head_field
+ if is_hlist then
+ local width, stretch, shrink, stretch_order, shrink_order = getglue(par.baseline_skip)
+ local delta = width - prev_depth - getheight(b) -- deficiency of space between baselines
+ local skip = nil
+ if delta < par.line_skip_limit then
+ width, stretch, shrink, stretch_order, shrink_order = getglue(par.lineskip)
+ skip = new_lineskip(width, stretch, shrink, stretch_order, shrink_order)
+ else
+ skip = new_baselineskip(delta, stretch, shrink, stretch_order, shrink_order)
+ end
if head_field then
- local n = slide_nodelist(head_field) -- todo: find_tail
- setlink(n,s)
+ setlink(tail_field,skip)
else
- par.head_field = s
+ par.head_field = skip
+ head_field = skip
end
+ tail_field = skip
end
end
- local head_field = par.head_field
if head_field then
- local n = slide_nodelist(head_field) -- todo: find_tail
- setlink(n,b)
+ setlink(tail_field,b)
else
par.head_field = b
end
- if getid(b) == hlist_code then
- local pd = getfield(b,"depth")
+ if is_hlist then
+ local pd = getdepth(b)
par.prev_depth = pd
texnest[texnest.ptr].prevdepth = pd
end
@@ -864,7 +903,7 @@ end
local function append_list(par, b)
local head_field = par.head_field
if head_field then
- local n = slide_nodelist(head_field) -- todo: find_tail
+ local n = slide_node_list(head_field) -- todo: find_tail
setlink(n,b)
else
par.head_field = b
@@ -878,7 +917,7 @@ local hztolerance = 2500
local hzwarned = false
local function used_skip(s)
- return s and (getfield(s,"width") ~= 0 or getfield(s,"stretch") ~= 0 or getfield(s,"shrink") ~= 0) and s or nil
+ return s and not is_zero_glue(s) and s
end
local function initialize_line_break(head,display)
@@ -970,7 +1009,7 @@ local function initialize_line_break(head,display)
prev_depth = texnest[texnest.ptr].prevdepth,
- final_par_glue = slide_nodelist(head), -- todo: we know tail already, slow
+ final_par_glue = slide_node_list(head), -- todo: we know tail already, slow
par_break_dir = tex.pardir,
line_break_dir = tex.pardir,
@@ -1069,13 +1108,17 @@ local function initialize_line_break(head,display)
local l = check_shrinkage(par,left_skip)
local r = check_shrinkage(par,right_skip)
- local l_order = stretch_orders[getfield(l,"stretch_order")]
- local r_order = stretch_orders[getfield(r,"stretch_order")]
- background.size = getfield(l,"width") + getfield(r,"width")
- background.shrink = getfield(l,"shrink") + getfield(r,"shrink")
- background[l_order] = getfield(l,"stretch")
- background[r_order] = getfield(r,"stretch") + background[r_order]
+ local lwidth, lstretch, lshrink, lstretch_order, lshrink_order = getglue(l)
+ local rwidth, rstretch, rshrink, rstretch_order, rshrink_order = getglue(r)
+
+ local l_order = stretch_orders[lstretch_order]
+ local r_order = stretch_orders[rstretch_order]
+
+ background.size = lwidth + rwidth
+ background.shrink = lshrink + rshrink
+ background[l_order] = lstretch
+ background[r_order] = rstretch + background[r_order]
-- this will move up so that we can assign the whole par table
@@ -1139,9 +1182,9 @@ local function initialize_line_break(head,display)
end
if last_line_fit > 0 then
- local spec = par.final_par_glue.spec
- local stretch = spec.stretch
- local stretch_order = spec.stretch_order
+ local final_par_glue = par.final_par_glue
+ local stretch = getfield(final_par_glue,"stretch")
+ local stretch_order = getfield(final_par_glue,"stretch_order")
if stretch > 0 and stretch_order > 0 and background.fi == 0 and background.fil == 0 and background.fill == 0 and background.filll == 0 then
par.do_last_line_fit = true
local si = stretch_orders[stretch_order]
@@ -1205,7 +1248,7 @@ local function post_line_break(par)
if not lastnode then
-- only at the end
- lastnode = slide_nodelist(head) -- todo: find_tail
+ lastnode = slide_node_list(head) -- todo: find_tail
if lastnode == par.final_par_glue then
lineend = lastnode
lastnode = getprev(lastnode)
@@ -1217,7 +1260,7 @@ local function post_line_break(par)
lastnode = replace_node(lastnode,new_rightskip(rightskip))
glue_break = true
lineend = lastnode
- lastnode = getprev(r)
+ lastnode = getprev(lastnode)
elseif id == disc_code then
local prevlast = getprev(lastnode)
local nextlast = getnext(lastnode)
@@ -1228,7 +1271,7 @@ local function post_line_break(par)
report_parbuilders('unsupported disc at location %a',3)
end
if pre then
- flush_nodelist(pre)
+ flush_node_list(pre)
pre = nil -- signal
end
if replace then
@@ -1239,13 +1282,13 @@ local function post_line_break(par)
setdisc(lastnode,pre,post,replace)
local pre, post, replace = getdisc(prevlast)
if pre then
- flush_nodelist(pre)
+ flush_node_list(pre)
end
if replace then
- flush_nodelist(replace)
+ flush_node_list(replace)
end
if post then
- flush_nodelist(post)
+ flush_node_list(post)
end
setdisc(prevlast) -- nil,nil,nil
elseif subtype == first_disc_code then
@@ -1258,7 +1301,7 @@ local function post_line_break(par)
setfield(lastnode,"post") -- nil
end
if replace then
- flush_nodelist(replace)
+ flush_node_list(replace)
end
if pre then
setlink(prevlast,pre)
@@ -1272,9 +1315,11 @@ local function post_line_break(par)
setdisc(lastnode) -- nil, nil, nil
disc_break = true
elseif id == kern_code then
- setfield(lastnode,"kern",0)
+ setkern(lastnode,0)
elseif getid(lastnode) == math_code then
- setfield(lastnode,"surround",0)
+ setkern(lastnode,0) -- surround
+ -- new in luatex
+ setglue(lastnode) -- zeros
end
end
lastnode = inject_dirs_at_end_of_line(stack,lastnode,getnext(head),current_break.cur_break)
@@ -1365,21 +1410,21 @@ local function post_line_break(par)
local adjust_head = texlists.adjust_head
local pre_adjust_head = texlists.pre_adjust_head
--
- setfield(finished_line,"shift",cur_indent)
+ setshift(finished_line,cur_indent)
--
-- -- this is gone:
--
-- if par.each_line_height ~= ignored_dimen then
- -- setfield(finished_line,"height",par.each_line_height)
+ -- setheight(finished_line,par.each_line_height)
-- end
-- if par.each_line_depth ~= ignored_dimen then
- -- setfield(finished_line,"depth",par.each_line_depth)
+ -- setdepth(finished_line,par.each_line_depth)
-- end
-- if par.first_line_height ~= ignored_dimen and (current_line == par.first_line + 1) then
- -- setfield(finished_line,"height",par.first_line_height)
+ -- setheight(finished_line,par.first_line_height)
-- end
-- if par.last_line_depth ~= ignored_dimen and current_line + 1 == par.best_line then
- -- setfield(finished_line,"depth",par.last_line_depth)
+ -- setdepth(finished_line,par.last_line_depth)
-- end
--
if texlists.pre_adjust_head ~= pre_adjust_head then
@@ -1427,29 +1472,35 @@ local function post_line_break(par)
local next = nil
while true do
next = getnext(current)
- if next == current_break.cur_break or getid(next) == glyph_code then
+ if next == current_break.cur_break then
break
end
- local id = getid(next)
- local subtype = getsubtype(next)
- if id == localpar_code then
+ local id = getid(next)
+ if id == glyph_code then
+ break
+ elseif id == localpar_code then
-- nothing
elseif id < math_code then
-- messy criterium
break
elseif id == math_code then
-- keep the math node
- setfield(next,"surround",0)
- break
- elseif id == kern_code and (subtype ~= userkern_code and subtype ~= italickern_code and not getattr(next,a_fontkern)) then
- -- fontkerns and accent kerns as well as otf injections
+ setkern(next,0) -- surround
+ -- new in luatex
+ setglue(lastnode) -- zeros
break
+ elseif id == kern_code then
+ local subtype = getsubtype(next)
+ if subtype ~= userkern_code and subtype ~= italickern_code and not getattr(next,a_fontkern) then
+ -- fontkerns and accent kerns as well as otf injections
+ break
+ end
end
current = next
end
if current ~= head then
setnext(current)
- flush_nodelist(getnext(head))
+ flush_node_list(getnext(head))
setlink(head,next)
end
end
@@ -1480,7 +1531,7 @@ local function wrap_up(par)
par.do_last_line_fit = false
else
local glue = par.final_par_glue
- setfield(glue,"width",getfield(glue,"width") + active_short - active_glue)
+ setwidth(glue,getwidth(glue) + active_short - active_glue)
setfield(glue,"stretch",0)
if trace_lastlinefit then
report_parbuilders("applying last line fit, short %a, glue %p",active_short,active_glue)
@@ -1915,8 +1966,8 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio
local id = getid(l)
if id == glyph_code then
-- ok ?
- elseif id == disc_code and l.post then
- l = l.post -- TODO: first char could be a disc
+ elseif id == disc_code and getfield(l,"post") then
+ l = getfield(l,"post") -- TODO: first char could be a disc
else
l = find_protchar_left(l)
end
@@ -2199,10 +2250,11 @@ function constructors.methods.basic(head,d)
while current and p_active ~= n_active do
local char, id = isglyph(current)
if char then
+ local wd, ht, dp = getwhd(current)
if is_rotated[par.line_break_dir] then
- active_width.size = active_width.size + getfield(current,"height") + getfield(current,"depth")
+ active_width.size = active_width.size + ht + dp
else
- active_width.size = active_width.size + getfield(current,"width")
+ active_width.size = active_width.size + wd
end
if checked_expansion then
local currentfont = getfont(current)
@@ -2222,10 +2274,11 @@ function constructors.methods.basic(head,d)
end
end
elseif id == hlist_code or id == vlist_code then
- if is_parallel[getfield(current,"dir")][par.line_break_dir] then
- active_width.size = active_width.size + getfield(current,"width")
+ local wd, ht, dp = getwhd(current)
+ if is_parallel[getdir(current)][par.line_break_dir] then
+ active_width.size = active_width.size + wd
else
- active_width.size = active_width.size + getfield(current,"depth") + getfield(current,"height")
+ active_width.size = active_width.size + ht + dp
end
elseif id == glue_code then
-- if par.auto_breaking then
@@ -2245,10 +2298,11 @@ function constructors.methods.basic(head,d)
end
end
check_shrinkage(par,current)
- local order = stretch_orders[getfield(current,"stretch_order")]
- active_width.size = active_width.size + getfield(current,"width")
- active_width[order] = active_width[order] + getfield(current,"stretch")
- active_width.shrink = active_width.shrink + getfield(current,"shrink")
+ local width, stretch, shrink, stretch_order = getglue(current)
+ local order = stretch_orders[stretch_order]
+ active_width.size = active_width.size + width
+ active_width[order] = active_width[order] + stretch
+ active_width.shrink = active_width.shrink + shrink
elseif id == disc_code then
local subtype = getsubtype(current)
if subtype ~= second_disc_code then
@@ -2256,7 +2310,7 @@ function constructors.methods.basic(head,d)
if second_pass or subtype <= automatic_disc_code then
local actual_pen = subtype == automatic_disc_code and par.ex_hyphen_penalty or par.hyphen_penalty
-- 0.81 :
- -- local actual_pen = getfield(current,"penalty")
+ -- local actual_pen = getpenalty(current)
--
local pre, post, replace = getdisc(current)
if not pre then -- trivial pre-break
@@ -2335,9 +2389,9 @@ function constructors.methods.basic(head,d)
p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
end
local active_width = par.active_width
- active_width.size = active_width.size + getfield(current,"kern")
+ active_width.size = active_width.size + getkern(current)
else
- local kern = getfield(current,"kern")
+ local kern = getkern(current)
if kern ~= 0 then
active_width.size = active_width.size + kern
if checked_expansion and expand_kerns and (getsubtype(current) == kerning_code or getattr(current,a_fontkern)) then
@@ -2362,11 +2416,13 @@ function constructors.methods.basic(head,d)
p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
end
local active_width = par.active_width
- active_width.size = active_width.size + getfield(current,"surround")
+ active_width.size = active_width.size + getkern(current) -- surround
+ -- new in luatex
+ + getwidth(current)
elseif id == rule_code then
- active_width.size = active_width.size + getfield(current,"width")
+ active_width.size = active_width.size + getwidth(current)
elseif id == penalty_code then
- p_active, n_active = try_break(getfield(current,"penalty"), unhyphenated_code, par, first_p, current, checked_expansion)
+ p_active, n_active = try_break(getpenalty(current), unhyphenated_code, par, first_p, current, checked_expansion)
elseif id == dir_code then
par.line_break_dir = checked_line_dir(dirstack) or par.line_break_dir
elseif id == localpar_code then
@@ -2448,727 +2504,730 @@ end
-- standard tex logging .. will be adapted ..
-local function write_esc(cs)
- local esc = tex.escapechar
- if esc then
- write("log",utfchar(esc),cs)
- else
- write("log",cs)
+do
+
+ local function write_esc(cs)
+ local esc = tex.escapechar
+ if esc then
+ write("log",utfchar(esc),cs)
+ else
+ write("log",cs)
+ end
end
-end
-function diagnostics.start()
-end
+ function diagnostics.start()
+ end
-function diagnostics.stop()
- write_nl("log",'')
-end
+ function diagnostics.stop()
+ write_nl("log",'')
+ end
-function diagnostics.current_pass(par,what)
- write_nl("log",format("@%s",what))
-end
+ function diagnostics.current_pass(par,what)
+ write_nl("log",formatters["@%s"](what))
+ end
-local verbose = false -- true
+ local verbose = false -- true
-local function short_display(target,a,font_in_short_display)
- while a do
- local char, id = isglyph(a)
- if char then
- local font = getfont(a)
- if font ~= font_in_short_display then
- write(target,tex.fontidentifier(font) .. ' ')
- font_in_short_display = font
- end
- if getsubtype(a) == ligature_code then
- font_in_short_display = short_display(target,getfield(a,"components"),font_in_short_display)
- else
- write(target,utfchar(char))
- end
- elseif id == disc_code then
- local pre, post, replace = getdisc(a)
- font_in_short_display = short_display(target,pre,font_in_short_display)
- font_in_short_display = short_display(target,post,font_in_short_display)
- elseif verbose then
- write(target,format("[%s]",nodecodes[id]))
- elseif id == rule_code then
- write(target,"|")
- elseif id == glue_code then
- write(target," ")
- elseif id == kern_code then
- local s = getsubtype(a)
- if s == userkern_code or s == italickern_code or getattr(a,a_fontkern) then
- if verbose then
- write(target,"[|]")
- -- else
- -- write(target,"")
+ local function short_display(target,a,font_in_short_display)
+ while a do
+ local char, id = isglyph(a)
+ if char then
+ local font = getfont(a)
+ if font ~= font_in_short_display then
+ write(target,tex.fontidentifier(font) .. ' ')
+ font_in_short_display = font
+ end
+ -- todo: instead of components the split tounicode string
+ if getsubtype(a) == ligature_code then
+ font_in_short_display = short_display(target,getcomponents(a),font_in_short_display)
+ else
+ write(target,utfchar(char))
end
+ elseif id == disc_code then
+ local pre, post, replace = getdisc(a)
+ font_in_short_display = short_display(target,pre,font_in_short_display)
+ font_in_short_display = short_display(target,post,font_in_short_display)
+ elseif verbose then
+ write(target,formatters["[%s]"](nodecodes[id]))
+ elseif id == rule_code then
+ write(target,"|")
+ elseif id == glue_code then
+ write(target," ")
+ elseif id == kern_code then
+ local s = getsubtype(a)
+ if s == userkern_code or s == italickern_code or getattr(a,a_fontkern) then
+ if verbose then
+ write(target,"[|]")
+ -- else
+ -- write(target,"")
+ end
+ else
+ write(target,"[]")
+ end
+ elseif id == math_code then
+ write(target,"$")
else
write(target,"[]")
end
- elseif id == math_code then
- write(target,"$")
- else
- write(target,"[]")
+ a = getnext(a)
end
- a = getnext(a)
+ return font_in_short_display
end
- return font_in_short_display
-end
-diagnostics.short_display = short_display
+ diagnostics.short_display = short_display
-function diagnostics.break_node(par, q, fit_class, break_type, current) -- %d ?
- local passive = par.passive
- local typ_ind = break_type == hyphenated_code and '-' or ""
- if par.do_last_line_fit then
- local s = number.toscaled(q.active_short)
- local g = number.toscaled(q.active_glue)
- if current then
- write_nl("log",format("@@%d: line %d.%d%s t=%s s=%s g=%s",
- passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ function diagnostics.break_node(par, q, fit_class, break_type, current) -- %d ?
+ local passive = par.passive
+ local typ_ind = break_type == hyphenated_code and '-' or ""
+ if par.do_last_line_fit then
+ local s = number.toscaled(q.active_short)
+ local g = number.toscaled(q.active_glue)
+ if current then
+ write_nl("log",formatters["@@%d: line %d.%d%s t=%s s=%s g=%s"](
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ else
+ write_nl("log",formatters["@@%d: line %d.%d%s t=%s s=%s a=%s"](
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ end
else
- write_nl("log",format("@@%d: line %d.%d%s t=%s s=%s a=%s",
- passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ write_nl("log",formatters["@@%d: line %d.%d%s t=%s"](
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits))
+ end
+ if not passive.prev_break then
+ write("log"," -> @0")
+ else
+ write("log",formatters[" -> @%d"](passive.prev_break.serial or 0))
end
- else
- write_nl("log",format("@@%d: line %d.%d%s t=%s",
- passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits))
- end
- if not passive.prev_break then
- write("log"," -> @0")
- else
- write("log",format(" -> @%d", passive.prev_break.serial or 0))
end
-end
-function diagnostics.feasible_break(par, current, r, b, pi, d, artificial_demerits)
- local printed_node = par.printed_node
- if printed_node ~= current then
- write_nl("log","")
+ function diagnostics.feasible_break(par, current, r, b, pi, d, artificial_demerits)
+ local printed_node = par.printed_node
+ if printed_node ~= current then
+ write_nl("log","")
+ if not current then
+ par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display)
+ else
+ local save_link = getnext(current)
+ setnext(current)
+ write_nl("log","")
+ par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display)
+ setnext(current,save_link)
+ end
+ par.printed_node = current
+ end
+ write_nl("log","@")
if not current then
- par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display)
+ write_esc("par")
else
- local save_link = getnext(current)
- setnext(current)
- write_nl("log","")
- par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display)
- setnext(current,save_link)
+ local id = getid(current)
+ if id == glue_code then
+ -- print nothing
+ elseif id == penalty_code then
+ write_esc("penalty")
+ elseif id == disc_code then
+ write_esc("discretionary")
+ elseif id == kern_code then
+ write_esc("kern")
+ elseif id == math_code then
+ write_esc("math")
+ else
+ write_esc("unknown")
+ end
+ end
+ local via, badness, demerits = 0, '*', '*'
+ if r.break_node then
+ via = r.break_node.serial or 0
+ end
+ if b <= infinite_badness then
+ badness = tonumber(d)
end
- par.printed_node = current
+ if not artificial_demerits then
+ demerits = tonumber(d)
+ end
+ write("log",formatters[" via @%d b=%s p=%s d=%s"](via,badness,pi,demerits))
end
- write_nl("log","@")
- if not current then
- write_esc("par")
- else
- local id = getid(current)
- if id == glue_code then
- -- print nothing
- elseif id == penalty_code then
- write_esc("penalty")
- elseif id == disc_code then
- write_esc("discretionary")
- elseif id == kern_code then
- write_esc("kern")
- elseif id == math_code then
- write_esc("math")
+
+ --
+
+ local function common_message(hlist,line,str)
+ write_nl("")
+ if status.output_active then -- unset
+ write(str," has occurred while \\output is active")
else
- write_esc("unknown")
+ write(str)
end
+ local fileline = status.linenumber
+ if line > 0 then
+ write(formatters[" in paragraph at lines %s--%s"](fileline,"--",fileline+line-1))
+ elseif line < 0 then
+ write(formatters[" in alignment at lines "](fileline,"--",fileline-line-1))
+ else
+ write(formatters[" detected at line %s"](fileline))
+ end
+ write_nl("")
+ diagnostics.short_display(getlist(hlist),false)
+ write_nl("")
+ -- diagnostics.start()
+ -- show_box(getlist(hlist))
+ -- diagnostics.stop()
+ end
+
+ function diagnostics.overfull_hbox(hlist,line,d)
+ common_message(hlist,line,formatters["Overfull \\hbox (%spt too wide)"](number.toscaled(d)))
end
- local via, badness, demerits = 0, '*', '*'
- if r.break_node then
- via = r.break_node.serial or 0
+
+ function diagnostics.bad_hbox(hlist,line,b)
+ common_message(hlist,line,formatters["Tight \\hbox (badness %i)"](b))
end
- if b <= infinite_badness then
- badness = tonumber(d) -- format("%d", b)
+
+ function diagnostics.underfull_hbox(hlist,line,b)
+ common_message(hlist,line,formatters["Underfull \\hbox (badness %i)"](b))
end
- if not artificial_demerits then
- demerits = tonumber(d) -- format("%d", d)
+
+ function diagnostics.loose_hbox(hlist,line,b)
+ common_message(hlist,line,formatters["Loose \\hbox (badness %i)"](b))
end
- write("log",format(" via @%d b=%s p=%s d=%s", via, badness, pi, demerits))
+
end
-- reporting --
statistics.register("alternative parbuilders", function()
if nofpars > 0 then
- return format("%s paragraphs, %s lines (%s protruded, %s adjusted)", nofpars, noflines, nofprotrudedlines, nofadjustedlines)
+ return formatters["%s paragraphs, %s lines (%s protruded, %s adjusted)"](nofpars,noflines,nofprotrudedlines,nofadjustedlines)
end
end)
--- actually scaling kerns is not such a good idea and it will become
--- configureable
-
--- This is no way a replacement for the built in (fast) packer
--- it's just an alternative for special (testing) purposes.
---
--- We could use two hpacks: one to be used in the par builder
--- and one to be used for other purposes. The one in the par
--- builder is much more simple as it does not need the expansion
--- code but only need to register the effective expansion factor
--- with the glyph.
-
-local function glyph_width_height_depth(curdir,pdir,p)
- local wd = getfield(p,"width")
- local ht = getfield(p,"height")
- local dp = getfield(p,"depth")
- if is_rotated[curdir] then
- if is_parallel[curdir][pdir] then
- local half = (ht + dp) / 2
- return wd, half, half
- else
- local half = wd / 2
- return ht + dp, half, half
- end
- elseif is_rotated[pdir] then
- if is_parallel[curdir][pdir] then
- local half = (ht + dp) / 2
- return wd, half, half
+do
+
+ -- actually scaling kerns is not such a good idea and it will become
+ -- configureable
+
+ -- This is no way a replacement for the built in (fast) packer
+ -- it's just an alternative for special (testing) purposes.
+ --
+ -- We could use two hpacks: one to be used in the par builder
+ -- and one to be used for other purposes. The one in the par
+ -- builder is much more simple as it does not need the expansion
+ -- code but only need to register the effective expansion factor
+ -- with the glyph.
+
+ local setnodecolor = nodes.tracers.colors.set
+
+ local function glyph_width_height_depth(curdir,pdir,p)
+ local wd, ht, dp = getwhd(p)
+ if is_rotated[curdir] then
+ if is_parallel[curdir][pdir] then
+ local half = (ht + dp) / 2
+ return wd, half, half
+ else
+ local half = wd / 2
+ return ht + dp, half, half
+ end
+ elseif is_rotated[pdir] then
+ if is_parallel[curdir][pdir] then
+ local half = (ht + dp) / 2
+ return wd, half, half
+ else
+ return ht + dp, wd, 0 -- weird
+ end
else
- return ht + dp, wd, 0 -- weird
- end
- else
- if glyphdir_is_equal[curdir][pdir] then
- return wd, ht, dp
- elseif is_opposite[curdir][pdir] then
- return wd, dp, ht
- else -- can this happen?
- return ht + dp, wd, 0
+ if glyphdir_is_equal[curdir][pdir] then
+ return wd, ht, dp
+ elseif is_opposite[curdir][pdir] then
+ return wd, dp, ht
+ else -- can this happen?
+ return ht + dp, wd, 0
+ end
end
end
-end
-local function pack_width_height_depth(curdir,pdir,p)
- local wd = getfield(p,"width")
- local ht = getfield(p,"height")
- local dp = getfield(p,"depth")
- if is_rotated[curdir] then
- if is_parallel[curdir][pdir] then
- local half = (ht + dp) / 2
- return wd, half, half
- else -- can this happen?
- local half = wd / 2
- return ht + dp, half, half
- end
- else
- if pardir_is_equal[curdir][pdir] then
- return wd, ht, dp
- elseif is_opposite[curdir][pdir] then
- return wd, dp, ht
- else -- weird dimensions, can this happen?
- return ht + dp, wd, 0
+ local function pack_width_height_depth(curdir,pdir,p)
+ local wd, ht, dp = getwhd(p)
+ if is_rotated[curdir] then
+ if is_parallel[curdir][pdir] then
+ local half = (ht + dp) / 2
+ return wd, half, half
+ else -- can this happen?
+ local half = wd / 2
+ return ht + dp, half, half
+ end
+ else
+ if pardir_is_equal[curdir][pdir] then
+ return wd, ht, dp
+ elseif is_opposite[curdir][pdir] then
+ return wd, dp, ht
+ else -- weird dimensions, can this happen?
+ return ht + dp, wd, 0
+ end
end
end
-end
-
--- local function xpack(head,width,method,direction,analysis)
---
--- -- inspect(analysis)
---
--- local expansion = method == "cal_expand_ratio"
--- local natural = analysis.size
--- local font_stretch = analysis.adjust_stretch
--- local font_shrink = analysis.adjust_shrink
--- local font_expand_ratio = 0
--- local delta = width - natural
---
--- local hlist = new_node("hlist")
---
--- setlist(hlist,head)
--- setfield(hlist,"dir",direction or tex.textdir)
--- setfield(hlist,"width",width)
--- setfield(hlist,"height",height)
--- setfield(hlist,"depth",depth)
---
--- if delta == 0 then
---
--- setfield(hlist,"glue_sign",0)
--- setfield(hlist,"glue_order",0)
--- setfield(hlist,"glue_set",0)
---
--- else
---
--- local order = analysis.filll ~= 0 and fillcodes.filll or
--- analysis.fill ~= 0 and fillcodes.fill or
--- analysis.fil ~= 0 and fillcodes.fil or
--- analysis.fi ~= 0 and fillcodes.fi or 0
---
--- if delta > 0 then
---
--- if expansion and order == 0 and font_stretch > 0 then
--- font_expand_ratio = (delta/font_stretch) * 1000
--- else
--- local stretch = analysis.stretch
--- if stretch ~= 0 then
--- setfield(hlist,"glue_sign",1) -- stretch
--- setfield(hlist,"glue_order",order)
--- setfield(hlist,"glue_set",delta/stretch)
--- else
--- setfield(hlist,"glue_sign",0) -- nothing
--- setfield(hlist,"glue_order",order)
--- setfield(hlist,"glue_set",0)
--- end
--- end
---
--- else
---
--- if expansion and order == 0 and font_shrink > 0 then
--- font_expand_ratio = (delta/font_shrink) * 1000
--- else
--- local shrink = analysis.shrink
--- if shrink ~= 0 then
--- setfield(hlist,"glue_sign",2) -- shrink
--- setfield(hlist,"glue_order",order)
--- setfield(hlist,"glue_set",-delta/stretch)
--- else
--- setfield(hlist,"glue_sign",0) -- nothing
--- setfield(hlist,"glue_order",order)
--- setfield(hlist,"glue_set",0)
--- end
--- end
---
--- end
---
--- end
---
--- if not expansion or font_expand_ratio == 0 then
--- -- nothing
--- elseif font_expand_ratio > 0 then
--- if font_expand_ratio > 1000 then
--- font_expand_ratio = 1000
--- end
--- local current = head
--- while current do
--- local id = getid(current)
--- if id == glyph_code then
--- local stretch, shrink = char_stretch_shrink(current) -- get only one
--- if stretch then
--- if trace_expansion then
--- setnodecolor(g,"hz:positive")
--- end
--- current.expansion_factor = font_expand_ratio * stretch
--- end
--- elseif id == kern_code then
--- local kern = getfield(current,"kern")
--- if kern ~= 0 and getsubtype(current) == kerning_code then
--- setfield(current,"kern",font_expand_ratio * kern)
--- end
--- end
--- current = getnext(current)
--- end
--- elseif font_expand_ratio < 0 then
--- if font_expand_ratio < -1000 then
--- font_expand_ratio = -1000
--- end
--- local current = head
--- while current do
--- local id = getid(current)
--- if id == glyph_code then
--- local stretch, shrink = char_stretch_shrink(current) -- get only one
--- if shrink then
--- if trace_expansion then
--- setnodecolor(g,"hz:negative")
--- end
--- current.expansion_factor = font_expand_ratio * shrink
--- end
--- elseif id == kern_code then
--- local kern = getfield(current,"kern")
--- if kern ~= 0 and getsubtype(current) == kerning_code then
--- setfield(current,"kern",font_expand_ratio * kern)
--- end
--- end
--- current = getnext(current)
--- end
--- end
--- return hlist, 0
--- end
-
-local function hpack(head,width,method,direction,firstline,line) -- fast version when head = nil
-
- -- we can pass the adjust_width and adjust_height so that we don't need to recalculate them but
- -- with the glue mess it's less trivial as we lack detail .. challenge
- local hlist = new_node("hlist")
-
- setfield(hlist,"dir",direction)
-
- if head == nil then
- setfield(hlist,"width",width)
- return hlist, 0
- else
- setlist(hlist,head)
- end
+ -- local function xpack(head,width,method,direction,analysis)
+ --
+ -- -- inspect(analysis)
+ --
+ -- local expansion = method == "cal_expand_ratio"
+ -- local natural = analysis.size
+ -- local font_stretch = analysis.adjust_stretch
+ -- local font_shrink = analysis.adjust_shrink
+ -- local font_expand_ratio = 0
+ -- local delta = width - natural
+ --
+ -- local hlist = new_hlist()
+ --
+ -- setlist(hlist,head)
+ -- setdir(hlist,direction or tex.textdir)
+ -- setwhd(hlist,width,height,depth)
+ --
+ -- if delta == 0 then
+ --
+ -- setfield(hlist,"glue_sign",0)
+ -- setfield(hlist,"glue_order",0)
+ -- setfield(hlist,"glue_set",0)
+ --
+ -- else
+ --
+ -- local order = analysis.filll ~= 0 and fillcodes.filll or
+ -- analysis.fill ~= 0 and fillcodes.fill or
+ -- analysis.fil ~= 0 and fillcodes.fil or
+ -- analysis.fi ~= 0 and fillcodes.fi or 0
+ --
+ -- if delta > 0 then
+ --
+ -- if expansion and order == 0 and font_stretch > 0 then
+ -- font_expand_ratio = (delta/font_stretch) * 1000
+ -- else
+ -- local stretch = analysis.stretch
+ -- if stretch ~= 0 then
+ -- setfield(hlist,"glue_sign",1) -- stretch
+ -- setfield(hlist,"glue_order",order)
+ -- setfield(hlist,"glue_set",delta/stretch)
+ -- else
+ -- setfield(hlist,"glue_sign",0) -- nothing
+ -- setfield(hlist,"glue_order",order)
+ -- setfield(hlist,"glue_set",0)
+ -- end
+ -- end
+ --
+ -- else
+ --
+ -- if expansion and order == 0 and font_shrink > 0 then
+ -- font_expand_ratio = (delta/font_shrink) * 1000
+ -- else
+ -- local shrink = analysis.shrink
+ -- if shrink ~= 0 then
+ -- setfield(hlist,"glue_sign",2) -- shrink
+ -- setfield(hlist,"glue_order",order)
+ -- setfield(hlist,"glue_set",-delta/stretch)
+ -- else
+ -- setfield(hlist,"glue_sign",0) -- nothing
+ -- setfield(hlist,"glue_order",order)
+ -- setfield(hlist,"glue_set",0)
+ -- end
+ -- end
+ --
+ -- end
+ --
+ -- end
+ --
+ -- if not expansion or font_expand_ratio == 0 then
+ -- -- nothing
+ -- elseif font_expand_ratio > 0 then
+ -- if font_expand_ratio > 1000 then
+ -- font_expand_ratio = 1000
+ -- end
+ -- local current = head
+ -- while current do
+ -- local id = getid(current)
+ -- if id == glyph_code then
+ -- local stretch, shrink = char_stretch_shrink(current) -- get only one
+ -- if stretch then
+ -- if trace_expansion then
+ -- setnodecolor(g,"hz:positive")
+ -- end
+ -- current.expansion_factor = font_expand_ratio * stretch
+ -- end
+ -- elseif id == kern_code then
+ -- local kern = getkern(current)
+ -- if kern ~= 0 and getsubtype(current) == kerning_code then
+ -- setkern(current,font_expand_ratio * kern)
+ -- end
+ -- end
+ -- current = getnext(current)
+ -- end
+ -- elseif font_expand_ratio < 0 then
+ -- if font_expand_ratio < -1000 then
+ -- font_expand_ratio = -1000
+ -- end
+ -- local current = head
+ -- while current do
+ -- local id = getid(current)
+ -- if id == glyph_code then
+ -- local stretch, shrink = char_stretch_shrink(current) -- get only one
+ -- if shrink then
+ -- if trace_expansion then
+ -- setnodecolor(g,"hz:negative")
+ -- end
+ -- current.expansion_factor = font_expand_ratio * shrink
+ -- end
+ -- elseif id == kern_code then
+ -- local kern = getkern(current)
+ -- if kern ~= 0 and getsubtype(current) == kerning_code then
+ -- setkern(current,font_expand_ratio * kern)
+ -- end
+ -- end
+ -- current = getnext(current)
+ -- end
+ -- end
+ -- return hlist, 0
+ -- end
+
+ local function hpack(head,width,method,direction,firstline,line) -- fast version when head = nil
+
+ -- we can pass the adjust_width and adjust_height so that we don't need to recalculate them but
+ -- with the glue mess it's less trivial as we lack detail .. challenge
+
+ local hlist = new_hlist()
+
+ setdir(hlist,direction)
+
+ if head == nil then
+ setwidth(hlist,width)
+ return hlist, 0
+ else
+ setlist(hlist,head)
+ end
- local cal_expand_ratio = method == "cal_expand_ratio" or method == "subst_ex_font"
+ local cal_expand_ratio = method == "cal_expand_ratio" or method == "subst_ex_font"
- direction = direction or tex.textdir
+ direction = direction or tex.textdir
- local line = 0
+ local line = 0
- local height = 0
- local depth = 0
- local natural = 0
- local font_stretch = 0
- local font_shrink = 0
- local font_expand_ratio = 0
- local last_badness = 0
- local expansion_stack = cal_expand_ratio and { } -- todo: optionally pass this
- local expansion_index = 0
- local total_stretch = { [0] = 0, 0, 0, 0, 0 }
- local total_shrink = { [0] = 0, 0, 0, 0, 0 }
+ local height = 0
+ local depth = 0
+ local natural = 0
+ local font_stretch = 0
+ local font_shrink = 0
+ local font_expand_ratio = 0
+ local last_badness = 0
+ local expansion_stack = cal_expand_ratio and { } -- todo: optionally pass this
+ local expansion_index = 0
+ local total_stretch = { [0] = 0, 0, 0, 0, 0 }
+ local total_shrink = { [0] = 0, 0, 0, 0, 0 }
- local hpack_dir = direction
+ local hpack_dir = direction
- local adjust_head = texlists.adjust_head
- local pre_adjust_head = texlists.pre_adjust_head
- local adjust_tail = adjust_head and slide_nodelist(adjust_head) -- todo: find_tail
- local pre_adjust_tail = pre_adjust_head and slide_nodelist(pre_adjust_head) -- todo: find_tail
+ local adjust_head = texlists.adjust_head
+ local pre_adjust_head = texlists.pre_adjust_head
+ local adjust_tail = adjust_head and slide_node_list(adjust_head) -- todo: find_tail
+ local pre_adjust_tail = pre_adjust_head and slide_node_list(pre_adjust_head) -- todo: find_tail
- new_dir_stack(hpack_dir)
+ new_dir_stack(hpack_dir)
- local checked_expansion = false
+ local checked_expansion = false
- if cal_expand_ratio then
- checked_expansion = { }
- setmetatableindex(checked_expansion,check_expand_lines)
- end
+ if cal_expand_ratio then
+ checked_expansion = { }
+ setmetatableindex(checked_expansion,check_expand_lines)
+ end
- -- this one also needs to check the font, so in the end indeed we might end up with two variants
+ -- this one also needs to check the font, so in the end indeed we might end up with two variants
- local fontexps, lastfont
+ local fontexps, lastfont
- local function process(current) -- called nested in disc replace
+ local function process(current) -- called nested in disc replace
- while current do
- local char, id = isglyph(current)
- if char then
- if cal_expand_ratio then
- local currentfont = getfont(current)
- if currentfont ~= lastfont then
- fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer
- lastfont = currentfont
+ while current do
+ local char, id = isglyph(current)
+ if char then
+ if cal_expand_ratio then
+ local currentfont = getfont(current)
+ if currentfont ~= lastfont then
+ fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer
+ lastfont = currentfont
+ end
+ if fontexps then
+ local expansion = fontexps[char]
+ if expansion then
+ font_stretch = font_stretch + expansion.glyphstretch
+ font_shrink = font_shrink + expansion.glyphshrink
+ expansion_index = expansion_index + 1
+ expansion_stack[expansion_index] = current
+ end
+ end
+ end
+ -- use inline
+ local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ?
+ natural = natural + wd
+ if ht > height then
+ height = ht
end
- if fontexps then
- local expansion = fontexps[char]
- if expansion then
- font_stretch = font_stretch + expansion.glyphstretch
- font_shrink = font_shrink + expansion.glyphshrink
+ if dp > depth then
+ depth = dp
+ end
+ elseif id == kern_code then
+ local kern = getkern(current)
+ if kern == 0 then
+ -- no kern
+ elseif getsubtype(current) == kerning_code then -- check getkern(p)
+ if cal_expand_ratio then
+ local stretch, shrink = kern_stretch_shrink(current,kern)
+ font_stretch = font_stretch + stretch
+ font_shrink = font_shrink + shrink
expansion_index = expansion_index + 1
expansion_stack[expansion_index] = current
end
+ natural = natural + kern
+ else
+ natural = natural + kern
end
- end
- -- use inline
- local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ?
- natural = natural + wd
- if ht > height then
- height = ht
- end
- if dp > depth then
- depth = dp
- end
- elseif id == kern_code then
- local kern = getfield(current,"kern")
- if kern == 0 then
- -- no kern
- elseif getsubtype(current) == kerning_code then -- check getfield(p,"kern")
- if cal_expand_ratio then
- local stretch, shrink = kern_stretch_shrink(current,kern)
- font_stretch = font_stretch + stretch
- font_shrink = font_shrink + shrink
- expansion_index = expansion_index + 1
- expansion_stack[expansion_index] = current
+ elseif id == disc_code then
+ local subtype = getsubtype(current)
+ if subtype ~= second_disc_code then
+ -- todo : local stretch, shrink = char_stretch_shrink(s)
+ local replace = getfield(current,"replace")
+ if replace then
+ process(replace)
+ end
end
- natural = natural + kern
- else
- natural = natural + kern
- end
- elseif id == disc_code then
- local subtype = getsubtype(current)
- if subtype ~= second_disc_code then
- -- todo : local stretch, shrink = char_stretch_shrink(s)
- local replace = getfield(current,"replace")
- if replace then
- process(replace)
+ elseif id == glue_code then
+ local wd, stretch, shrink, stretch_order, shrink_order = getglue(current)
+ natural = natural + wd
+ total_stretch[stretch_order] = total_stretch[stretch_order] + stretch
+ total_shrink [shrink_order] = total_shrink[shrink_order] + shrink
+ if getsubtype(current) >= leaders_code then
+ local leader = getleader(current)
+ local wd, ht, dp = getwhd(leader) -- can become getwhd(current) after 1.003
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
end
- end
- elseif id == glue_code then
- natural = natural + getfield(current,"width")
- local op = getfield(current,"stretch_order")
- local om = getfield(current,"shrink_order")
- total_stretch[op] = total_stretch[op] + getfield(current,"stretch")
- total_shrink [om] = total_shrink [om] + getfield(current,"shrink")
- if getsubtype(current) >= leaders_code then
- local leader = getleader(current)
- local ht = getfield(leader,"height")
- local dp = getfield(leader,"depth")
+ elseif id == hlist_code or id == vlist_code then
+ local sh = getshift(current)
+ local wd, ht, dp = pack_width_height_depth(hpack_dir,getdir(current) or hpack_dir,current) -- added: or pack_dir
+ local hs, ds = ht - sh, dp + sh
+ natural = natural + wd
+ if hs > height then
+ height = hs
+ end
+ if ds > depth then
+ depth = ds
+ end
+ elseif id == rule_code then
+ local wd, ht, dp = getwhd(current)
+ natural = natural + wd
if ht > height then
height = ht
end
if dp > depth then
depth = dp
end
+ elseif id == math_code then
+ natural = natural + getkern(current) -- surround
+ -- new in luatex
+ + getwidth(current)
+ elseif id == unset_code then
+ local wd, ht, dp = getwhd(current)
+ local sh = getshift(current)
+ local hs = ht - sh
+ local ds = dp + sh
+ natural = natural + wd
+ if hs > height then
+ height = hs
+ end
+ if ds > depth then
+ depth = ds
+ end
+ elseif id == ins_code or id == mark_code then
+ local prev, next = getboth(current)
+ if adjust_tail then -- todo
+ setlink(prev,next)
+ setlink(adjust_tail,current)
+ setnext(current)
+ adjust_tail = current
+ else
+ adjust_head = current
+ adjust_tail = current
+ setboth(current)
+ end
+ elseif id == adjust_code then
+ local list = getlist(current)
+ if adjust_tail then
+ setnext(adjust_tail,list)
+ else
+ adjust_head = list
+ end
+ adjust_tail = slide_node_list(list) -- find_tail(list)
+ elseif id == dir_code then
+ hpack_dir = checked_line_dir(stack,current) or hpack_dir
+ elseif id == marginkern_code then
+ local width = getwidth(current)
+ if cal_expand_ratio then
+ -- is this ok?
+ local glyph = getfield(current,"glyph")
+ local char_pw = getsubtype(current) == leftmargin_code and left_pw or right_pw
+ font_stretch = font_stretch - width - char_pw(glyph)
+ font_shrink = font_shrink - width - char_pw(glyph)
+ expansion_index = expansion_index + 1
+ expansion_stack[expansion_index] = glyph
+ end
+ natural = natural + width
end
- elseif id == hlist_code or id == vlist_code then
- local sh = getfield(current,"shift")
- local wd, ht, dp = pack_width_height_depth(hpack_dir,getfield(current,"dir") or hpack_dir,current) -- added: or pack_dir
- local hs, ds = ht - sh, dp + sh
- natural = natural + wd
- if hs > height then
- height = hs
- end
- if ds > depth then
- depth = ds
- end
- elseif id == rule_code then
- local wd = getfield(current,"width")
- local ht = getfield(current,"height")
- local dp = getfield(current,"depth")
- natural = natural + wd
- if ht > height then
- height = ht
- end
- if dp > depth then
- depth = dp
- end
- elseif id == math_code then
- natural = natural + getfield(current,"surround")
- elseif id == unset_code then
- local wd = getfield(current,"width")
- local ht = getfield(current,"height")
- local dp = getfield(current,"depth")
- local sh = getfield(current,"shift")
- local hs = ht - sh
- local ds = dp + sh
- natural = natural + wd
- if hs > height then
- height = hs
- end
- if ds > depth then
- depth = ds
- end
- elseif id == ins_code or id == mark_code then
- local prev, next = getboth(current)
- if adjust_tail then -- todo
- setlink(prev,next)
- setlink(adjust_tail,current)
- setnext(current)
- adjust_tail = current
- else
- adjust_head = current
- adjust_tail = current
- setboth(current)
- end
- elseif id == adjust_code then
- local list = getlist(current)
- if adjust_tail then
- setnext(adjust_tail,list)
- else
- adjust_head = list
- end
- adjust_tail = slide_nodelist(list) -- find_tail(list)
- elseif id == dir_code then
- hpack_dir = checked_line_dir(stack,current) or hpack_dir
- elseif id == marginkern_code then
- local width = getfield(current,"width")
- if cal_expand_ratio then
- -- is this ok?
- local glyph = getfield(current,"glyph")
- local char_pw = getsubtype(current) == leftmargin_code and left_pw or right_pw
- font_stretch = font_stretch - width - char_pw(glyph)
- font_shrink = font_shrink - width - char_pw(glyph)
- expansion_index = expansion_index + 1
- expansion_stack[expansion_index] = glyph
- end
- natural = natural + width
+ current = getnext(current)
end
- current = getnext(current)
- end
-
- end
- process(head)
-
- if adjust_tail then
- adjust_tail.next = nil -- todo
- end
- if pre_adjust_tail then
- pre_adjust_tail.next = nil -- todo
- end
- if method == "additional" then
- width = width + natural
- end
+ end
- setfield(hlist,"width",width)
- setfield(hlist,"height",height)
- setfield(hlist,"depth",depth)
+ process(head)
- local delta = width - natural
- if delta == 0 then
- setfield(hlist,"glue_sign",0)
- setfield(hlist,"glue_order",0)
- setfield(hlist,"glue_set",0)
- elseif delta > 0 then
- -- natural width smaller than requested width
- local order = (total_stretch[4] ~= 0 and 4 or total_stretch[3] ~= 0 and 3) or
- (total_stretch[2] ~= 0 and 2 or total_stretch[1] ~= 0 and 1) or 0
- if cal_expand_ratio and order == 0 and font_stretch > 0 then -- check sign of font_stretch
- font_expand_ratio = delta/font_stretch
+ if adjust_tail then
+ adjust_tail.next = nil -- todo
+ end
+ if pre_adjust_tail then
+ pre_adjust_tail.next = nil -- todo
+ end
+ if method == "additional" then
+ width = width + natural
+ end
- if font_expand_ratio > 1 then
- font_expand_ratio = 1
- end
+ setwhd(hlist,width,height,depth)
- local fontexps, lastfont
- for i=1,expansion_index do
- local g = expansion_stack[i]
- local e = 0
- local char = isglyph(g)
- if char then
- local currentfont = getfont(g)
- if currentfont ~= lastfont then
- fontexps = expansions[currentfont]
- lastfont = currentfont
- end
- local data = fontexps[char]
- if trace_expansion then
- setnodecolor(g,"hz:positive")
- end
- e = font_expand_ratio * data.glyphstretch / 1000
- else
- local kern = getfield(g,"kern")
- local stretch, shrink = kern_stretch_shrink(g,kern)
- e = font_expand_ratio * stretch / 1000
- end
- setfield(g,"expansion_factor",e)
- end
- end
- local tso = total_stretch[order]
- if tso ~= 0 then
- setfield(hlist,"glue_sign",1)
- setfield(hlist,"glue_order",order)
- setfield(hlist,"glue_set",delta/tso)
- else
+ local delta = width - natural
+ if delta == 0 then
setfield(hlist,"glue_sign",0)
- setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_order",0)
setfield(hlist,"glue_set",0)
- end
- if font_expand_ratio ~= 0 then
- -- todo
- elseif order == 0 then -- and getlist(hlist) then
- last_badness = calculate_badness(delta,total_stretch[0])
- if last_badness > tex.hbadness then
- if last_badness > 100 then
- diagnostics.underfull_hbox(hlist,line,last_badness)
- else
- diagnostics.loose_hbox(hlist,line,last_badness)
+ elseif delta > 0 then
+ -- natural width smaller than requested width
+ local order = (total_stretch[4] ~= 0 and 4 or total_stretch[3] ~= 0 and 3) or
+ (total_stretch[2] ~= 0 and 2 or total_stretch[1] ~= 0 and 1) or 0
+ if cal_expand_ratio and order == 0 and font_stretch > 0 then -- check sign of font_stretch
+ font_expand_ratio = delta/font_stretch
+
+ if font_expand_ratio > 1 then
+ font_expand_ratio = 1
+ end
+
+ local fontexps, lastfont
+ for i=1,expansion_index do
+ local g = expansion_stack[i]
+ local e = 0
+ local char = isglyph(g)
+ if char then
+ local currentfont = getfont(g)
+ if currentfont ~= lastfont then
+ fontexps = expansions[currentfont]
+ lastfont = currentfont
+ end
+ local data = fontexps[char]
+ if trace_expansion then
+ setnodecolor(g,"hz:positive")
+ end
+ e = font_expand_ratio * data.glyphstretch / 1000
+ else
+ local kern = getkern(g)
+ local stretch, shrink = kern_stretch_shrink(g,kern)
+ e = font_expand_ratio * stretch / 1000
+ end
+ setfield(g,"expansion_factor",e)
end
end
- end
- else
- -- natural width larger than requested width
- local order = total_shrink[4] ~= 0 and 4 or total_shrink[3] ~= 0 and 3
- or total_shrink[2] ~= 0 and 2 or total_shrink[1] ~= 0 and 1 or 0
- if cal_expand_ratio and order == 0 and font_shrink > 0 then -- check sign of font_shrink
- font_expand_ratio = delta/font_shrink
-
- if font_expand_ratio < 1 then
- font_expand_ratio = -1
+ local tso = total_stretch[order]
+ if tso ~= 0 then
+ setfield(hlist,"glue_sign",1)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",delta/tso)
+ else
+ setfield(hlist,"glue_sign",0)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",0)
end
-
- local fontexps, lastfont
- for i=1,expansion_index do
- local g = expansion_stack[i]
- local e = 0
- local char = isglyph(g)
- if char then
- local currentfont = getfont(g)
- if currentfont ~= lastfont then
- fontexps = expansions[currentfont]
- lastfont = currentfont
- end
- local data = fontexps[char]
- if trace_expansion then
- setnodecolor(g,"hz:negative")
+ if font_expand_ratio ~= 0 then
+ -- todo
+ elseif order == 0 then -- and getlist(hlist) then
+ last_badness = calculate_badness(delta,total_stretch[0])
+ if last_badness > tex.hbadness then
+ if last_badness > 100 then
+ diagnostics.underfull_hbox(hlist,line,last_badness)
+ else
+ diagnostics.loose_hbox(hlist,line,last_badness)
end
- e = font_expand_ratio * data.glyphshrink / 1000
- else
- local kern = getfield(g,"kern")
- local stretch, shrink = kern_stretch_shrink(g,kern)
- e = font_expand_ratio * shrink / 1000
end
- setfield(g,"expansion_factor",e)
end
- end
- local tso = total_shrink[order]
- if tso ~= 0 then
- setfield(hlist,"glue_sign",2)
- setfield(hlist,"glue_order",order)
- setfield(hlist,"glue_set",-delta/tso)
else
- setfield(hlist,"glue_sign",0)
- setfield(hlist,"glue_order",order)
- setfield(hlist,"glue_set",0)
- end
- if font_expand_ratio ~= 0 then
- -- todo
- elseif tso < -delta and order == 0 then -- and getlist(hlist) then
- last_badness = 1000000
- setfield(hlist,"glue_set",1)
- local fuzz = - delta - total_shrink[0]
- local hfuzz = tex.hfuzz
- if fuzz > hfuzz or tex.hbadness < 100 then
- local overfullrule = tex.overfullrule
- if fuzz > hfuzz and overfullrule > 0 then
- -- weird, is always called and no rules shows up
- setfield(slide_nodelist(list),"next",new_rule(overfullrule,nil,nil,hlist.dir)) -- todo: find_tail
+ -- natural width larger than requested width
+ local order = total_shrink[4] ~= 0 and 4 or total_shrink[3] ~= 0 and 3
+ or total_shrink[2] ~= 0 and 2 or total_shrink[1] ~= 0 and 1 or 0
+ if cal_expand_ratio and order == 0 and font_shrink > 0 then -- check sign of font_shrink
+ font_expand_ratio = delta/font_shrink
+
+ if font_expand_ratio < 1 then
+ font_expand_ratio = -1
+ end
+
+ local fontexps, lastfont
+ for i=1,expansion_index do
+ local g = expansion_stack[i]
+ local e = 0
+ local char = isglyph(g)
+ if char then
+ local currentfont = getfont(g)
+ if currentfont ~= lastfont then
+ fontexps = expansions[currentfont]
+ lastfont = currentfont
+ end
+ local data = fontexps[char]
+ if trace_expansion then
+ setnodecolor(g,"hz:negative")
+ end
+ e = font_expand_ratio * data.glyphshrink / 1000
+ else
+ local kern = getkern(g)
+ local stretch, shrink = kern_stretch_shrink(g,kern)
+ e = font_expand_ratio * shrink / 1000
+ end
+ setfield(g,"expansion_factor",e)
end
- diagnostics.overfull_hbox(hlist,line,-delta)
end
- elseif order == 0 and getlist(hlist) and last_badness > tex.hbadness then
- diagnostics.bad_hbox(hlist,line,last_badness)
+ local tso = total_shrink[order]
+ if tso ~= 0 then
+ setfield(hlist,"glue_sign",2)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",-delta/tso)
+ else
+ setfield(hlist,"glue_sign",0)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",0)
+ end
+ if font_expand_ratio ~= 0 then
+ -- todo
+ elseif tso < -delta and order == 0 then -- and getlist(hlist) then
+ last_badness = 1000000
+ setfield(hlist,"glue_set",1)
+ local fuzz = - delta - total_shrink[0]
+ local hfuzz = tex.hfuzz
+ if fuzz > hfuzz or tex.hbadness < 100 then
+ local overfullrule = tex.overfullrule
+ if fuzz > hfuzz and overfullrule > 0 then
+ -- weird, is always called and no rules shows up
+ setnext(slide_node_list(list),new_rule(overfullrule,nil,nil,getdir(hlist))) -- todo: find_tail
+ end
+ diagnostics.overfull_hbox(hlist,line,-delta)
+ end
+ elseif order == 0 and getlist(hlist) and last_badness > tex.hbadness then
+ diagnostics.bad_hbox(hlist,line,last_badness)
+ end
end
+ return hlist, last_badness
end
- return hlist, last_badness
-end
-
-xpack_nodes = hpack -- comment this for old fashioned expansion (we need to fix float mess)
-
-constructors.methods.hpack = hpack
-
-local function common_message(hlist,line,str)
- write_nl("")
- if status.output_active then -- unset
- write(str," has occurred while \\output is active")
- end
- local fileline = status.linenumber
- if line > 0 then
- write(str," in paragraph at lines ",fileline,"--",fileline+line-1)
- elseif line < 0 then
- write(str," in alignment at lines ",fileline,"--",fileline-line-1)
- else
- write(str," detected at line ",fileline)
- end
- write_nl("")
- diagnostics.short_display(hlist.list,false)
- write_nl("")
- -- diagnostics.start()
- -- show_box(hlist.list)
- -- diagnostics.stop()
-end
-function diagnostics.overfull_hbox(hlist,line,d)
- common_message(hlist,line,format("Overfull \\hbox (%spt too wide)",number.toscaled(d)))
-end
-
-function diagnostics.bad_hbox(hlist,line,b)
- common_message(hlist,line,format("Tight \\hbox (badness %i)",b))
-end
+ xpack_nodes = hpack -- comment this for old fashioned expansion (we need to fix float mess)
-function diagnostics.underfull_hbox(hlist,line,b)
- common_message(hlist,line,format("Underfull \\hbox (badness %i)",b))
-end
+ constructors.methods.hpack = hpack
-function diagnostics.loose_hbox(hlist,line,b)
- common_message(hlist,line,format("Loose \\hbox (badness %i)",b))
end