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.lua3151
1 files changed, 1573 insertions, 1578 deletions
diff --git a/tex/context/base/mkiv/node-ltp.lua b/tex/context/base/mkiv/node-ltp.lua
index a8de4d783..97eb62ea2 100644
--- a/tex/context/base/mkiv/node-ltp.lua
+++ b/tex/context/base/mkiv/node-ltp.lua
@@ -134,6 +134,53 @@ if not modules then modules = { } end modules ['node-par'] = {
]]--
+--[[--
+
+#define dir_TLT 0
+#define dir_TRT 1
+#define dir_LTL 2
+#define dir_RTT 3
+
+#define dir_TLT_or_TRT(A) (A < 2)
+#define dir_LTL_or_RTT(A) (A > 1)
+
+#define textdir_parallel(A,B) (\
+(dir_TLT_or_TRT(A) and dir_TLT_or_TRT(B)) or \
+(dir_LTL_or_RTT(A) and dir_LTL_or_RTT(B))\
+)
+
+#define pardir_parallel(A,B) (\
+(dir_TLT_or_TRT(A) and dir_TLT_or_TRT(B)) or \
+(dir_LTL_or_RTT(A) and dir_LTL_or_RTT(B))\
+)
+
+#define pardir_opposite(A,B) (\
+(A == dir_LTL and B == dir_RTT) or \
+(A == dir_RTT and B == dir_LTL)\
+)
+
+#define textdir_opposite(A,B) (\
+(A == dir_TLT and B == dir_TRT) or \
+(A == dir_TRT and B == dir_TLT)\
+)
+
+#define glyphdir_opposite(A,B) 0
+
+#define pardir_equal(A,B) (\
+(dir_TLT_or_TRT(A) and dir_TLT_or_TRT(B)) or \
+(A == dir_LTL and B == dir_LTL) or \
+(A == dir_RTT and B == dir_RTT)\
+)
+
+#define textdir_equal(A,B) (\
+(A == dir_TLT and B == dir_TLT) or \
+(A == dir_TRT and B == dir_TRT) or \
+(A == dir_LTL and dir_LTL_or_RTT(B)) or \
+(A == dir_RTT and dir_LTL_or_RTT(B))\
+)
+
+--]]--
+
local tonumber = tonumber
local utfchar = utf.char
local write, write_nl = texio.write, texio.write_nl
@@ -209,7 +256,7 @@ local getwhd = nuts.getwhd
local getcomponents = nuts.getcomponents
local getkern = nuts.getkern
local getpenalty = nuts.getpenalty
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
local getshift = nuts.getshift
local getwidth = nuts.getwidth
local getheight = nuts.getheight
@@ -230,7 +277,7 @@ local setsubtype = nuts.setsubtype
local setglue = nuts.setglue
local setwhd = nuts.setwhd
local setkern = nuts.setkern
-local setdir = nuts.setdir
+local setdirection = nuts.setdirection
local setshift = nuts.setshift
local setwidth = nuts.setwidth
----- setheight = nuts.setheight
@@ -248,13 +295,14 @@ local replace_node = nuts.replace
local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
local is_zero_glue = nuts.is_zero_glue
+local is_skipable = nuts.protrusion_skippable
local nodepool = nuts.pool
local nodecodes = nodes.nodecodes
local kerncodes = nodes.kerncodes
local glyphcodes = nodes.glyphcodes
-local gluecodes = nodes.gluecodes
+local leadercodes = nodes.leadercodes
local margincodes = nodes.margincodes
local disccodes = nodes.disccodes
local mathcodes = nodes.mathcodes
@@ -278,9 +326,9 @@ local marginkern_code = nodecodes.marginkern
local dir_code = nodecodes.dir
local boundary_code = nodecodes.boundary
-local protrusion_code = boundarycodes.protrusion
+local protrusionboundary_code = boundarycodes.protrusion
-local leaders_code = gluecodes.leaders
+local leaders_code = leadercodes.leaders
local localpar_code = nodecodes.localpar
@@ -289,17 +337,17 @@ local italickern_code = kerncodes.italiccorrection
local fontkern_code = kerncodes.fontkern
local accentkern_code = kerncodes.accentkern
-local ligature_code = glyphcodes.ligature
+local ligatureglyph_code = glyphcodes.ligature
-local stretch_orders = nodes.fillcodes
+local fillcodes = nodes.fillcodes
local leftmargin_code = margincodes.left
----- rightmargin_code = margincodes.right
-local automatic_disc_code = disccodes.automatic
-local regular_disc_code = disccodes.regular
-local first_disc_code = disccodes.first
-local second_disc_code = disccodes.second
+local automaticdisc_code = disccodes.automatic
+local regulardisc_code = disccodes.regular
+local firstdisc_code = disccodes.first
+local seconddisc_code = disccodes.second
local endmath_code = mathcodes.endmath
@@ -325,7 +373,7 @@ local fit_decent_class = 2 -- fitness for all other lines
local fit_tight_class = 3 -- fitness for lines shrinking 0.5 to 1.0 of their shrinkability
local new_penalty = nodepool.penalty
-local new_dir = nodepool.textdir
+local new_direction = nodepool.direction
local new_leftmarginkern = nodepool.leftmarginkern
local new_rightmarginkern = nodepool.rightmarginkern
local new_leftskip = nodepool.leftskip
@@ -336,17 +384,6 @@ 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
-local is_opposite = nodes.textdir_is_opposite
-local textdir_is_equal = nodes.textdir_is_equal
-local pardir_is_equal = nodes.pardir_is_equal
-local glyphdir_is_equal = nodes.glyphdir_is_equal
-
-local dir_pops = nodes.dir_is_pop
-local dir_negations = nodes.dir_negation
-local is_skipable = nuts.protrusion_skippable
-
-- helpers --
-- It makes more sense to move the somewhat messy dir state tracking
@@ -361,22 +398,24 @@ end
-- in the parbuilder.
local function checked_line_dir(stack,current)
- if not dir_pops[current] then
+ local direction, pop = getdirection(current)
+ if not pop then
local n = stack.n + 1
stack.n = n
stack[n] = current
- return getdir(current)
+ return direction
elseif n > 0 then
local n = stack.n
local dirnode = stack[n]
dirstack.n = n - 1
- return getdir(dirnode)
+ direction = getdirection(dirnode) -- we could save it
+ return direction
else
report_parbuilders("warning: missing pop node (%a)",1) -- in line ...
end
end
--- The next function checks a dir nodes in a list and appends the negations
+-- The next function checks dir nodes in a list and appends the negations
-- that are currently needed (some day LuaTeX will be more tolerant). We use
-- the negations for the next line.
@@ -384,10 +423,12 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop)
local e = start
local n = stack.n
local h = nil
+ -- todo: traverse
while start and start ~= stop do
local id = getid(start)
if id == dir_code then
- if not dir_pops[getdir(start)] then -- weird, what is this #
+ local direction, pop = getdirection(start)
+ if not pop then
n = n + 1
stack[n] = start
elseif n > 0 then
@@ -399,7 +440,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[getdir(stack[i])]))
+ h, current = insert_node_after(current,current,new_direction(getdirection(stack[i]),true))
end
stack.n = n
return current
@@ -408,7 +449,7 @@ end
local function inject_dirs_at_begin_of_line(stack,current)
local h = nil
for i=stack.n,1,-1 do
- h, current = insert_node_after(current,current,new_dir(stack[i]))
+ h, current = insert_node_after(current,current,new_direction(stack[i]))
end
stack.n = 0
return current
@@ -632,7 +673,7 @@ local function find(head) -- do we really want to recurse into an hlist?
head = getnext(head)
end
elseif id == boundary_code then
- if getsubtype(head) == protrusion_code then
+ if getsubtype(head) == protrusionboundary_code then
local v = getdata(head)
if v == 1 or v == 3 then
head = getnext(head)
@@ -686,7 +727,7 @@ local function find(head,tail)
tail = getprev(tail)
end
elseif id == boundary_code then
- if getsubtype(head) == protrusion_code then
+ if getsubtype(head) == protrusionboundary_code then
local v = getdata(tail)
if v == 2 or v == 3 then
tail = getprev(tail)
@@ -750,7 +791,7 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
local char, id = isglyph(s)
if char then
local wd, ht, dp = getwhd(s)
- if is_rotated[line_break_dir] then -- can be shared
+ if is_rotated(line_break_dir) then
size = size + ht + dp
else
size = size + wd
@@ -767,7 +808,7 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
end
elseif id == hlist_code or id == vlist_code then
local wd, ht, dp = getwhd(s)
- if is_parallel[getdir(s)][line_break_dir] then
+ if textdir_parallel(getdirection(s),line_break_dir) then
size = size + wd
else
size = size + ht + dp
@@ -798,1707 +839,1710 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
return size, adjust_stretch, adjust_shrink
end
-local function compute_break_width(par,break_type,p) -- split in two
- local break_width = par.break_width
- if break_type > unhyphenated_code then
- local disc_width = par.disc_width
- local checked_expansion = par.checked_expansion
- local line_break_dir = par.line_break_dir
- local break_size = break_width.size + disc_width.size
- local break_adjust_stretch = break_width.adjust_stretch + disc_width.adjust_stretch
- local break_adjust_shrink = break_width.adjust_shrink + disc_width.adjust_shrink
- local pre, post, replace = getdisc(p)
- if replace then
- local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace)
- break_size = break_size - size
- break_adjust_stretch = break_adjust_stretch - adjust_stretch
- break_adjust_shrink = break_adjust_shrink - adjust_shrink
- end
- if post then
- local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,post)
- break_size = break_size + size
- break_adjust_stretch = break_adjust_stretch + adjust_stretch
- break_adjust_shrink = break_adjust_shrink + adjust_shrink
- end
- break_width.size = break_size
- break_width.adjust_stretch = break_adjust_stretch
- break_width.adjust_shrink = break_adjust_shrink
- if not post then
- p = getnext(p)
- else
- return
+-- We can actually make par local to this module as we never break inside a break call and that way the
+-- array is reused. At some point the information will be part of the paragraph spec as passed.
+
+local hztolerance = 2500
+local hzwarned = false
+
+do
+
+ local function compute_break_width(par,break_type,p) -- split in two
+ local break_width = par.break_width
+ if break_type > unhyphenated_code then
+ local disc_width = par.disc_width
+ local checked_expansion = par.checked_expansion
+ local line_break_dir = par.line_break_dir
+ local break_size = break_width.size + disc_width.size
+ local break_adjust_stretch = break_width.adjust_stretch + disc_width.adjust_stretch
+ local break_adjust_shrink = break_width.adjust_shrink + disc_width.adjust_shrink
+ local pre, post, replace = getdisc(p)
+ if replace then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace)
+ break_size = break_size - size
+ break_adjust_stretch = break_adjust_stretch - adjust_stretch
+ break_adjust_shrink = break_adjust_shrink - adjust_shrink
+ end
+ if post then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,post)
+ break_size = break_size + size
+ break_adjust_stretch = break_adjust_stretch + adjust_stretch
+ break_adjust_shrink = break_adjust_shrink + adjust_shrink
+ end
+ break_width.size = break_size
+ break_width.adjust_stretch = break_adjust_stretch
+ break_width.adjust_shrink = break_adjust_shrink
+ if not post then
+ p = getnext(p)
+ else
+ return
+ end
end
- end
- while p do -- skip spacing etc
- local id = getid(p)
- if id == glyph_code then
- return -- happens often
- elseif id == glue_code then
- 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 - getkern(p)
+ while p do -- skip spacing etc
+ local id = getid(p)
+ if id == glyph_code then
+ return -- happens often
+ elseif id == glue_code then
+ local wd, stretch, shrink, stretch_order = getglue(p)
+ local order = fillcodes[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 - getkern(p)
+ else
+ return
+ end
+ elseif id == math_code then
+ break_width.size = break_width.size - getkern(p) -- surround
+ -- new in luatex
+ local wd, stretch, shrink, stretch_order = getglue(p)
+ local order = fillcodes[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
- elseif id == math_code then
- 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
+ p = getnext(p)
end
- p = getnext(p)
end
-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 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
- setlink(tail_field,skip)
- else
- par.head_field = skip
- head_field = skip
+ 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 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
+ setlink(tail_field,skip)
+ else
+ par.head_field = skip
+ head_field = skip
+ end
+ tail_field = skip
end
- tail_field = skip
+ end
+ if head_field then
+ setlink(tail_field,b)
+ else
+ par.head_field = b
+ end
+ if is_hlist then
+ local pd = getdepth(b)
+ par.prev_depth = pd
+ texnest[texnest.ptr].prevdepth = pd
end
end
- if head_field then
- setlink(tail_field,b)
- else
- par.head_field = b
- end
- if is_hlist then
- local pd = getdepth(b)
- par.prev_depth = pd
- texnest[texnest.ptr].prevdepth = pd
- end
-end
-local function append_list(par, b)
- local head_field = par.head_field
- if head_field then
- local n = slide_node_list(head_field) -- todo: find_tail
- setlink(n,b)
- else
- par.head_field = b
- end
-end
-
--- We can actually make par local to this module as we never break inside a break call and that way the
--- array is reused. At some point the information will be part of the paragraph spec as passed.
-
-local hztolerance = 2500
-local hzwarned = false
-
-local function used_skip(s)
- return s and not is_zero_glue(s) and s
-end
-
-local function initialize_line_break(head,display)
-
- local hang_indent = tex.hangindent or 0
- local hsize = tex.hsize or 0
- local hang_after = tex.hangafter or 0
- local par_shape_ptr = tex.parshape
- local left_skip = tonut(tex.leftskip) -- nodes
- local right_skip = tonut(tex.rightskip) -- nodes
- local pretolerance = tex.pretolerance
- local tolerance = tex.tolerance
- local adjust_spacing = tex.adjustspacing
- local protrude_chars = tex.protrudechars
- local last_line_fit = tex.lastlinefit
-
- local newhead = new_temp()
- setnext(newhead,head)
-
- local adjust_spacing_status = adjust_spacing > 1 and -1 or 0
-
- -- metatables
-
- local par = {
- head = newhead,
- head_field = nil,
- display = display,
- font_in_short_display = 0,
- no_shrink_error_yet = true, -- have we complained about infinite shrinkage?
- second_pass = false, -- is this our second attempt to break this paragraph?
- final_pass = false, -- is this our final attempt to break this paragraph?
- threshold = 0, -- maximum badness on feasible lines
-
- passive = nil, -- most recent node on passive list
- printed_node = head, -- most recent node that has been printed
- pass_number = 0, -- the number of passive nodes allocated on this pass
- auto_breaking = 0, -- make auto_breaking accessible out of line_break
-
- active_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 },
- break_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 },
- disc_width = { size = 0, adjust_stretch = 0, adjust_shrink = 0 },
- fill_width = { stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 },
- background = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 },
-
- hang_indent = hang_indent,
- hsize = hsize,
- hang_after = hang_after,
- par_shape_ptr = par_shape_ptr,
- left_skip = left_skip,
- right_skip = right_skip,
- pretolerance = pretolerance,
- tolerance = tolerance,
-
- protrude_chars = protrude_chars,
- adjust_spacing = adjust_spacing,
- max_stretch_ratio = adjust_spacing_status,
- max_shrink_ratio = adjust_spacing_status,
- cur_font_step = adjust_spacing_status,
- checked_expansion = false,
- tracing_paragraphs = tex.tracingparagraphs > 0,
-
- emergency_stretch = tex.emergencystretch or 0,
- looseness = tex.looseness or 0,
- line_penalty = tex.linepenalty or 0,
- hyphen_penalty = tex.hyphenpenalty or 0,
- broken_penalty = tex.brokenpenalty or 0,
- inter_line_penalty = tex.interlinepenalty or 0,
- club_penalty = tex.clubpenalty or 0,
- widow_penalty = tex.widowpenalty or 0,
- display_widow_penalty = tex.displaywidowpenalty or 0,
- ex_hyphen_penalty = tex.exhyphenpenalty or 0,
-
- adj_demerits = tex.adjdemerits or 0,
- double_hyphen_demerits = tex.doublehyphendemerits or 0,
- final_hyphen_demerits = tex.finalhyphendemerits or 0,
-
- first_line = 0, -- texnest[texnest.ptr].modeline, -- 0, -- cur_list.pg_field
-
- -- each_line_height = tex.pdfeachlineheight or 0, -- this will go away
- -- each_line_depth = tex.pdfeachlinedepth or 0, -- this will go away
- -- first_line_height = tex.pdffirstlineheight or 0, -- this will go away
- -- last_line_depth = tex.pdflastlinedepth or 0, -- this will go away
-
- -- ignored_dimen = tex.pdfignoreddimen or 0,
-
- baseline_skip = tonut(tex.baselineskip),
- lineskip = tonut(tex.lineskip),
- line_skip_limit = tex.lineskiplimit,
-
- prev_depth = texnest[texnest.ptr].prevdepth,
-
- final_par_glue = slide_node_list(head), -- todo: we know tail already, slow
-
- par_break_dir = tex.pardir,
- line_break_dir = tex.pardir,
-
- internal_pen_inter = 0, -- running localinterlinepenalty
- internal_pen_broken = 0, -- running localbrokenpenalty
- internal_left_box = nil, -- running localleftbox
- internal_left_box_width = 0, -- running localleftbox width
- init_internal_left_box = nil, -- running localleftbox
- init_internal_left_box_width = 0, -- running localleftbox width
- internal_right_box = nil, -- running localrightbox
- internal_right_box_width = 0, -- running localrightbox width
-
- best_place = { }, -- how to achieve minimal_demerits
- best_pl_line = { }, -- corresponding line number
- easy_line = 0, -- line numbers easy_line are equivalent in break nodes
- last_special_line = 0, -- line numbers last_special_line all have the same width
- first_width = 0, -- the width of all lines last_special_line, if no parshape has been specified
- second_width = 0, -- the width of all lines last_special_line
- first_indent = 0, -- left margin to go with first_width
- second_indent = 0, -- left margin to go with second_width
-
- best_bet = nil, -- use this passive node and its predecessors
- fewest_demerits = 0, -- the demerits associated with best_bet
- best_line = 0, -- line number following the last line of the new paragraph
- line_diff = 0, -- the difference between the current line number and the optimum best_line
-
- -- not yet used
-
- best_pl_short = { }, -- shortfall corresponding to minimal_demerits
- best_pl_glue = { }, -- corresponding glue stretch or shrink
- do_last_line_fit = false,
- last_line_fit = last_line_fit,
-
- minimum_demerits = awful_badness,
-
- minimal_demerits = {
-
- [fit_very_loose_class] = awful_badness,
- [fit_loose_class] = awful_badness,
- [fit_decent_class] = awful_badness,
- [fit_tight_class] = awful_badness,
-
- },
-
- prev_char_p = nil,
-
- statistics = {
-
- noflines = 0,
- nofprotrudedlines = 0,
- nofadjustedlines = 0,
-
- },
-
- -- -- just a thought ... parshape functions ... it would be nice to
- -- -- also store the height so far (probably not too hard) although
- -- -- in most cases we work on grids in such cases
- --
- -- adapt_width = function(par,line)
- -- -- carry attribute, so that we can accumulate
- -- local left = 655360 * (line - 1)
- -- local right = 655360 * (line - 1)
- -- return left, right
- -- end
+ local function append_list(par, b)
+ local head_field = par.head_field
+ if head_field then
+ local n = slide_node_list(head_field) -- todo: find_tail
+ setlink(n,b)
+ else
+ par.head_field = b
+ end
+ end
+
+ local function used_skip(s)
+ return s and not is_zero_glue(s) and s
+ end
+
+ local function initialize_line_break(head,display)
+
+ local hang_indent = tex.hangindent or 0
+ local hsize = tex.hsize or 0
+ local hang_after = tex.hangafter or 0
+ local par_shape_ptr = tex.parshape
+ local left_skip = tonut(tex.leftskip) -- nodes
+ local right_skip = tonut(tex.rightskip) -- nodes
+ local pretolerance = tex.pretolerance
+ local tolerance = tex.tolerance
+ local adjust_spacing = tex.adjustspacing
+ local protrude_chars = tex.protrudechars
+ local last_line_fit = tex.lastlinefit
+ local par_dir = tex.pardirection
+
+ local newhead = new_temp()
+ setnext(newhead,head)
+
+ local adjust_spacing_status = adjust_spacing > 1 and -1 or 0
+
+ -- metatables
+
+ local par = {
+ head = newhead,
+ head_field = nil,
+ display = display,
+ font_in_short_display = 0,
+ no_shrink_error_yet = true, -- have we complained about infinite shrinkage?
+ second_pass = false, -- is this our second attempt to break this paragraph?
+ final_pass = false, -- is this our final attempt to break this paragraph?
+ threshold = 0, -- maximum badness on feasible lines
+
+ passive = nil, -- most recent node on passive list
+ printed_node = head, -- most recent node that has been printed
+ pass_number = 0, -- the number of passive nodes allocated on this pass
+ auto_breaking = 0, -- make auto_breaking accessible out of line_break
+
+ active_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 },
+ break_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 },
+ disc_width = { size = 0, adjust_stretch = 0, adjust_shrink = 0 },
+ fill_width = { stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 },
+ background = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 },
+
+ hang_indent = hang_indent,
+ hsize = hsize,
+ hang_after = hang_after,
+ par_shape_ptr = par_shape_ptr,
+ left_skip = left_skip,
+ right_skip = right_skip,
+ pretolerance = pretolerance,
+ tolerance = tolerance,
+
+ protrude_chars = protrude_chars,
+ adjust_spacing = adjust_spacing,
+ max_stretch_ratio = adjust_spacing_status,
+ max_shrink_ratio = adjust_spacing_status,
+ cur_font_step = adjust_spacing_status,
+ checked_expansion = false,
+ tracing_paragraphs = tex.tracingparagraphs > 0,
+
+ emergency_stretch = tex.emergencystretch or 0,
+ looseness = tex.looseness or 0,
+ line_penalty = tex.linepenalty or 0,
+ hyphen_penalty = tex.hyphenpenalty or 0,
+ broken_penalty = tex.brokenpenalty or 0,
+ inter_line_penalty = tex.interlinepenalty or 0,
+ club_penalty = tex.clubpenalty or 0,
+ widow_penalty = tex.widowpenalty or 0,
+ display_widow_penalty = tex.displaywidowpenalty or 0,
+ ex_hyphen_penalty = tex.exhyphenpenalty or 0,
+
+ adj_demerits = tex.adjdemerits or 0,
+ double_hyphen_demerits = tex.doublehyphendemerits or 0,
+ final_hyphen_demerits = tex.finalhyphendemerits or 0,
+
+ first_line = 0, -- texnest[texnest.ptr].modeline, -- 0, -- cur_list.pg_field
+
+ -- each_line_height = tex.pdfeachlineheight or 0, -- this will go away
+ -- each_line_depth = tex.pdfeachlinedepth or 0, -- this will go away
+ -- first_line_height = tex.pdffirstlineheight or 0, -- this will go away
+ -- last_line_depth = tex.pdflastlinedepth or 0, -- this will go away
+
+ -- ignored_dimen = tex.pdfignoreddimen or 0,
+
+ baseline_skip = tonut(tex.baselineskip),
+ lineskip = tonut(tex.lineskip),
+ line_skip_limit = tex.lineskiplimit,
+
+ prev_depth = texnest[texnest.ptr].prevdepth,
+
+ final_par_glue = slide_node_list(head), -- todo: we know tail already, slow
+
+ par_break_dir = par_dir,
+ line_break_dir = par_dir,
+
+ internal_pen_inter = 0, -- running localinterlinepenalty
+ internal_pen_broken = 0, -- running localbrokenpenalty
+ internal_left_box = nil, -- running localleftbox
+ internal_left_box_width = 0, -- running localleftbox width
+ init_internal_left_box = nil, -- running localleftbox
+ init_internal_left_box_width = 0, -- running localleftbox width
+ internal_right_box = nil, -- running localrightbox
+ internal_right_box_width = 0, -- running localrightbox width
+
+ best_place = { }, -- how to achieve minimal_demerits
+ best_pl_line = { }, -- corresponding line number
+ easy_line = 0, -- line numbers easy_line are equivalent in break nodes
+ last_special_line = 0, -- line numbers last_special_line all have the same width
+ first_width = 0, -- the width of all lines last_special_line, if no parshape has been specified
+ second_width = 0, -- the width of all lines last_special_line
+ first_indent = 0, -- left margin to go with first_width
+ second_indent = 0, -- left margin to go with second_width
+
+ best_bet = nil, -- use this passive node and its predecessors
+ fewest_demerits = 0, -- the demerits associated with best_bet
+ best_line = 0, -- line number following the last line of the new paragraph
+ line_diff = 0, -- the difference between the current line number and the optimum best_line
+
+ -- not yet used
+
+ best_pl_short = { }, -- shortfall corresponding to minimal_demerits
+ best_pl_glue = { }, -- corresponding glue stretch or shrink
+ do_last_line_fit = false,
+ last_line_fit = last_line_fit,
+
+ minimum_demerits = awful_badness,
+
+ minimal_demerits = {
+
+ [fit_very_loose_class] = awful_badness,
+ [fit_loose_class] = awful_badness,
+ [fit_decent_class] = awful_badness,
+ [fit_tight_class] = awful_badness,
+
+ },
+
+ prev_char_p = nil,
+
+ statistics = {
+
+ noflines = 0,
+ nofprotrudedlines = 0,
+ nofadjustedlines = 0,
+
+ },
+
+ -- -- just a thought ... parshape functions ... it would be nice to
+ -- -- also store the height so far (probably not too hard) although
+ -- -- in most cases we work on grids in such cases
+ --
+ -- adapt_width = function(par,line)
+ -- -- carry attribute, so that we can accumulate
+ -- local left = 655360 * (line - 1)
+ -- local right = 655360 * (line - 1)
+ -- return left, right
+ -- end
- }
+ }
- -- optimizers
+ -- optimizers
- par.used_left_skip = used_skip(par.left_skip)
- par.used_right_skip = used_skip(par.right_skip)
+ par.used_left_skip = used_skip(par.left_skip)
+ par.used_right_skip = used_skip(par.right_skip)
- -- so far
+ -- so far
- if adjust_spacing > 1 then
- local checked_expansion = { par = par }
- setmetatableindex(checked_expansion,check_expand_pars)
- par.checked_expansion = checked_expansion
+ if adjust_spacing > 1 then
+ local checked_expansion = { par = par }
+ setmetatableindex(checked_expansion,check_expand_pars)
+ par.checked_expansion = checked_expansion
- if par.tolerance < hztolerance then
- if not hzwarned then
- report_parbuilders("setting tolerance to %a for hz",hztolerance)
- hzwarned = true
+ if par.tolerance < hztolerance then
+ if not hzwarned then
+ report_parbuilders("setting tolerance to %a for hz",hztolerance)
+ hzwarned = true
+ end
+ par.tolerance = hztolerance
end
- par.tolerance = hztolerance
- end
- expand_kerns = expand_kerns_mode or (adjust_spacing == 2)
+ expand_kerns = expand_kerns_mode or (adjust_spacing == 2)
- end
+ end
- -- we need par for the error message
+ -- we need par for the error message
- local background = par.background
+ local background = par.background
- local l = check_shrinkage(par,left_skip)
- local r = check_shrinkage(par,right_skip)
+ local l = check_shrinkage(par,left_skip)
+ local r = check_shrinkage(par,right_skip)
- local lwidth, lstretch, lshrink, lstretch_order, lshrink_order = getglue(l)
- local rwidth, rstretch, rshrink, rstretch_order, rshrink_order = getglue(r)
+ 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]
+ local l_order = fillcodes[lstretch_order]
+ local r_order = fillcodes[rstretch_order]
- background.size = lwidth + rwidth
- background.shrink = lshrink + rshrink
- background[l_order] = lstretch
- background[r_order] = rstretch + background[r_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
+ -- this will move up so that we can assign the whole par table
- if not par_shape_ptr then
- if hang_indent == 0 then
- par.second_width = hsize
- par.second_indent = 0
- else
- local abs_hang_after = hang_after >0 and hang_after or -hang_after
- local abs_hang_indent = hang_indent>0 and hang_indent or -hang_indent
- par.last_special_line = abs_hang_after
- if hang_after < 0 then
- par.first_width = hsize - abs_hang_indent
- if hang_indent >= 0 then
- par.first_indent = hang_indent
- else
- par.first_indent = 0
- end
+ if not par_shape_ptr then
+ if hang_indent == 0 then
par.second_width = hsize
par.second_indent = 0
else
- par.first_width = hsize
- par.first_indent = 0
- par.second_width = hsize - abs_hang_indent
- if hang_indent >= 0 then
- par.second_indent = hang_indent
- else
+ local abs_hang_after = hang_after >0 and hang_after or -hang_after
+ local abs_hang_indent = hang_indent>0 and hang_indent or -hang_indent
+ par.last_special_line = abs_hang_after
+ if hang_after < 0 then
+ par.first_width = hsize - abs_hang_indent
+ if hang_indent >= 0 then
+ par.first_indent = hang_indent
+ else
+ par.first_indent = 0
+ end
+ par.second_width = hsize
par.second_indent = 0
+ else
+ par.first_width = hsize
+ par.first_indent = 0
+ par.second_width = hsize - abs_hang_indent
+ if hang_indent >= 0 then
+ par.second_indent = hang_indent
+ else
+ par.second_indent = 0
+ end
end
end
+ else
+ local last_special_line = #par_shape_ptr
+ par.last_special_line = last_special_line
+ local parshape = par_shape_ptr[last_special_line]
+ par.second_width = parshape[2]
+ par.second_indent = parshape[1]
end
- else
- local last_special_line = #par_shape_ptr
- par.last_special_line = last_special_line
- local parshape = par_shape_ptr[last_special_line]
- par.second_width = parshape[2]
- par.second_indent = parshape[1]
- end
- if par.looseness == 0 then
- par.easy_line = par.last_special_line
- else
- par.easy_line = max_halfword
- end
+ if par.looseness == 0 then
+ par.easy_line = par.last_special_line
+ else
+ par.easy_line = max_halfword
+ end
- if pretolerance >= 0 then
- par.threshold = pretolerance
- par.second_pass = false
- par.final_pass = false
- else
- par.threshold = tolerance
- par.second_pass = true
- par.final_pass = par.emergency_stretch <= 0
- if trace_basic then
- if par.final_pass then
- report_parbuilders("enabling second and final pass")
- else
- report_parbuilders("enabling second pass")
+ if pretolerance >= 0 then
+ par.threshold = pretolerance
+ par.second_pass = false
+ par.final_pass = false
+ else
+ par.threshold = tolerance
+ par.second_pass = true
+ par.final_pass = par.emergency_stretch <= 0
+ if trace_basic then
+ if par.final_pass then
+ report_parbuilders("enabling second and final pass")
+ else
+ report_parbuilders("enabling second pass")
+ end
end
end
- end
- if last_line_fit > 0 then
- 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]
- if trace_lastlinefit or trace_basic then
- report_parbuilders("enabling last line fit, stretch order %a set to %a, linefit is %a",si,stretch,last_line_fit)
+ if last_line_fit > 0 then
+ 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 = fillcodes[stretch_order]
+ if trace_lastlinefit or trace_basic then
+ report_parbuilders("enabling last line fit, stretch order %a set to %a, linefit is %a",si,stretch,last_line_fit)
+ end
+ par.fill_width[si] = stretch
end
- par.fill_width[si] = stretch
end
- end
- return par
-end
+ return par
+ end
--- there are still all kind of artefacts in here (a side effect I guess of pdftex,
--- etex, omega and other extensions that got obscured by patching)
+ -- there are still all kind of artefacts in here (a side effect I guess of pdftex,
+ -- etex, omega and other extensions that got obscured by patching)
-local function post_line_break(par)
+ local function post_line_break(par)
- local prevgraf = texnest[texnest.ptr].prevgraf
- local current_line = prevgraf + 1 -- the current line number being justified
+ local prevgraf = texnest[texnest.ptr].prevgraf
+ local current_line = prevgraf + 1 -- the current line number being justified
- local adjust_spacing = par.adjust_spacing
- local protrude_chars = par.protrude_chars
- local statistics = par.statistics
+ local adjust_spacing = par.adjust_spacing
+ local protrude_chars = par.protrude_chars
+ local statistics = par.statistics
- local stack = new_dir_stack()
+ local stack = new_dir_stack()
- local leftskip = par.used_left_skip -- used or normal ?
- local rightskip = par.right_skip
- local parshape = par.par_shape_ptr
- ----- ignored_dimen = par.ignored_dimen
+ local leftskip = par.used_left_skip -- used or normal ?
+ local rightskip = par.right_skip
+ local parshape = par.par_shape_ptr
+ ----- ignored_dimen = par.ignored_dimen
- local adapt_width = par.adapt_width
+ local adapt_width = par.adapt_width
- -- reverse the links of the relevant passive nodes, goto first breakpoint
+ -- reverse the links of the relevant passive nodes, goto first breakpoint
- local current_break = nil
+ local current_break = nil
- local break_node = par.best_bet.break_node
- repeat
- local first_break = break_node
- break_node = break_node.prev_break
- first_break.prev_break = current_break
- current_break = first_break
- until not break_node
+ local break_node = par.best_bet.break_node
+ repeat
+ local first_break = break_node
+ break_node = break_node.prev_break
+ first_break.prev_break = current_break
+ current_break = first_break
+ until not break_node
- local head = par.head
+ local head = par.head
- -- maybe : each_...
+ -- maybe : each_...
- while current_break do
+ while current_break do
- inject_dirs_at_begin_of_line(stack,head)
+ inject_dirs_at_begin_of_line(stack,head)
- local disc_break = false
- local post_disc_break = false
- local glue_break = false
+ local disc_break = false
+ local post_disc_break = false
+ local glue_break = false
- local lineend = nil -- q lineend refers to the last node of the line (and paragraph)
- local lastnode = current_break.cur_break -- r lastnode refers to the node after which the dir nodes should be closed
+ local lineend = nil -- lineend : the last node of the line (and paragraph)
+ local lastnode = current_break.cur_break -- lastnode: the node after which the dir nodes should be closed
- if not lastnode then
- -- only at the end
- lastnode = slide_node_list(head) -- todo: find_tail
- if lastnode == par.final_par_glue then
- lineend = lastnode
- lastnode = getprev(lastnode)
- end
- else -- todo: use insert_list_after
- local id = getid(lastnode)
- if id == glue_code then
- -- lastnode is normal skip
- lastnode = replace_node(lastnode,new_rightskip(rightskip))
- glue_break = true
- lineend = lastnode
- lastnode = getprev(lastnode)
- elseif id == disc_code then
- local prevlast = getprev(lastnode)
- local nextlast = getnext(lastnode)
- local subtype = getsubtype(lastnode)
- local pre, post, replace, pretail, posttail, replacetail = getdisc(lastnode,true)
- if subtype == second_disc_code then
- if not (getid(prevlast) == disc_code and getsubtype(prevlast) == first_disc_code) then
- report_parbuilders('unsupported disc at location %a',3)
- end
- if pre then
- flush_node_list(pre)
- pre = nil -- signal
+ if not lastnode then
+ -- only at the end
+ lastnode = slide_node_list(head) -- todo: find_tail
+ if lastnode == par.final_par_glue then
+ lineend = lastnode
+ lastnode = getprev(lastnode)
+ end
+ else -- todo: use insert_list_after
+ local id = getid(lastnode)
+ if id == glue_code then
+ -- lastnode is normal skip
+ lastnode = replace_node(lastnode,new_rightskip(rightskip))
+ glue_break = true
+ lineend = lastnode
+ lastnode = getprev(lastnode)
+ elseif id == disc_code then
+ local prevlast = getprev(lastnode)
+ local nextlast = getnext(lastnode)
+ local subtype = getsubtype(lastnode)
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(lastnode,true)
+ if subtype == seconddisc_code then
+ if not (getid(prevlast) == disc_code and getsubtype(prevlast) == firstdisc_code) then
+ report_parbuilders('unsupported disc at location %a',3)
+ end
+ if pre then
+ flush_node_list(pre)
+ pre = nil -- signal
+ end
+ if replace then
+ setlink(prevlast,replace)
+ setlink(replacetail,lastnode)
+ replace = nil -- signal
+ end
+ setdisc(lastnode,pre,post,replace)
+ local pre, post, replace = getdisc(prevlast)
+ if pre then
+ flush_node_list(pre)
+ end
+ if replace then
+ flush_node_list(replace)
+ end
+ if post then
+ flush_node_list(post)
+ end
+ setdisc(prevlast) -- nil,nil,nil
+ elseif subtype == firstdisc_code then
+ -- what is v ... next probably
+ if not (getid(v) == disc_code and getsubtype(v) == seconddisc_code) then
+ report_parbuilders('unsupported disc at location %a',4)
+ end
+ setsubtype(nextlast,regulardisc_code)
+ setfield(nextlast,"replace",post)
+ setfield(lastnode,"post") -- nil
end
if replace then
- setlink(prevlast,replace)
- setlink(replacetail,lastnode)
- replace = nil -- signal
+ flush_node_list(replace)
end
- setdisc(lastnode,pre,post,replace)
- local pre, post, replace = getdisc(prevlast)
if pre then
- flush_node_list(pre)
- end
- if replace then
- flush_node_list(replace)
+ setlink(prevlast,pre)
+ setlink(pretail,lastnode)
end
if post then
- flush_node_list(post)
- end
- setdisc(prevlast) -- nil,nil,nil
- elseif subtype == first_disc_code then
- -- what is v ... next probably
- if not (getid(v) == disc_code and getsubtype(v) == second_disc_code) then
- report_parbuilders('unsupported disc at location %a',4)
+ setlink(lastnode,post)
+ setlink(posttail,nextlast)
+ post_disc_break = true
end
- setsubtype(nextlast,regular_disc_code)
- setfield(nextlast,"replace",post)
- setfield(lastnode,"post") -- nil
- end
- if replace then
- flush_node_list(replace)
+ setdisc(lastnode) -- nil, nil, nil
+ disc_break = true
+ elseif id == kern_code then
+ setkern(lastnode,0)
+ elseif getid(lastnode) == math_code then
+ setkern(lastnode,0) -- surround
+ -- new in luatex
+ setglue(lastnode) -- zeros
end
- if pre then
- setlink(prevlast,pre)
- setlink(pretail,lastnode)
+ end
+ lastnode = inject_dirs_at_end_of_line(stack,lastnode,getnext(head),current_break.cur_break)
+ local rightbox = current_break.passive_right_box
+ if rightbox then
+ lastnode = insert_node_after(lastnode,lastnode,copy_node(rightbox))
+ end
+ if not lineend then
+ lineend = lastnode
+ end
+ if lineend and lineend ~= head and protrude_chars > 0 then
+ local id = getid(lineend)
+ local c = (disc_break and (id == glyph_code or id ~= disc_code) and lineend) or getprev(lineend)
+ local p = find_protchar_right(getnext(head),c)
+ if p and getid(p) == glyph_code then
+ local w, last_rightmost_char = right_pw(p)
+ if last_rightmost_char and w ~= 0 then
+ -- so we inherit attributes, lineend is new pseudo head
+ lineend, c = insert_node_after(lineend,c,new_rightmarginkern(copy_node(last_rightmost_char),-w))
+ end
end
- if post then
- setlink(lastnode,post)
- setlink(posttail,nextlast)
- post_disc_break = true
+ end
+ -- we finish the line
+ local r = getnext(lineend)
+ setnext(lineend)
+ if not glue_break then
+ if rightskip then
+ insert_node_after(lineend,lineend,new_rightskip(right_skip)) -- lineend moves on as pseudo head
end
- setdisc(lastnode) -- nil, nil, nil
- disc_break = true
- elseif id == kern_code then
- setkern(lastnode,0)
- elseif getid(lastnode) == math_code then
- 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)
- local rightbox = current_break.passive_right_box
- if rightbox then
- lastnode = insert_node_after(lastnode,lastnode,copy_node(rightbox))
- end
- if not lineend then
- lineend = lastnode
- end
- if lineend and lineend ~= head and protrude_chars > 0 then
- local id = getid(lineend)
- local c = (disc_break and (id == glyph_code or id ~= disc_code) and lineend) or getprev(lineend)
- local p = find_protchar_right(getnext(head),c)
- if p and getid(p) == glyph_code then
- local w, last_rightmost_char = right_pw(p)
- if last_rightmost_char and w ~= 0 then
- -- so we inherit attributes, lineend is new pseudo head
- lineend, c = insert_node_after(lineend,c,new_rightmarginkern(copy_node(last_rightmost_char),-w))
+ -- each time ?
+ local q = getnext(head)
+ setlink(head,r)
+ -- insert leftbox (if needed after parindent)
+ local leftbox = current_break.passive_left_box
+ if leftbox then
+ local first = getnext(q)
+ if first and current_line == (par.first_line + 1) and getid(first) == hlist_code and not getlist(first) then
+ insert_node_after(q,q,copy_node(leftbox))
+ else
+ q = insert_node_before(q,q,copy_node(leftbox))
end
end
- end
- -- we finish the line
- local r = getnext(lineend)
- setnext(lineend)
- if not glue_break then
- if rightskip then
- insert_node_after(lineend,lineend,new_rightskip(right_skip)) -- lineend moves on as pseudo head
+ if protrude_chars > 0 then
+ local p = find_protchar_left(q)
+ if p and getid(p) == glyph_code then
+ local w, last_leftmost_char = left_pw(p)
+ if last_leftmost_char and w ~= 0 then
+ -- so we inherit attributes, q is pseudo head and moves back
+ q = insert_node_before(q,q,new_leftmarginkern(copy_node(last_leftmost_char),-w))
+ end
+ end
end
- end
- -- each time ?
- local q = getnext(head)
- setlink(head,r)
- -- insert leftbox (if needed after parindent)
- local leftbox = current_break.passive_left_box
- if leftbox then
- local first = getnext(q)
- if first and current_line == (par.first_line + 1) and getid(first) == hlist_code and not getlist(first) then
- insert_node_after(q,q,copy_node(leftbox))
+ if leftskip then
+ q = insert_node_before(q,q,new_leftskip(leftskip))
+ end
+ local cur_width, cur_indent
+ if current_line > par.last_special_line then
+ cur_indent = par.second_indent
+ cur_width = par.second_width
+ elseif parshape then
+ local shape = parshape[current_line]
+ cur_indent = shape[1]
+ cur_width = shape[2]
else
- q = insert_node_before(q,q,copy_node(leftbox))
- end
- end
- if protrude_chars > 0 then
- local p = find_protchar_left(q)
- if p and getid(p) == glyph_code then
- local w, last_leftmost_char = left_pw(p)
- if last_leftmost_char and w ~= 0 then
- -- so we inherit attributes, q is pseudo head and moves back
- q = insert_node_before(q,q,new_leftmarginkern(copy_node(last_leftmost_char),-w))
- end
+ cur_indent = par.first_indent
+ cur_width = par.first_width
end
- end
- if leftskip then
- q = insert_node_before(q,q,new_leftskip(leftskip))
- end
- local cur_width, cur_indent
- if current_line > par.last_special_line then
- cur_indent = par.second_indent
- cur_width = par.second_width
- elseif parshape then
- local shape = parshape[current_line]
- cur_indent = shape[1]
- cur_width = shape[2]
- else
- cur_indent = par.first_indent
- cur_width = par.first_width
- end
- if adapt_width then -- extension
- local l, r = adapt_width(par,current_line)
- cur_indent = cur_indent + l
- cur_width = cur_width - l - r
- end
+ if adapt_width then -- extension
+ local l, r = adapt_width(par,current_line)
+ cur_indent = cur_indent + l
+ cur_width = cur_width - l - r
+ end
- statistics.noflines = statistics.noflines + 1
- local finished_line = nil
- if adjust_spacing > 0 then
- statistics.nofadjustedlines = statistics.nofadjustedlines + 1
- finished_line = xpack_nodes(q,cur_width,"cal_expand_ratio",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis)
- else
- finished_line = xpack_nodes(q,cur_width,"exactly",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis)
- end
- if protrude_chars > 0 then
- statistics.nofprotrudedlines = statistics.nofprotrudedlines + 1
- end
- -- wrong:
- local adjust_head = texlists.adjust_head
- local pre_adjust_head = texlists.pre_adjust_head
- --
- setshift(finished_line,cur_indent)
- --
- -- -- this is gone:
- --
- -- if par.each_line_height ~= ignored_dimen then
- -- setheight(finished_line,par.each_line_height)
- -- end
- -- if par.each_line_depth ~= ignored_dimen then
- -- setdepth(finished_line,par.each_line_depth)
- -- end
- -- if par.first_line_height ~= ignored_dimen and (current_line == par.first_line + 1) then
- -- setheight(finished_line,par.first_line_height)
- -- end
- -- if par.last_line_depth ~= ignored_dimen and current_line + 1 == par.best_line then
- -- setdepth(finished_line,par.last_line_depth)
- -- end
- --
- if texlists.pre_adjust_head ~= pre_adjust_head then
- append_list(par, texlists.pre_adjust_head)
- texlists.pre_adjust_head = pre_adjust_head
- end
- append_to_vlist(par,finished_line)
- if texlists.adjust_head ~= adjust_head then
- append_list(par, texlists.adjust_head)
- texlists.adjust_head = adjust_head
- end
- --
- local pen
- if current_line + 1 ~= par.best_line then
- if current_break.passive_pen_inter then
- pen = current_break.passive_pen_inter
+ statistics.noflines = statistics.noflines + 1
+ local finished_line = nil
+ if adjust_spacing > 0 then
+ statistics.nofadjustedlines = statistics.nofadjustedlines + 1
+ finished_line = xpack_nodes(q,cur_width,"cal_expand_ratio",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis)
else
- pen = par.inter_line_penalty
- end
- if current_line == prevgraf + 1 then
- pen = pen + par.club_penalty
- end
- if current_line + 2 == par.best_line then
- if par.display then
- pen = pen + par.display_widow_penalty
+ finished_line = xpack_nodes(q,cur_width,"exactly",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis)
+ end
+ if protrude_chars > 0 then
+ statistics.nofprotrudedlines = statistics.nofprotrudedlines + 1
+ end
+ -- wrong:
+ local adjust_head = texlists.adjust_head
+ local pre_adjust_head = texlists.pre_adjust_head
+ --
+ setshift(finished_line,cur_indent)
+ --
+ -- -- this is gone:
+ --
+ -- if par.each_line_height ~= ignored_dimen then
+ -- setheight(finished_line,par.each_line_height)
+ -- end
+ -- if par.each_line_depth ~= ignored_dimen then
+ -- setdepth(finished_line,par.each_line_depth)
+ -- end
+ -- if par.first_line_height ~= ignored_dimen and (current_line == par.first_line + 1) then
+ -- setheight(finished_line,par.first_line_height)
+ -- end
+ -- if par.last_line_depth ~= ignored_dimen and current_line + 1 == par.best_line then
+ -- setdepth(finished_line,par.last_line_depth)
+ -- end
+ --
+ if texlists.pre_adjust_head ~= pre_adjust_head then
+ append_list(par, texlists.pre_adjust_head)
+ texlists.pre_adjust_head = pre_adjust_head
+ end
+ append_to_vlist(par,finished_line)
+ if texlists.adjust_head ~= adjust_head then
+ append_list(par, texlists.adjust_head)
+ texlists.adjust_head = adjust_head
+ end
+ --
+ local pen
+ if current_line + 1 ~= par.best_line then
+ if current_break.passive_pen_inter then
+ pen = current_break.passive_pen_inter
else
- pen = pen + par.widow_penalty
+ pen = par.inter_line_penalty
end
- end
- if disc_break then
- if current_break.passive_pen_broken ~= 0 then
- pen = pen + current_break.passive_pen_broken
- else
- pen = pen + par.broken_penalty
+ if current_line == prevgraf + 1 then
+ pen = pen + par.club_penalty
end
- end
- if pen ~= 0 then
- append_to_vlist(par,new_penalty(pen))
- end
- end
- current_line = current_line + 1
- current_break = current_break.prev_break
- if current_break and not post_disc_break then
- local current = head
- local next = nil
- while true do
- next = getnext(current)
- if next == current_break.cur_break then
- break
+ if current_line + 2 == par.best_line then
+ if par.display then
+ pen = pen + par.display_widow_penalty
+ else
+ pen = pen + par.widow_penalty
+ end
end
- 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
- setkern(next,0) -- surround
- -- new in luatex
- setglue(lastnode) -- zeros
- break
- elseif id == kern_code then
- local subtype = getsubtype(next)
- if subtype == fontkern_code or subtype == accentkern_code then
- -- fontkerns and accent kerns as well as otf injections
- break
+ if disc_break then
+ if current_break.passive_pen_broken ~= 0 then
+ pen = pen + current_break.passive_pen_broken
+ else
+ pen = pen + par.broken_penalty
end
end
- current = next
+ if pen ~= 0 then
+ append_to_vlist(par,new_penalty(pen))
+ end
end
- if current ~= head then
- setnext(current)
- flush_node_list(getnext(head))
- setlink(head,next)
+ current_line = current_line + 1
+ current_break = current_break.prev_break
+ if current_break and not post_disc_break then
+ local current = head
+ local next = nil
+ while true do
+ next = getnext(current)
+ if next == current_break.cur_break then
+ break
+ end
+ 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
+ setkern(next,0) -- surround
+ -- new in luatex
+ setglue(lastnode) -- zeros
+ break
+ elseif id == kern_code then
+ local subtype = getsubtype(next)
+ if subtype == fontkern_code or subtype == accentkern_code then
+ -- fontkerns and accent kerns as well as otf injections
+ break
+ end
+ end
+ current = next
+ end
+ if current ~= head then
+ setnext(current)
+ flush_node_list(getnext(head))
+ setlink(head,next)
+ end
end
end
- end
- -- if current_line ~= par.best_line then
- -- report_parbuilders("line breaking")
- -- end
- par.head = nil -- needs checking
- current_line = current_line - 1
- if trace_basic then
- report_parbuilders("paragraph broken into %a lines",current_line)
- end
- texnest[texnest.ptr].prevgraf = current_line
-end
-
-local function wrap_up(par)
- if par.tracing_paragraphs then
- diagnostics.stop()
- end
- if par.do_last_line_fit then
- local best_bet = par.best_bet
- local active_short = best_bet.active_short
- local active_glue = best_bet.active_glue
- if active_short == 0 then
- if trace_lastlinefit then
- report_parbuilders("disabling last line fit, no active_short")
- end
- par.do_last_line_fit = false
- else
- local glue = par.final_par_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)
- end
+ -- if current_line ~= par.best_line then
+ -- report_parbuilders("line breaking")
+ -- end
+ par.head = nil -- needs checking
+ current_line = current_line - 1
+ if trace_basic then
+ report_parbuilders("paragraph broken into %a lines",current_line)
end
+ texnest[texnest.ptr].prevgraf = current_line
end
- -- we have a bunch of glue and and temp nodes not freed
- local head = par.head
- if getid(head) == temp_code then
- par.head = getnext(head)
- flush_node(head)
- end
- post_line_break(par)
- reset_meta(par)
- register_statistics(par)
- return par.head_field
-end
--- we could do active nodes differently ... table instead of linked list or a list
--- with prev nodes but it doesn't save much (as we still need to keep indices then
--- in next)
-
-local function deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) -- no need for adjust if disabled
- local active = par.active
- local active_width = par.active_width
- prev_r.next = r.next
- -- removes r
- -- r = nil
- if prev_r == active then
- r = active.next
- if r.id == delta_code then
- local aw = active_width.size + r.size active_width.size = aw cur_active_width.size = aw
- local aw = active_width.stretch + r.stretch active_width.stretch = aw cur_active_width.stretch = aw
- local aw = active_width.fi + r.fi active_width.fi = aw cur_active_width.fi = aw
- local aw = active_width.fil + r.fil active_width.fil = aw cur_active_width.fil = aw
- local aw = active_width.fill + r.fill active_width.fill = aw cur_active_width.fill = aw
- local aw = active_width.filll + r.filll active_width.filll = aw cur_active_width.filll = aw
- local aw = active_width.shrink + r.shrink active_width.shrink = aw cur_active_width.shrink = aw
- if checked_expansion then
- local aw = active_width.adjust_stretch + r.adjust_stretch active_width.adjust_stretch = aw cur_active_width.adjust_stretch = aw
- local aw = active_width.adjust_shrink + r.adjust_shrink active_width.adjust_shrink = aw cur_active_width.adjust_shrink = aw
- end
- active.next = r.next
- -- removes r
- -- r = nil
+ local function wrap_up(par)
+ if par.tracing_paragraphs then
+ diagnostics.stop()
end
- elseif prev_r.id == delta_code then
- r = prev_r.next
- if r == active then
- cur_active_width.size = cur_active_width.size - prev_r.size
- cur_active_width.stretch = cur_active_width.stretch - prev_r.stretch
- cur_active_width.fi = cur_active_width.fi - prev_r.fi
- cur_active_width.fil = cur_active_width.fil - prev_r.fil
- cur_active_width.fill = cur_active_width.fill - prev_r.fill
- cur_active_width.filll = cur_active_width.filll - prev_r.filll
- cur_active_width.shrink = cur_active_width.shrink - prev_r.shrink
- if checked_expansion then
- cur_active_width.adjust_stretch = cur_active_width.adjust_stretch - prev_r.adjust_stretch
- cur_active_width.adjust_shrink = cur_active_width.adjust_shrink - prev_r.adjust_shrink
+ if par.do_last_line_fit then
+ local best_bet = par.best_bet
+ local active_short = best_bet.active_short
+ local active_glue = best_bet.active_glue
+ if active_short == 0 then
+ if trace_lastlinefit then
+ report_parbuilders("disabling last line fit, no active_short")
+ end
+ par.do_last_line_fit = false
+ else
+ local glue = par.final_par_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)
+ end
end
- prev_prev_r.next = active
- -- removes prev_r
- -- prev_r = nil
- prev_r = prev_prev_r
- elseif r.id == delta_code then
- local rn = r.size cur_active_width.size = cur_active_width.size + rn prev_r.size = prev_r.size + rn
- local rn = r.stretch cur_active_width.stretch = cur_active_width.stretch + rn prev_r.stretch = prev_r.stretch + rn
- local rn = r.fi cur_active_width.fi = cur_active_width.fi + rn prev_r.fi = prev_r.fi + rn
- local rn = r.fil cur_active_width.fil = cur_active_width.fil + rn prev_r.fil = prev_r.fil + rn
- local rn = r.fill cur_active_width.fill = cur_active_width.fill + rn prev_r.fill = prev_r.fill + rn
- local rn = r.filll cur_active_width.filll = cur_active_width.filll + rn prev_r.filll = prev_r.fill + rn
- local rn = r.shrink cur_active_width.shrink = cur_active_width.shrink + rn prev_r.shrink = prev_r.shrink + rn
- if checked_expansion then
- local rn = r.adjust_stretch cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + rn prev_r.adjust_stretch = prev_r.adjust_stretch + rn
- local rn = r.adjust_shrink cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + rn prev_r.adjust_shrink = prev_r.adjust_shrink + rn
+ end
+ -- we have a bunch of glue and and temp nodes not freed
+ local head = par.head
+ if getid(head) == temp_code then
+ par.head = getnext(head)
+ flush_node(head)
+ end
+ post_line_break(par)
+ reset_meta(par)
+ register_statistics(par)
+ return par.head_field
+ end
+
+ -- we could do active nodes differently ... table instead of linked list or a list
+ -- with prev nodes but it doesn't save much (as we still need to keep indices then
+ -- in next)
+
+ local function deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) -- no need for adjust if disabled
+ local active = par.active
+ local active_width = par.active_width
+ prev_r.next = r.next
+ -- removes r
+ -- r = nil
+ if prev_r == active then
+ r = active.next
+ if r.id == delta_code then
+ local aw = active_width.size + r.size active_width.size = aw cur_active_width.size = aw
+ local aw = active_width.stretch + r.stretch active_width.stretch = aw cur_active_width.stretch = aw
+ local aw = active_width.fi + r.fi active_width.fi = aw cur_active_width.fi = aw
+ local aw = active_width.fil + r.fil active_width.fil = aw cur_active_width.fil = aw
+ local aw = active_width.fill + r.fill active_width.fill = aw cur_active_width.fill = aw
+ local aw = active_width.filll + r.filll active_width.filll = aw cur_active_width.filll = aw
+ local aw = active_width.shrink + r.shrink active_width.shrink = aw cur_active_width.shrink = aw
+ if checked_expansion then
+ local aw = active_width.adjust_stretch + r.adjust_stretch active_width.adjust_stretch = aw cur_active_width.adjust_stretch = aw
+ local aw = active_width.adjust_shrink + r.adjust_shrink active_width.adjust_shrink = aw cur_active_width.adjust_shrink = aw
+ end
+ active.next = r.next
+ -- removes r
+ -- r = nil
+ end
+ elseif prev_r.id == delta_code then
+ r = prev_r.next
+ if r == active then
+ cur_active_width.size = cur_active_width.size - prev_r.size
+ cur_active_width.stretch = cur_active_width.stretch - prev_r.stretch
+ cur_active_width.fi = cur_active_width.fi - prev_r.fi
+ cur_active_width.fil = cur_active_width.fil - prev_r.fil
+ cur_active_width.fill = cur_active_width.fill - prev_r.fill
+ cur_active_width.filll = cur_active_width.filll - prev_r.filll
+ cur_active_width.shrink = cur_active_width.shrink - prev_r.shrink
+ if checked_expansion then
+ cur_active_width.adjust_stretch = cur_active_width.adjust_stretch - prev_r.adjust_stretch
+ cur_active_width.adjust_shrink = cur_active_width.adjust_shrink - prev_r.adjust_shrink
+ end
+ prev_prev_r.next = active
+ -- removes prev_r
+ -- prev_r = nil
+ prev_r = prev_prev_r
+ elseif r.id == delta_code then
+ local rn = r.size cur_active_width.size = cur_active_width.size + rn prev_r.size = prev_r.size + rn
+ local rn = r.stretch cur_active_width.stretch = cur_active_width.stretch + rn prev_r.stretch = prev_r.stretch + rn
+ local rn = r.fi cur_active_width.fi = cur_active_width.fi + rn prev_r.fi = prev_r.fi + rn
+ local rn = r.fil cur_active_width.fil = cur_active_width.fil + rn prev_r.fil = prev_r.fil + rn
+ local rn = r.fill cur_active_width.fill = cur_active_width.fill + rn prev_r.fill = prev_r.fill + rn
+ local rn = r.filll cur_active_width.filll = cur_active_width.filll + rn prev_r.filll = prev_r.fill + rn
+ local rn = r.shrink cur_active_width.shrink = cur_active_width.shrink + rn prev_r.shrink = prev_r.shrink + rn
+ if checked_expansion then
+ local rn = r.adjust_stretch cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + rn prev_r.adjust_stretch = prev_r.adjust_stretch + rn
+ local rn = r.adjust_shrink cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + rn prev_r.adjust_shrink = prev_r.adjust_shrink + rn
+ end
+ prev_r.next = r.next
+ -- removes r
+ -- r = nil
end
- prev_r.next = r.next
- -- removes r
- -- r = nil
end
+ return prev_r, r
end
- return prev_r, r
-end
-local function lastlinecrap(shortfall,active_short,active_glue,cur_active_width,fill_width,last_line_fit)
- if active_short == 0 or active_glue <= 0 then
- return false, 0, fit_decent_class, 0, 0
- end
- if cur_active_width.fi ~= fill_width.fi or cur_active_width.fil ~= fill_width.fil or cur_active_width.fill ~= fill_width.fill or cur_active_width.filll ~= fill_width.filll then
- return false, 0, fit_decent_class, 0, 0
- end
- local adjustment = active_short > 0 and cur_active_width.stretch or cur_active_width.shrink
- if adjustment <= 0 then
- return false, 0, fit_decent_class, adjustment, 0
- end
- adjustment = calculate_fraction(adjustment,active_short,active_glue,maxdimen)
- if last_line_fit < 1000 then
- adjustment = calculate_fraction(adjustment,last_line_fit,1000,maxdimen) -- uses previous adjustment
- end
- local fit_class = fit_decent_class
- if adjustment > 0 then
- local stretch = cur_active_width.stretch
- if adjustment > shortfall then
- adjustment = shortfall
- end
- if adjustment > 7230584 and stretch < 1663497 then
- return true, fit_very_loose_class, shortfall, adjustment, infinite_badness
+ local function lastlinecrap(shortfall,active_short,active_glue,cur_active_width,fill_width,last_line_fit)
+ if active_short == 0 or active_glue <= 0 then
+ return false, 0, fit_decent_class, 0, 0
end
- -- if adjustment == 0 then -- badness = 0
- -- return true, shortfall, fit_decent_class, 0, 0
- -- elseif stretch <= 0 then -- badness = 10000
- -- return true, shortfall, fit_very_loose_class, adjustment, 10000
- -- end
- -- local badness = (adjustment == 0 and 0) or (stretch <= 0 and 10000) or calculate_badness(adjustment,stretch)
- local badness = calculate_badness(adjustment,stretch)
- if badness > 99 then
- return true, shortfall, fit_very_loose_class, adjustment, badness
- elseif badness > 12 then
- return true, shortfall, fit_loose_class, adjustment, badness
- else
- return true, shortfall, fit_decent_class, adjustment, badness
+ if cur_active_width.fi ~= fill_width.fi or cur_active_width.fil ~= fill_width.fil or cur_active_width.fill ~= fill_width.fill or cur_active_width.filll ~= fill_width.filll then
+ return false, 0, fit_decent_class, 0, 0
end
- elseif adjustment < 0 then
- local shrink = cur_active_width.shrink
- if -adjustment > shrink then
- adjustment = -shrink
+ local adjustment = active_short > 0 and cur_active_width.stretch or cur_active_width.shrink
+ if adjustment <= 0 then
+ return false, 0, fit_decent_class, adjustment, 0
end
- local badness = calculate_badness(-adjustment,shrink)
- if badness > 12 then
- return true, shortfall, fit_tight_class, adjustment, badness
- else
- return true, shortfall, fit_decent_class, adjustment, badness
+ adjustment = calculate_fraction(adjustment,active_short,active_glue,maxdimen)
+ if last_line_fit < 1000 then
+ adjustment = calculate_fraction(adjustment,last_line_fit,1000,maxdimen) -- uses previous adjustment
end
- else
- return false, 0, fit_decent_class, 0, 0
- end
-end
-
--- todo: statistics .. count tries and so
-
-local trialcount = 0
-
-local function try_break(pi, break_type, par, first_p, current, checked_expansion)
-
--- trialcount = trialcount + 1
--- print(trialcount,pi,break_type,current,nuts.tostring(current))
-
- if pi >= infinite_penalty then -- this breakpoint is inhibited by infinite penalty
- local p_active = par.active
- return p_active, p_active and p_active.next
- elseif pi <= -infinite_penalty then -- this breakpoint will be forced
- pi = eject_penalty
- end
-
- local prev_prev_r = nil -- a step behind prev_r, if type(prev_r)=delta_code
- local prev_r = par.active -- stays a step behind r
- local r = nil -- runs through the active list
- local no_break_yet = true -- have we found a feasible break at current?
- local node_r_stays_active = false -- should node r remain in the active list?
- local line_width = 0 -- the current line will be justified to this width
- local line_number = 0 -- line number of current active node
- local old_line_number = 0 -- maximum line number in current equivalence class of lines
-
- local protrude_chars = par.protrude_chars
- local checked_expansion = par.checked_expansion
- local break_width = par.break_width
- local active_width = par.active_width
- local background = par.background
- local minimal_demerits = par.minimal_demerits
- local best_place = par.best_place
- local best_pl_line = par.best_pl_line
- local best_pl_short = par.best_pl_short
- local best_pl_glue = par.best_pl_glue
- local do_last_line_fit = par.do_last_line_fit
- local final_pass = par.final_pass
- local tracing_paragraphs = par.tracing_paragraphs
- -- local par_active = par.active
-
- local adapt_width = par.adapt_width
-
- local parshape = par.par_shape_ptr
-
- local cur_active_width = checked_expansion and { -- distance from current active node
- size = active_width.size,
- stretch = active_width.stretch,
- fi = active_width.fi,
- fil = active_width.fil,
- fill = active_width.fill,
- filll = active_width.filll,
- shrink = active_width.shrink,
- adjust_stretch = active_width.adjust_stretch,
- adjust_shrink = active_width.adjust_shrink,
- } or {
- size = active_width.size,
- stretch = active_width.stretch,
- fi = active_width.fi,
- fil = active_width.fil,
- fill = active_width.fill,
- filll = active_width.filll,
- shrink = active_width.shrink,
- }
-
- while true do
- r = prev_r.next
- if r.id == delta_code then
- cur_active_width.size = cur_active_width.size + r.size
- cur_active_width.stretch = cur_active_width.stretch + r.stretch
- cur_active_width.fi = cur_active_width.fi + r.fi
- cur_active_width.fil = cur_active_width.fil + r.fil
- cur_active_width.fill = cur_active_width.fill + r.fill
- cur_active_width.filll = cur_active_width.filll + r.filll
- cur_active_width.shrink = cur_active_width.shrink + r.shrink
- if checked_expansion then
- cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + r.adjust_stretch
- cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + r.adjust_shrink
+ local fit_class = fit_decent_class
+ if adjustment > 0 then
+ local stretch = cur_active_width.stretch
+ if adjustment > shortfall then
+ adjustment = shortfall
+ end
+ if adjustment > 7230584 and stretch < 1663497 then
+ return true, fit_very_loose_class, shortfall, adjustment, infinite_badness
+ end
+ -- if adjustment == 0 then -- badness = 0
+ -- return true, shortfall, fit_decent_class, 0, 0
+ -- elseif stretch <= 0 then -- badness = 10000
+ -- return true, shortfall, fit_very_loose_class, adjustment, 10000
+ -- end
+ -- local badness = (adjustment == 0 and 0) or (stretch <= 0 and 10000) or calculate_badness(adjustment,stretch)
+ local badness = calculate_badness(adjustment,stretch)
+ if badness > 99 then
+ return true, shortfall, fit_very_loose_class, adjustment, badness
+ elseif badness > 12 then
+ return true, shortfall, fit_loose_class, adjustment, badness
+ else
+ return true, shortfall, fit_decent_class, adjustment, badness
+ end
+ elseif adjustment < 0 then
+ local shrink = cur_active_width.shrink
+ if -adjustment > shrink then
+ adjustment = -shrink
+ end
+ local badness = calculate_badness(-adjustment,shrink)
+ if badness > 12 then
+ return true, shortfall, fit_tight_class, adjustment, badness
+ else
+ return true, shortfall, fit_decent_class, adjustment, badness
end
- prev_prev_r = prev_r
- prev_r = r
else
- line_number = r.line_number
- if line_number > old_line_number then
- local minimum_demerits = par.minimum_demerits
- if minimum_demerits < awful_badness and (old_line_number ~= par.easy_line or r == par.active) then
- if no_break_yet then
- no_break_yet = false
- break_width.size = background.size
- break_width.stretch = background.stretch
- break_width.fi = background.fi
- break_width.fil = background.fil
- break_width.fill = background.fill
- break_width.filll = background.filll
- break_width.shrink = background.shrink
- if checked_expansion then
- break_width.adjust_stretch = 0
- break_width.adjust_shrink = 0
+ return false, 0, fit_decent_class, 0, 0
+ end
+ end
+
+ -- todo: statistics .. count tries and so
+
+ local trialcount = 0
+
+ local function try_break(pi, break_type, par, first_p, current, checked_expansion)
+
+ -- trialcount = trialcount + 1
+ -- print(trialcount,pi,break_type,current,nuts.tostring(current))
+
+ if pi >= infinite_penalty then -- this breakpoint is inhibited by infinite penalty
+ local p_active = par.active
+ return p_active, p_active and p_active.next
+ elseif pi <= -infinite_penalty then -- this breakpoint will be forced
+ pi = eject_penalty
+ end
+
+ local prev_prev_r = nil -- a step behind prev_r, if type(prev_r)=delta_code
+ local prev_r = par.active -- stays a step behind r
+ local r = nil -- runs through the active list
+ local no_break_yet = true -- have we found a feasible break at current?
+ local node_r_stays_active = false -- should node r remain in the active list?
+ local line_width = 0 -- the current line will be justified to this width
+ local line_number = 0 -- line number of current active node
+ local old_line_number = 0 -- maximum line number in current equivalence class of lines
+
+ local protrude_chars = par.protrude_chars
+ local checked_expansion = par.checked_expansion
+ local break_width = par.break_width
+ local active_width = par.active_width
+ local background = par.background
+ local minimal_demerits = par.minimal_demerits
+ local best_place = par.best_place
+ local best_pl_line = par.best_pl_line
+ local best_pl_short = par.best_pl_short
+ local best_pl_glue = par.best_pl_glue
+ local do_last_line_fit = par.do_last_line_fit
+ local final_pass = par.final_pass
+ local tracing_paragraphs = par.tracing_paragraphs
+ -- local par_active = par.active
+
+ local adapt_width = par.adapt_width
+
+ local parshape = par.par_shape_ptr
+
+ local cur_active_width = checked_expansion and { -- distance from current active node
+ size = active_width.size,
+ stretch = active_width.stretch,
+ fi = active_width.fi,
+ fil = active_width.fil,
+ fill = active_width.fill,
+ filll = active_width.filll,
+ shrink = active_width.shrink,
+ adjust_stretch = active_width.adjust_stretch,
+ adjust_shrink = active_width.adjust_shrink,
+ } or {
+ size = active_width.size,
+ stretch = active_width.stretch,
+ fi = active_width.fi,
+ fil = active_width.fil,
+ fill = active_width.fill,
+ filll = active_width.filll,
+ shrink = active_width.shrink,
+ }
+
+ while true do
+ r = prev_r.next
+ if r.id == delta_code then
+ cur_active_width.size = cur_active_width.size + r.size
+ cur_active_width.stretch = cur_active_width.stretch + r.stretch
+ cur_active_width.fi = cur_active_width.fi + r.fi
+ cur_active_width.fil = cur_active_width.fil + r.fil
+ cur_active_width.fill = cur_active_width.fill + r.fill
+ cur_active_width.filll = cur_active_width.filll + r.filll
+ cur_active_width.shrink = cur_active_width.shrink + r.shrink
+ if checked_expansion then
+ cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + r.adjust_stretch
+ cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + r.adjust_shrink
+ end
+ prev_prev_r = prev_r
+ prev_r = r
+ else
+ line_number = r.line_number
+ if line_number > old_line_number then
+ local minimum_demerits = par.minimum_demerits
+ if minimum_demerits < awful_badness and (old_line_number ~= par.easy_line or r == par.active) then
+ if no_break_yet then
+ no_break_yet = false
+ break_width.size = background.size
+ break_width.stretch = background.stretch
+ break_width.fi = background.fi
+ break_width.fil = background.fil
+ break_width.fill = background.fill
+ break_width.filll = background.filll
+ break_width.shrink = background.shrink
+ if checked_expansion then
+ break_width.adjust_stretch = 0
+ break_width.adjust_shrink = 0
+ end
+ if current then
+ compute_break_width(par,break_type,current)
+ end
end
- if current then
- compute_break_width(par,break_type,current)
+ if prev_r.id == delta_code then
+ prev_r.size = prev_r.size - cur_active_width.size + break_width.size
+ prev_r.stretch = prev_r.stretch - cur_active_width.stretc + break_width.stretch
+ prev_r.fi = prev_r.fi - cur_active_width.fi + break_width.fi
+ prev_r.fil = prev_r.fil - cur_active_width.fil + break_width.fil
+ prev_r.fill = prev_r.fill - cur_active_width.fill + break_width.fill
+ prev_r.filll = prev_r.filll - cur_active_width.filll + break_width.filll
+ prev_r.shrink = prev_r.shrink - cur_active_width.shrink + break_width.shrink
+ if checked_expansion then
+ prev_r.adjust_stretch = prev_r.adjust_stretch - cur_active_width.adjust_stretch + break_width.adjust_stretch
+ prev_r.adjust_shrink = prev_r.adjust_shrink - cur_active_width.adjust_shrink + break_width.adjust_shrink
+ end
+ elseif prev_r == par.active then
+ active_width.size = break_width.size
+ active_width.stretch = break_width.stretch
+ active_width.fi = break_width.fi
+ active_width.fil = break_width.fil
+ active_width.fill = break_width.fill
+ active_width.filll = break_width.filll
+ active_width.shrink = break_width.shrink
+ if checked_expansion then
+ active_width.adjust_stretch = break_width.adjust_stretch
+ active_width.adjust_shrink = break_width.adjust_shrink
+ end
+ else
+ local q = checked_expansion and {
+ id = delta_code,
+ subtype = nosubtype_code,
+ next = r,
+ size = break_width.size - cur_active_width.size,
+ stretch = break_width.stretch - cur_active_width.stretch,
+ fi = break_width.fi - cur_active_width.fi,
+ fil = break_width.fil - cur_active_width.fil,
+ fill = break_width.fill - cur_active_width.fill,
+ filll = break_width.filll - cur_active_width.filll,
+ shrink = break_width.shrink - cur_active_width.shrink,
+ adjust_stretch = break_width.adjust_stretch - cur_active_width.adjust_stretch,
+ adjust_shrink = break_width.adjust_shrink - cur_active_width.adjust_shrink,
+ } or {
+ id = delta_code,
+ subtype = nosubtype_code,
+ next = r,
+ size = break_width.size - cur_active_width.size,
+ stretch = break_width.stretch - cur_active_width.stretch,
+ fi = break_width.fi - cur_active_width.fi,
+ fil = break_width.fil - cur_active_width.fil,
+ fill = break_width.fill - cur_active_width.fill,
+ filll = break_width.filll - cur_active_width.filll,
+ shrink = break_width.shrink - cur_active_width.shrink,
+ }
+ prev_r.next = q
+ prev_prev_r = prev_r
+ prev_r = q
end
- end
- if prev_r.id == delta_code then
- prev_r.size = prev_r.size - cur_active_width.size + break_width.size
- prev_r.stretch = prev_r.stretch - cur_active_width.stretc + break_width.stretch
- prev_r.fi = prev_r.fi - cur_active_width.fi + break_width.fi
- prev_r.fil = prev_r.fil - cur_active_width.fil + break_width.fil
- prev_r.fill = prev_r.fill - cur_active_width.fill + break_width.fill
- prev_r.filll = prev_r.filll - cur_active_width.filll + break_width.filll
- prev_r.shrink = prev_r.shrink - cur_active_width.shrink + break_width.shrink
- if checked_expansion then
- prev_r.adjust_stretch = prev_r.adjust_stretch - cur_active_width.adjust_stretch + break_width.adjust_stretch
- prev_r.adjust_shrink = prev_r.adjust_shrink - cur_active_width.adjust_shrink + break_width.adjust_shrink
+ local adj_demerits = par.adj_demerits
+ local abs_adj_demerits = adj_demerits > 0 and adj_demerits or -adj_demerits
+ if abs_adj_demerits >= awful_badness - minimum_demerits then
+ minimum_demerits = awful_badness - 1
+ else
+ minimum_demerits = minimum_demerits + abs_adj_demerits
end
- elseif prev_r == par.active then
- active_width.size = break_width.size
- active_width.stretch = break_width.stretch
- active_width.fi = break_width.fi
- active_width.fil = break_width.fil
- active_width.fill = break_width.fill
- active_width.filll = break_width.filll
- active_width.shrink = break_width.shrink
- if checked_expansion then
- active_width.adjust_stretch = break_width.adjust_stretch
- active_width.adjust_shrink = break_width.adjust_shrink
+ for fit_class = fit_very_loose_class, fit_tight_class do
+ if minimal_demerits[fit_class] <= minimum_demerits then
+ -- insert a new active node from best_place[fit_class] to current
+ par.pass_number = par.pass_number + 1
+ local prev_break = best_place[fit_class]
+ local passive = {
+ id = passive_code,
+ subtype = nosubtype_code,
+ next = par.passive,
+ cur_break = current,
+ serial = par.pass_number,
+ prev_break = prev_break,
+ passive_pen_inter = par.internal_pen_inter,
+ passive_pen_broken = par.internal_pen_broken,
+ passive_last_left_box = par.internal_left_box,
+ passive_last_left_box_width = par.internal_left_box_width,
+ passive_left_box = prev_break and prev_break.passive_last_left_box or par.init_internal_left_box,
+ passive_left_box_width = prev_break and prev_break.passive_last_left_box_width or par.init_internal_left_box_width,
+ passive_right_box = par.internal_right_box,
+ passive_right_box_width = par.internal_right_box_width,
+ -- analysis = table.fastcopy(cur_active_width),
+ }
+ par.passive = passive
+ local q = {
+ id = break_type,
+ subtype = fit_class,
+ break_node = passive,
+ line_number = best_pl_line[fit_class] + 1,
+ total_demerits = minimal_demerits[fit_class], -- or 0,
+ next = r,
+ }
+ if do_last_line_fit then
+ local active_short = best_pl_short[fit_class]
+ local active_glue = best_pl_glue[fit_class]
+ q.active_short = active_short
+ q.active_glue = active_glue
+ if trace_lastlinefit then
+ report_parbuilders("setting short to %i and glue to %p using class %a",active_short,active_glue,fit_class)
+ end
+ end
+ -- q.next = r -- already done
+ prev_r.next = q
+ prev_r = q
+ if tracing_paragraphs then
+ diagnostics.break_node(par,q,fit_class,break_type,current)
+ end
+ end
+ minimal_demerits[fit_class] = awful_badness
end
- else
- local q = checked_expansion and {
- id = delta_code,
- subtype = nosubtype_code,
- next = r,
- size = break_width.size - cur_active_width.size,
- stretch = break_width.stretch - cur_active_width.stretch,
- fi = break_width.fi - cur_active_width.fi,
- fil = break_width.fil - cur_active_width.fil,
- fill = break_width.fill - cur_active_width.fill,
- filll = break_width.filll - cur_active_width.filll,
- shrink = break_width.shrink - cur_active_width.shrink,
- adjust_stretch = break_width.adjust_stretch - cur_active_width.adjust_stretch,
- adjust_shrink = break_width.adjust_shrink - cur_active_width.adjust_shrink,
- } or {
- id = delta_code,
- subtype = nosubtype_code,
- next = r,
- size = break_width.size - cur_active_width.size,
- stretch = break_width.stretch - cur_active_width.stretch,
- fi = break_width.fi - cur_active_width.fi,
- fil = break_width.fil - cur_active_width.fil,
- fill = break_width.fill - cur_active_width.fill,
- filll = break_width.filll - cur_active_width.filll,
- shrink = break_width.shrink - cur_active_width.shrink,
- }
- prev_r.next = q
- prev_prev_r = prev_r
- prev_r = q
- end
- local adj_demerits = par.adj_demerits
- local abs_adj_demerits = adj_demerits > 0 and adj_demerits or -adj_demerits
- if abs_adj_demerits >= awful_badness - minimum_demerits then
- minimum_demerits = awful_badness - 1
- else
- minimum_demerits = minimum_demerits + abs_adj_demerits
- end
- for fit_class = fit_very_loose_class, fit_tight_class do
- if minimal_demerits[fit_class] <= minimum_demerits then
- -- insert a new active node from best_place[fit_class] to current
- par.pass_number = par.pass_number + 1
- local prev_break = best_place[fit_class]
- local passive = {
- id = passive_code,
- subtype = nosubtype_code,
- next = par.passive,
- cur_break = current,
- serial = par.pass_number,
- prev_break = prev_break,
- passive_pen_inter = par.internal_pen_inter,
- passive_pen_broken = par.internal_pen_broken,
- passive_last_left_box = par.internal_left_box,
- passive_last_left_box_width = par.internal_left_box_width,
- passive_left_box = prev_break and prev_break.passive_last_left_box or par.init_internal_left_box,
- passive_left_box_width = prev_break and prev_break.passive_last_left_box_width or par.init_internal_left_box_width,
- passive_right_box = par.internal_right_box,
- passive_right_box_width = par.internal_right_box_width,
--- analysis = table.fastcopy(cur_active_width),
- }
- par.passive = passive
- local q = {
- id = break_type,
- subtype = fit_class,
- break_node = passive,
- line_number = best_pl_line[fit_class] + 1,
- total_demerits = minimal_demerits[fit_class], -- or 0,
+ par.minimum_demerits = awful_badness
+ if r ~= par.active then
+ local q = checked_expansion and {
+ id = delta_code,
+ subtype = nosubtype_code,
+ next = r,
+ size = cur_active_width.size - break_width.size,
+ stretch = cur_active_width.stretch - break_width.stretch,
+ fi = cur_active_width.fi - break_width.fi,
+ fil = cur_active_width.fil - break_width.fil,
+ fill = cur_active_width.fill - break_width.fill,
+ filll = cur_active_width.filll - break_width.filll,
+ shrink = cur_active_width.shrink - break_width.shrink,
+ adjust_stretch = cur_active_width.adjust_stretch - break_width.adjust_stretch,
+ adjust_shrink = cur_active_width.adjust_shrink - break_width.adjust_shrink,
+ } or {
+ id = delta_code,
+ subtype = nosubtype_code,
next = r,
+ size = cur_active_width.size - break_width.size,
+ stretch = cur_active_width.stretch - break_width.stretch,
+ fi = cur_active_width.fi - break_width.fi,
+ fil = cur_active_width.fil - break_width.fil,
+ fill = cur_active_width.fill - break_width.fill,
+ filll = cur_active_width.filll - break_width.filll,
+ shrink = cur_active_width.shrink - break_width.shrink,
}
- if do_last_line_fit then
- local active_short = best_pl_short[fit_class]
- local active_glue = best_pl_glue[fit_class]
- q.active_short = active_short
- q.active_glue = active_glue
- if trace_lastlinefit then
- report_parbuilders("setting short to %i and glue to %p using class %a",active_short,active_glue,fit_class)
- end
- end
-- q.next = r -- already done
prev_r.next = q
+ prev_prev_r = prev_r
prev_r = q
- if tracing_paragraphs then
- diagnostics.break_node(par,q,fit_class,break_type,current)
- end
end
- minimal_demerits[fit_class] = awful_badness
- end
- par.minimum_demerits = awful_badness
- if r ~= par.active then
- local q = checked_expansion and {
- id = delta_code,
- subtype = nosubtype_code,
- next = r,
- size = cur_active_width.size - break_width.size,
- stretch = cur_active_width.stretch - break_width.stretch,
- fi = cur_active_width.fi - break_width.fi,
- fil = cur_active_width.fil - break_width.fil,
- fill = cur_active_width.fill - break_width.fill,
- filll = cur_active_width.filll - break_width.filll,
- shrink = cur_active_width.shrink - break_width.shrink,
- adjust_stretch = cur_active_width.adjust_stretch - break_width.adjust_stretch,
- adjust_shrink = cur_active_width.adjust_shrink - break_width.adjust_shrink,
- } or {
- id = delta_code,
- subtype = nosubtype_code,
- next = r,
- size = cur_active_width.size - break_width.size,
- stretch = cur_active_width.stretch - break_width.stretch,
- fi = cur_active_width.fi - break_width.fi,
- fil = cur_active_width.fil - break_width.fil,
- fill = cur_active_width.fill - break_width.fill,
- filll = cur_active_width.filll - break_width.filll,
- shrink = cur_active_width.shrink - break_width.shrink,
- }
- -- q.next = r -- already done
- prev_r.next = q
- prev_prev_r = prev_r
- prev_r = q
end
- end
- if r == par.active then
- return r, r and r.next -- p_active, n_active
- end
- if line_number > par.easy_line then
- old_line_number = max_halfword - 1
- line_width = par.second_width
- else
- old_line_number = line_number
- if line_number > par.last_special_line then
+ if r == par.active then
+ return r, r and r.next -- p_active, n_active
+ end
+ if line_number > par.easy_line then
+ old_line_number = max_halfword - 1
line_width = par.second_width
- elseif parshape then
- line_width = parshape[line_number][2]
else
- line_width = par.first_width
+ old_line_number = line_number
+ if line_number > par.last_special_line then
+ line_width = par.second_width
+ elseif parshape then
+ line_width = parshape[line_number][2]
+ else
+ line_width = par.first_width
+ end
end
- end
- if adapt_width then
- local l, r = adapt_width(par,line_number)
- line_width = line_width - l - r
- end
- end
- local artificial_demerits = false -- has d been forced to zero
- local shortfall = line_width - cur_active_width.size - par.internal_right_box_width -- used in badness calculations
- if not r.break_node then
- shortfall = shortfall - par.init_internal_left_box_width
- else
- shortfall = shortfall - (r.break_node.passive_last_left_box_width or 0)
- end
- local pw, lp, rp -- used later on
- if protrude_chars > 1 then
- -- this is quite time consuming
- local b = r.break_node
- local l = b and b.cur_break or first_p
- local o = current and getprev(current)
- if current and getid(current) == disc_code then
- local pre, _, _, pretail = getdisc(current,true)
- if pre then
- o = pretail
- else
- o = find_protchar_right(l,o)
+ if adapt_width then
+ local l, r = adapt_width(par,line_number)
+ line_width = line_width - l - r
end
- else
- o = find_protchar_right(l,o)
end
- if o and getid(o) == glyph_code then
- pw, rp = right_pw(o)
- shortfall = shortfall + pw
- end
- local id = getid(l)
- if id == glyph_code then
- -- ok ?
- elseif id == disc_code and getfield(l,"post") then
- l = getfield(l,"post") -- TODO: first char could be a disc
+ local artificial_demerits = false -- has d been forced to zero
+ local shortfall = line_width - cur_active_width.size - par.internal_right_box_width -- used in badness calculations
+ if not r.break_node then
+ shortfall = shortfall - par.init_internal_left_box_width
else
- l = find_protchar_left(l)
- end
- if l and getid(l) == glyph_code then
- pw, lp = left_pw(l)
- shortfall = shortfall + pw
+ shortfall = shortfall - (r.break_node.passive_last_left_box_width or 0)
end
- end
- if checked_expansion and shortfall ~= 0 then
- local margin_kern_stretch = 0
- local margin_kern_shrink = 0
+ local pw, lp, rp -- used later on
if protrude_chars > 1 then
- if lp then
- local data = expansions[getfont(lp)][getchar(lp)]
- if data then
- margin_kern_stretch, margin_kern_shrink = data.glyphstretch, data.glyphshrink
+ -- this is quite time consuming
+ local b = r.break_node
+ local l = b and b.cur_break or first_p
+ local o = current and getprev(current)
+ if current and getid(current) == disc_code then
+ local pre, _, _, pretail = getdisc(current,true)
+ if pre then
+ o = pretail
+ else
+ o = find_protchar_right(l,o)
end
+ else
+ o = find_protchar_right(l,o)
end
- if rp then
- local data = expansions[getfont(lp)][getchar(lp)]
- if data then
- margin_kern_stretch = margin_kern_stretch + data.glyphstretch
- margin_kern_shrink = margin_kern_shrink + data.glyphshrink
- end
+ if o and getid(o) == glyph_code then
+ pw, rp = right_pw(o)
+ shortfall = shortfall + pw
end
- end
- local total = cur_active_width.adjust_stretch + margin_kern_stretch
- if shortfall > 0 and total > 0 then
- if total > shortfall then
- shortfall = total / (par.max_stretch_ratio / par.cur_font_step) / 2
+ local id = getid(l)
+ if id == glyph_code then
+ -- ok ?
+ elseif id == disc_code and getfield(l,"post") then
+ l = getfield(l,"post") -- TODO: first char could be a disc
else
- shortfall = shortfall - total
+ l = find_protchar_left(l)
end
- else
- total = cur_active_width.adjust_shrink + margin_kern_shrink
- if shortfall < 0 and total > 0 then
- if total > - shortfall then
- shortfall = - total / (par.max_shrink_ratio / par.cur_font_step) / 2
- else
- shortfall = shortfall + total
- end
+ if l and getid(l) == glyph_code then
+ pw, lp = left_pw(l)
+ shortfall = shortfall + pw
end
end
- end
- local b = 0
- local g = 0
- local fit_class = fit_decent_class
- local found = false
- if shortfall > 0 then
- if cur_active_width.fi ~= 0 or cur_active_width.fil ~= 0 or cur_active_width.fill ~= 0 or cur_active_width.filll ~= 0 then
- if not do_last_line_fit then
- -- okay
- elseif not current then
- found, shortfall, fit_class, g, b = lastlinecrap(shortfall,r.active_short,r.active_glue,cur_active_width,par.fill_width,par.last_line_fit)
+ if checked_expansion and shortfall ~= 0 then
+ local margin_kern_stretch = 0
+ local margin_kern_shrink = 0
+ if protrude_chars > 1 then
+ if lp then
+ local data = expansions[getfont(lp)][getchar(lp)]
+ if data then
+ margin_kern_stretch, margin_kern_shrink = data.glyphstretch, data.glyphshrink
+ end
+ end
+ if rp then
+ local data = expansions[getfont(lp)][getchar(lp)]
+ if data then
+ margin_kern_stretch = margin_kern_stretch + data.glyphstretch
+ margin_kern_shrink = margin_kern_shrink + data.glyphshrink
+ end
+ end
+ end
+ local total = cur_active_width.adjust_stretch + margin_kern_stretch
+ if shortfall > 0 and total > 0 then
+ if total > shortfall then
+ shortfall = total / (par.max_stretch_ratio / par.cur_font_step) / 2
+ else
+ shortfall = shortfall - total
+ end
else
- shortfall = 0
+ total = cur_active_width.adjust_shrink + margin_kern_shrink
+ if shortfall < 0 and total > 0 then
+ if total > - shortfall then
+ shortfall = - total / (par.max_shrink_ratio / par.cur_font_step) / 2
+ else
+ shortfall = shortfall + total
+ end
+ end
end
- else
- local stretch = cur_active_width.stretch
- if shortfall > 7230584 and stretch < 1663497 then
- b = infinite_badness
- fit_class = fit_very_loose_class
+ end
+ local b = 0
+ local g = 0
+ local fit_class = fit_decent_class
+ local found = false
+ if shortfall > 0 then
+ if cur_active_width.fi ~= 0 or cur_active_width.fil ~= 0 or cur_active_width.fill ~= 0 or cur_active_width.filll ~= 0 then
+ if not do_last_line_fit then
+ -- okay
+ elseif not current then
+ found, shortfall, fit_class, g, b = lastlinecrap(shortfall,r.active_short,r.active_glue,cur_active_width,par.fill_width,par.last_line_fit)
+ else
+ shortfall = 0
+ end
else
- b = calculate_badness(shortfall,stretch)
- if b > 99 then
+ local stretch = cur_active_width.stretch
+ if shortfall > 7230584 and stretch < 1663497 then
+ b = infinite_badness
fit_class = fit_very_loose_class
- elseif b > 12 then
- fit_class = fit_loose_class
else
- fit_class = fit_decent_class
+ b = calculate_badness(shortfall,stretch)
+ if b > 99 then
+ fit_class = fit_very_loose_class
+ elseif b > 12 then
+ fit_class = fit_loose_class
+ else
+ fit_class = fit_decent_class
+ end
end
end
- end
- else
- local shrink = cur_active_width.shrink
- if -shortfall > shrink then
- b = infinite_badness + 1
- else
- b = calculate_badness(-shortfall,shrink)
- end
- if b > 12 then
- fit_class = fit_tight_class
- else
- fit_class = fit_decent_class
- end
- end
- if do_last_line_fit and not found then
- if not current then
- -- g = 0
- shortfall = 0
- elseif shortfall > 0 then
- g = cur_active_width.stretch
- elseif shortfall < 0 then
- g = cur_active_width.shrink
else
- g = 0
+ local shrink = cur_active_width.shrink
+ if -shortfall > shrink then
+ b = infinite_badness + 1
+ else
+ b = calculate_badness(-shortfall,shrink)
+ end
+ if b > 12 then
+ fit_class = fit_tight_class
+ else
+ fit_class = fit_decent_class
+ end
end
- end
- -- ::FOUND::
- local continue_only = false -- brrr
- if b > infinite_badness or pi == eject_penalty then
- if final_pass and par.minimum_demerits == awful_badness and r.next == par.active and prev_r == par.active then
- artificial_demerits = true -- set demerits zero, this break is forced
- node_r_stays_active = false
- elseif b > par.threshold then
- prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion)
- continue_only = true
- else
- node_r_stays_active = false
+ if do_last_line_fit and not found then
+ if not current then
+ -- g = 0
+ shortfall = 0
+ elseif shortfall > 0 then
+ g = cur_active_width.stretch
+ elseif shortfall < 0 then
+ g = cur_active_width.shrink
+ else
+ g = 0
+ end
end
- else
- prev_r = r
- if b > par.threshold then
- continue_only = true
+ -- ::FOUND::
+ local continue_only = false -- brrr
+ if b > infinite_badness or pi == eject_penalty then
+ if final_pass and par.minimum_demerits == awful_badness and r.next == par.active and prev_r == par.active then
+ artificial_demerits = true -- set demerits zero, this break is forced
+ node_r_stays_active = false
+ elseif b > par.threshold then
+ prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion)
+ continue_only = true
+ else
+ node_r_stays_active = false
+ end
else
- node_r_stays_active = true
- end
- end
- if not continue_only then
- local d = 0
- if not artificial_demerits then
- d = par.line_penalty + b
- if (d >= 0 and d or -d) >= 10000 then -- abs(d)
- d = 100000000
+ prev_r = r
+ if b > par.threshold then
+ continue_only = true
else
- d = d * d
+ node_r_stays_active = true
end
- if pi == 0 then
- -- nothing
- elseif pi > 0 then
- d = d + pi * pi
- elseif pi > eject_penalty then
- d = d - pi * pi
- end
- if break_type == hyphenated_code and r.id == hyphenated_code then
- if current then
- d = d + par.double_hyphen_demerits
+ end
+ if not continue_only then
+ local d = 0
+ if not artificial_demerits then
+ d = par.line_penalty + b
+ if (d >= 0 and d or -d) >= 10000 then -- abs(d)
+ d = 100000000
else
- d = d + par.final_hyphen_demerits
+ d = d * d
+ end
+ if pi == 0 then
+ -- nothing
+ elseif pi > 0 then
+ d = d + pi * pi
+ elseif pi > eject_penalty then
+ d = d - pi * pi
+ end
+ if break_type == hyphenated_code and r.id == hyphenated_code then
+ if current then
+ d = d + par.double_hyphen_demerits
+ else
+ d = d + par.final_hyphen_demerits
+ end
+ end
+ local delta = fit_class - r.subtype
+ if (delta >= 0 and delta or -delta) > 1 then -- abs(delta)
+ d = d + par.adj_demerits
end
end
- local delta = fit_class - r.subtype
- if (delta >= 0 and delta or -delta) > 1 then -- abs(delta)
- d = d + par.adj_demerits
+ if tracing_paragraphs then
+ diagnostics.feasible_break(par,current,r,b,pi,d,artificial_demerits)
end
- end
- if tracing_paragraphs then
- diagnostics.feasible_break(par,current,r,b,pi,d,artificial_demerits)
- end
- d = d + r.total_demerits -- this is the minimum total demerits from the beginning to current via r
- if d <= minimal_demerits[fit_class] then
- minimal_demerits[fit_class] = d
- best_place [fit_class] = r.break_node
- best_pl_line [fit_class] = line_number
- if do_last_line_fit then
- best_pl_short[fit_class] = shortfall
- best_pl_glue [fit_class] = g
- if trace_lastlinefit then
- report_parbuilders("storing last line fit short %a and glue %p in class %a",shortfall,g,fit_class)
+ d = d + r.total_demerits -- this is the minimum total demerits from the beginning to current via r
+ if d <= minimal_demerits[fit_class] then
+ minimal_demerits[fit_class] = d
+ best_place [fit_class] = r.break_node
+ best_pl_line [fit_class] = line_number
+ if do_last_line_fit then
+ best_pl_short[fit_class] = shortfall
+ best_pl_glue [fit_class] = g
+ if trace_lastlinefit then
+ report_parbuilders("storing last line fit short %a and glue %p in class %a",shortfall,g,fit_class)
+ end
+ end
+ if d < par.minimum_demerits then
+ par.minimum_demerits = d
end
end
- if d < par.minimum_demerits then
- par.minimum_demerits = d
+ if not node_r_stays_active then
+ prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion)
end
end
- if not node_r_stays_active then
- prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion)
- end
end
end
end
-end
-
--- we can call the normal one for simple box building in the otr so we need
--- frequent enabling/disabling
-local dcolor = { [0] = "red", "green", "blue", "magenta", "cyan", "gray" }
+ -- we can call the normal one for simple box building in the otr so we need
+ -- frequent enabling/disabling
-local temp_head = new_temp()
+ local temp_head = new_temp()
-function constructors.methods.basic(head,d)
- if trace_basic then
- report_parbuilders("starting at %a",head)
- end
+ function constructors.methods.basic(head,d)
+ if trace_basic then
+ report_parbuilders("starting at %a",head)
+ end
- local par = initialize_line_break(head,d)
+ local par = initialize_line_break(head,d)
- local checked_expansion = par.checked_expansion
- local active_width = par.active_width
- local disc_width = par.disc_width
- local background = par.background
- local tracing_paragraphs = par.tracing_paragraphs
+ local checked_expansion = par.checked_expansion
+ local active_width = par.active_width
+ local disc_width = par.disc_width
+ local background = par.background
+ local tracing_paragraphs = par.tracing_paragraphs
- local dirstack = new_dir_stack()
+ local dirstack = new_dir_stack()
- if tracing_paragraphs then
- diagnostics.start()
- if par.pretolerance >= 0 then
- diagnostics.current_pass(par,"firstpass")
+ if tracing_paragraphs then
+ diagnostics.start()
+ if par.pretolerance >= 0 then
+ diagnostics.current_pass(par,"firstpass")
+ end
end
- end
- while true do
- reset_meta(par)
- if par.threshold > infinite_badness then
- par.threshold = infinite_badness
- end
- par.active.next = {
- id = unhyphenated_code,
- subtype = fit_decent_class,
- next = par.active,
- break_node = nil,
- line_number = par.first_line + 1,
- total_demerits = 0,
- active_short = 0,
- active_glue = 0,
- }
- active_width.size = background.size
- active_width.stretch = background.stretch
- active_width.fi = background.fi
- active_width.fil = background.fil
- active_width.fill = background.fill
- active_width.filll = background.filll
- active_width.shrink = background.shrink
-
- if checked_expansion then
- active_width.adjust_stretch = 0
- active_width.adjust_shrink = 0
- end
+ while true do
+ reset_meta(par)
+ if par.threshold > infinite_badness then
+ par.threshold = infinite_badness
+ end
+ par.active.next = {
+ id = unhyphenated_code,
+ subtype = fit_decent_class,
+ next = par.active,
+ break_node = nil,
+ line_number = par.first_line + 1,
+ total_demerits = 0,
+ active_short = 0,
+ active_glue = 0,
+ }
+ active_width.size = background.size
+ active_width.stretch = background.stretch
+ active_width.fi = background.fi
+ active_width.fil = background.fil
+ active_width.fill = background.fill
+ active_width.filll = background.filll
+ active_width.shrink = background.shrink
- par.passive = nil -- = 0
- par.printed_node = temp_head -- only when tracing, shared
- par.pass_number = 0
--- par.auto_breaking = true
+ if checked_expansion then
+ active_width.adjust_stretch = 0
+ active_width.adjust_shrink = 0
+ end
- setnext(temp_head,head)
+ par.passive = nil -- = 0
+ par.printed_node = temp_head -- only when tracing, shared
+ par.pass_number = 0
+ -- par.auto_breaking = true
- local current = head
- local first_p = current
+ setnext(temp_head,head)
- local auto_breaking = true
+ local current = head
+ local first_p = current
- par.font_in_short_display = 0
+ local auto_breaking = true
- if current then
- local id = getid(current)
- if id == localpar_code then
- par.init_internal_left_box = getfield(current,"box_left")
- par.init_internal_left_box_width = getfield(current,"box_left_width")
- par.internal_pen_inter = getfield(current,"pen_inter")
- par.internal_pen_broken = getfield(current,"pen_broken")
- par.internal_left_box = par.init_internal_left_box
- par.internal_left_box_width = par.init_internal_left_box_width
- par.internal_right_box = getfield(current,"box_right")
- par.internal_right_box_width = getfield(current,"box_right_width")
+ par.font_in_short_display = 0
+
+ if current then
+ local id = getid(current)
+ if id == localpar_code then
+ par.init_internal_left_box = getfield(current,"box_left")
+ par.init_internal_left_box_width = getfield(current,"box_left_width")
+ par.internal_pen_inter = getfield(current,"pen_inter")
+ par.internal_pen_broken = getfield(current,"pen_broken")
+ par.internal_left_box = par.init_internal_left_box
+ par.internal_left_box_width = par.init_internal_left_box_width
+ par.internal_right_box = getfield(current,"box_right")
+ par.internal_right_box_width = getfield(current,"box_right_width")
+ end
end
- end
- -- all passes are combined in this loop so maybe we should split this into
- -- three function calls; we then also need to do the wrap_up elsewhere
+ -- all passes are combined in this loop so maybe we should split this into
+ -- three function calls; we then also need to do the wrap_up elsewhere
- -- split into normal and expansion loop
+ -- split into normal and expansion loop
- -- use an active local
+ -- use an active local
- local fontexp, lastfont -- we can pass fontexp to calculate width if needed
+ local fontexp, lastfont -- we can pass fontexp to calculate width if needed
- -- i flattened the inner loop over glyphs .. it looks nicer and the extra p_active ~= n_active
- -- test is fast enough (and try_break now returns the updated values); the kern helper has been
- -- inlined as it did a double check on id so in fact we had hardly any code to share
+ -- i flattened the inner loop over glyphs .. it looks nicer and the extra p_active ~= n_active
+ -- test is fast enough (and try_break now returns the updated values); the kern helper has been
+ -- inlined as it did a double check on id so in fact we had hardly any code to share
- local p_active = par.active
- local n_active = p_active and p_active.next
- local second_pass = par.second_pass
+ local p_active = par.active
+ local n_active = p_active and p_active.next
+ local second_pass = par.second_pass
- trialcount = 0
+ trialcount = 0
- 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 + ht + dp
- else
- active_width.size = active_width.size + wd
- end
- if checked_expansion then
- local currentfont = getfont(current)
- local data = checked_expansion[currentfont]
- if data then
- 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
- active_width.adjust_stretch = active_width.adjust_stretch + expansion.glyphstretch
- active_width.adjust_shrink = active_width.adjust_shrink + expansion.glyphshrink
+ 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 + ht + dp
+ else
+ active_width.size = active_width.size + wd
+ end
+ if checked_expansion then
+ local currentfont = getfont(current)
+ local data = checked_expansion[currentfont]
+ if data then
+ 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
+ active_width.adjust_stretch = active_width.adjust_stretch + expansion.glyphstretch
+ active_width.adjust_shrink = active_width.adjust_shrink + expansion.glyphshrink
+ end
end
end
end
- end
- elseif id == hlist_code or id == vlist_code then
- 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 + ht + dp
- end
- elseif id == glue_code then
--- if par.auto_breaking then
- if auto_breaking then
- local prev_p = getprev(current)
- if prev_p and prev_p ~= temp_head then
- local id = getid(prev_p)
- -- we need to check this with the latest patches to the tex kernel
- if (id == glyph_code) or (id < math_code) then
- p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
- elseif id == kern_code then
- local s = getsubtype(prev_p)
- if s ~= userkern_code and s ~= italickern_code then
+ elseif id == hlist_code or id == vlist_code then
+ local wd, ht, dp = getwhd(current)
+ if textdir_parallel(getdirection(current),par.line_break_dir) then
+ active_width.size = active_width.size + wd
+ else
+ active_width.size = active_width.size + ht + dp
+ end
+ elseif id == glue_code then
+ -- if par.auto_breaking then
+ if auto_breaking then
+ local prev_p = getprev(current)
+ if prev_p and prev_p ~= temp_head then
+ local id = getid(prev_p)
+ -- we need to check this with the latest patches to the tex kernel
+ if (id == glyph_code) or (id < math_code) then
p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
+ elseif id == kern_code then
+ local s = getsubtype(prev_p)
+ if s ~= userkern_code and s ~= italickern_code then
+ p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
+ end
end
end
end
- end
- check_shrinkage(par,current)
- 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
- local line_break_dir = par.line_break_dir
- 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 = getpenalty(current)
- --
- local pre, post, replace = getdisc(current)
- if not pre then -- trivial pre-break
- disc_width.size = 0
- if checked_expansion then
- disc_width.adjust_stretch = 0
- disc_width.adjust_shrink = 0
- end
- p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion)
- else
- local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre)
- disc_width.size = size
- active_width.size = active_width.size + size
- if checked_expansion then
- disc_width.adjust_stretch = adjust_stretch
- disc_width.adjust_shrink = adjust_shrink
- active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch
- active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink
+ check_shrinkage(par,current)
+ local width, stretch, shrink, stretch_order = getglue(current)
+ local order = fillcodes[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 ~= seconddisc_code then
+ local line_break_dir = par.line_break_dir
+ if second_pass or subtype <= automaticdisc_code then
+ local actual_pen = subtype == automaticdisc_code and par.ex_hyphen_penalty or par.hyphen_penalty
+ -- 0.81 :
+ -- local actual_pen = getpenalty(current)
+ --
+ local pre, post, replace = getdisc(current)
+ if not pre then -- trivial pre-break
+ disc_width.size = 0
+ if checked_expansion then
+ disc_width.adjust_stretch = 0
+ disc_width.adjust_shrink = 0
+ end
+ p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion)
else
- -- disc_width.adjust_stretch = 0
- -- disc_width.adjust_shrink = 0
- end
- p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion)
- if subtype == first_disc_code then
- local cur_p_next = getnext(current)
- if getid(cur_p_next) ~= disc_code or getsubtype(cur_p_next) ~= second_disc_code then
- report_parbuilders("unsupported disc at location %a",1)
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre)
+ disc_width.size = size
+ active_width.size = active_width.size + size
+ if checked_expansion then
+ disc_width.adjust_stretch = adjust_stretch
+ disc_width.adjust_shrink = adjust_shrink
+ active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch
+ active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink
else
- local pre = getfield(cur_p_next,"pre")
- if pre then
- local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre)
- disc_width.size = disc_width.size + size
- if checked_expansion then
- disc_width.adjust_stretch = disc_width.adjust_stretch + adjust_stretch
- disc_width.adjust_shrink = disc_width.adjust_shrink + adjust_shrink
- end
- p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, cur_p_next, checked_expansion)
- --
- -- I will look into this some day ... comment in linebreak.w says that this fails,
- -- maybe this is what Taco means with his comment in the luatex manual.
- --
- -- do_one_seven_eight(sub_disc_width_from_active_width);
- -- do_one_seven_eight(reset_disc_width);
- -- s = vlink_no_break(vlink(current));
- -- add_to_widths(s, line_break_dir, adjust_spacing,disc_width);
- -- ext_try_break(...,first_p,vlink(current));
- --
+ -- disc_width.adjust_stretch = 0
+ -- disc_width.adjust_shrink = 0
+ end
+ p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion)
+ if subtype == firstdisc_code then
+ local cur_p_next = getnext(current)
+ if getid(cur_p_next) ~= disc_code or getsubtype(cur_p_next) ~= seconddisc_code then
+ report_parbuilders("unsupported disc at location %a",1)
else
- report_parbuilders("unsupported disc at location %a",2)
+ local pre = getfield(cur_p_next,"pre")
+ if pre then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre)
+ disc_width.size = disc_width.size + size
+ if checked_expansion then
+ disc_width.adjust_stretch = disc_width.adjust_stretch + adjust_stretch
+ disc_width.adjust_shrink = disc_width.adjust_shrink + adjust_shrink
+ end
+ p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, cur_p_next, checked_expansion)
+ --
+ -- I will look into this some day ... comment in linebreak.w says that this fails,
+ -- maybe this is what Taco means with his comment in the luatex manual.
+ --
+ -- do_one_seven_eight(sub_disc_width_from_active_width);
+ -- do_one_seven_eight(reset_disc_width);
+ -- s = vlink_no_break(vlink(current));
+ -- add_to_widths(s, line_break_dir, adjust_spacing,disc_width);
+ -- ext_try_break(...,first_p,vlink(current));
+ --
+ else
+ report_parbuilders("unsupported disc at location %a",2)
+ end
end
end
+ -- beware, we cannot restore to a saved value as the try_break adapts active_width
+ active_width.size = active_width.size - disc_width.size
+ if checked_expansion then
+ active_width.adjust_stretch = active_width.adjust_stretch - disc_width.adjust_stretch
+ active_width.adjust_shrink = active_width.adjust_shrink - disc_width.adjust_shrink
+ end
end
- -- beware, we cannot restore to a saved value as the try_break adapts active_width
- active_width.size = active_width.size - disc_width.size
+ end
+ if replace then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace)
+ active_width.size = active_width.size + size
if checked_expansion then
- active_width.adjust_stretch = active_width.adjust_stretch - disc_width.adjust_stretch
- active_width.adjust_shrink = active_width.adjust_shrink - disc_width.adjust_shrink
+ active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch
+ active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink
end
end
end
- if replace then
- local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace)
- active_width.size = active_width.size + size
- if checked_expansion then
- active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch
- active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink
+ elseif id == kern_code then
+ local s = getsubtype(current)
+ if s == userkern_code or s == italickern_code then
+ local v = getnext(current)
+ -- if par.auto_breaking and getid(v) == glue_code then
+ if auto_breaking and getid(v) == glue_code then
+ 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 + getkern(current)
+ else
+ local kern = getkern(current)
+ if kern ~= 0 then
+ active_width.size = active_width.size + kern
+ if checked_expansion and expand_kerns and getsubtype(current) == fontkern_code then
+ local stretch, shrink = kern_stretch_shrink(current,kern)
+ if expand_kerns == "stretch" then
+ active_width.adjust_stretch = active_width.adjust_stretch + stretch
+ elseif expand_kerns == "shrink" then
+ active_width.adjust_shrink = active_width.adjust_shrink + shrink
+ else
+ active_width.adjust_stretch = active_width.adjust_stretch + stretch
+ active_width.adjust_shrink = active_width.adjust_shrink + shrink
+ end
+ end
end
end
- end
- elseif id == kern_code then
- local s = getsubtype(current)
- if s == userkern_code or s == italickern_code then
+ elseif id == math_code then
+ -- par.auto_breaking = getsubtype(current) == endmath_code
+ auto_breaking = getsubtype(current) == endmath_code
local v = getnext(current)
- -- if par.auto_breaking and getid(v) == glue_code then
+ -- if par.auto_breaking and getid(v) == glue_code then
if auto_breaking and getid(v) == glue_code then
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 + getkern(current)
- else
- local kern = getkern(current)
- if kern ~= 0 then
- active_width.size = active_width.size + kern
- if checked_expansion and expand_kerns and getsubtype(current) == fontkern_code then
- local stretch, shrink = kern_stretch_shrink(current,kern)
- if expand_kerns == "stretch" then
- active_width.adjust_stretch = active_width.adjust_stretch + stretch
- elseif expand_kerns == "shrink" then
- active_width.adjust_shrink = active_width.adjust_shrink + shrink
- else
- active_width.adjust_stretch = active_width.adjust_stretch + stretch
- active_width.adjust_shrink = active_width.adjust_shrink + shrink
- end
- end
+ 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 + getwidth(current)
+ elseif id == penalty_code then
+ 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
+ par.internal_pen_inter = getfield(current,"pen_inter")
+ par.internal_pen_broken = getfield(current,"pen_broken")
+ par.internal_left_box = getfield(current,"box_left")
+ par.internal_left_box_width = getfield(current,"box_left_width")
+ par.internal_right_box = getfield(current,"box_right")
+ par.internal_right_box_width = getfield(current,"box_right_width")
+ elseif trace_unsupported then
+ if id == mark_code or id == ins_code or id == adjust_code then
+ -- skip
+ else
+ report_parbuilders("node of type %a found in paragraph",type(id))
end
end
- elseif id == math_code then
--- par.auto_breaking = getsubtype(current) == endmath_code
- auto_breaking = getsubtype(current) == endmath_code
- local v = getnext(current)
--- if par.auto_breaking and getid(v) == glue_code then
- if auto_breaking and getid(v) == glue_code then
- 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 + getkern(current) -- surround
- -- new in luatex
- + getwidth(current)
- elseif id == rule_code then
- active_width.size = active_width.size + getwidth(current)
- elseif id == penalty_code then
- 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
- par.internal_pen_inter = getfield(current,"pen_inter")
- par.internal_pen_broken = getfield(current,"pen_broken")
- par.internal_left_box = getfield(current,"box_left")
- par.internal_left_box_width = getfield(current,"box_left_width")
- par.internal_right_box = getfield(current,"box_right")
- par.internal_right_box_width = getfield(current,"box_right_width")
- elseif trace_unsupported then
- if id == mark_code or id == ins_code or id == adjust_code then
- -- skip
- else
- report_parbuilders("node of type %a found in paragraph",type(id))
- end
+ current = getnext(current)
end
- current = getnext(current)
- end
- if not current then
- local p_active, n_active = try_break(eject_penalty, hyphenated_code, par, first_p, current, checked_expansion)
- if n_active ~= p_active then
- local r = n_active
- par.fewest_demerits = awful_badness
- repeat -- use local d
- if r.id ~= delta_code and r.total_demerits < par.fewest_demerits then
- par.fewest_demerits = r.total_demerits
- par.best_bet = r
- end
- r = r.next
- until r == p_active
- par.best_line = par.best_bet.line_number
- local asked_looseness = par.looseness
- if asked_looseness == 0 then
- return wrap_up(par)
- end
- local r = n_active
- local actual_looseness = 0
- -- minimize assignments to par but happens seldom
- repeat
- if r.id ~= delta_code then
- local line_diff = r.line_number - par.best_line
- par.line_diff = line_diff
- if (line_diff < actual_looseness and asked_looseness <= line_diff) or
- (line_diff > actual_looseness and asked_looseness >= line_diff) then
- par.best_bet = r
- actual_looseness = line_diff
+ if not current then
+ local p_active, n_active = try_break(eject_penalty, hyphenated_code, par, first_p, current, checked_expansion)
+ if n_active ~= p_active then
+ local r = n_active
+ par.fewest_demerits = awful_badness
+ repeat -- use local d
+ if r.id ~= delta_code and r.total_demerits < par.fewest_demerits then
par.fewest_demerits = r.total_demerits
- elseif line_diff == actual_looseness and r.total_demerits < par.fewest_demerits then
par.best_bet = r
- par.fewest_demerits = r.total_demerits
end
+ r = r.next
+ until r == p_active
+ par.best_line = par.best_bet.line_number
+ local asked_looseness = par.looseness
+ if asked_looseness == 0 then
+ return wrap_up(par)
+ end
+ local r = n_active
+ local actual_looseness = 0
+ -- minimize assignments to par but happens seldom
+ repeat
+ if r.id ~= delta_code then
+ local line_diff = r.line_number - par.best_line
+ par.line_diff = line_diff
+ if (line_diff < actual_looseness and asked_looseness <= line_diff) or
+ (line_diff > actual_looseness and asked_looseness >= line_diff) then
+ par.best_bet = r
+ actual_looseness = line_diff
+ par.fewest_demerits = r.total_demerits
+ elseif line_diff == actual_looseness and r.total_demerits < par.fewest_demerits then
+ par.best_bet = r
+ par.fewest_demerits = r.total_demerits
+ end
+ end
+ r = r.next
+ until r == p_active
+ par.best_line = par.best_bet.line_number
+ if actual_looseness == asked_looseness or par.final_pass then
+ return wrap_up(par)
end
- r = r.next
- until r == p_active
- par.best_line = par.best_bet.line_number
- if actual_looseness == asked_looseness or par.final_pass then
- return wrap_up(par)
end
end
- end
- reset_meta(par) -- clean up the memory by removing the break nodes
- if not second_pass then
- if tracing_paragraphs then
- diagnostics.current_pass(par,"secondpass")
- end
- par.threshold = par.tolerance
- par.second_pass = true
- par.final_pass = par.emergency_stretch <= 0
- else
- if tracing_paragraphs then
- diagnostics.current_pass(par,"emergencypass")
+ reset_meta(par) -- clean up the memory by removing the break nodes
+ if not second_pass then
+ if tracing_paragraphs then
+ diagnostics.current_pass(par,"secondpass")
+ end
+ par.threshold = par.tolerance
+ par.second_pass = true
+ par.final_pass = par.emergency_stretch <= 0
+ else
+ if tracing_paragraphs then
+ diagnostics.current_pass(par,"emergencypass")
+ end
+ par.background.stretch = par.background.stretch + par.emergency_stretch
+ par.final_pass = true
end
- par.background.stretch = par.background.stretch + par.emergency_stretch
- par.final_pass = true
end
+ return wrap_up(par)
end
- return wrap_up(par)
+
end
-- standard tex logging .. will be adapted ..
@@ -2537,7 +2581,7 @@ do
font_in_short_display = font
end
-- todo: instead of components the split tounicode string
- if getsubtype(a) == ligature_code then
+ if getsubtype(a) == ligatureglyph_code then
font_in_short_display = short_display(target,getcomponents(a),font_in_short_display)
else
write(target,utfchar(char))
@@ -2713,55 +2757,6 @@ do
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
- 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
-
- 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
-
-- local function xpack(head,width,method,direction,analysis)
--
-- -- inspect(analysis)
@@ -2776,7 +2771,7 @@ do
-- local hlist = new_hlist()
--
-- setlist(hlist,head)
- -- setdir(hlist,direction or tex.textdir)
+ -- setdirection(hlist,direction or tex.textdirection)
-- setwhd(hlist,width,height,depth)
--
-- if delta == 0 then
@@ -2889,7 +2884,7 @@ do
local hlist = new_hlist()
- setdir(hlist,direction)
+ setdirection(hlist,direction)
if head == nil then
setwidth(hlist,width)
@@ -2958,7 +2953,7 @@ do
end
end
-- use inline
- local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ?
+ local wd, ht, dp = getwhd(current)
natural = natural + wd
if ht > height then
height = ht
@@ -2984,7 +2979,7 @@ do
end
elseif id == disc_code then
local subtype = getsubtype(current)
- if subtype ~= second_disc_code then
+ if subtype ~= seconddisc_code then
-- todo : local stretch, shrink = char_stretch_shrink(s)
local replace = getfield(current,"replace")
if replace then
@@ -3008,7 +3003,7 @@ do
end
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 wd, ht, dp = getwhd(current)
local hs, ds = ht - sh, dp + sh
natural = natural + wd
if hs > height then
@@ -3214,7 +3209,7 @@ do
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
+ setnext(slide_node_list(list),new_rule(overfullrule,nil,nil,getdirection(hlist))) -- todo: find_tail
end
diagnostics.overfull_hbox(hlist,line,-delta)
end