diff options
Diffstat (limited to 'macros/luatex/latex/linebreaker/linebreaker.lua')
-rw-r--r-- | macros/luatex/latex/linebreaker/linebreaker.lua | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/macros/luatex/latex/linebreaker/linebreaker.lua b/macros/luatex/latex/linebreaker/linebreaker.lua index 6a2d20e074..99966ad302 100644 --- a/macros/luatex/latex/linebreaker/linebreaker.lua +++ b/macros/luatex/latex/linebreaker/linebreaker.lua @@ -1,3 +1,11 @@ +-- linebreaker.lua +-- +-- (c) Michal Hoftich <michal.h21@gmail.com> +-- +-- This program can be redistributed and/or modified under the terms +-- of the LaTeX Project Public License Distributed from CTAN archives +-- in directory macros/latex/base/lppl.txt. + local linebreaker = {} local hlist_id = node.id "hlist" @@ -22,7 +30,7 @@ end linebreaker.debug = false -- max allowed value of tolerance -linebreaker.max_tolerance = 9999 +linebreaker.max_tolerance = 8189 -- maximal possible value of tolerance (thanks to Jan Šustek for pointing that out) -- maximal allowed emergencystretch linebreaker.max_emergencystretch = tex.sp("3em") -- line breaking function is customizable @@ -43,9 +51,38 @@ linebreaker.previous_points = linebreaker.vertical_point / linebreaker.boxsize linebreaker.width_factor = 1.5 -- will be linebreaker active? linebreaker.active = true + +-- use cubic method for tolerance calculation +linebreaker.use_cubic = false -- return array with default parameters function linebreaker.parameters() - return {} + return { + pardir = tex.pardir + ,pretolerance = tex.pretolerance + ,tracingparagraphs=tex.tracingparagraphs + ,tolerance=tex.tolerance + ,looseness=tex.looseness + ,hyphenpenalty=tex.hyphenpenalty + ,exhyphenpenalty=tex.exhyphenpenalty + ,pdfadjustspacing=tex.pdfadjustspacing + ,adjdemerits=tex.adjdemerits + ,pdfprotrudechars=tex.pdfprotrudechars + ,linepenalty=tex.linepenalty + ,lastlinefit=tex.lastlinefit + ,doublehyphendemerits=tex.doublehyphendemerits + ,finalhyphendemerits=tex.finalhyphendemerits + ,hangafter=tex.hangafter + ,interlinepenalty=tex.interlinepenalty + ,clubpenalty=tex.clubpenalty + ,widowpenalty=tex.widowpenalty + ,brokenpenalty=tex.brokenpenalty + ,emergencystretch=tex.emergencystretch + ,hangindent=tex.hangindent + ,hsize=tex.hsize + ,leftskip=tex.leftskip + ,rightskip=tex.rightskip + ,parshape=tex.parshape + } end -- diagnostic function for traversing nodes returned by linebreaking @@ -144,9 +181,23 @@ local function glue_calc(n, sign,set) end --- calculate new tolerance +local function cube_root(num) + return num ^(1/3) +end + + +-- calculate new tolerance using method suggested by Jan Šustek +local function calc_tolerance_cubic(previous, step) + local previous = previous or tex.tolerance + local max_cycles = linebreaker.max_cycles + local max_tolerance = linebreaker.max_tolerance + local new = 100 * (cube_root(previous / 100) + (cube_root(max_tolerance/100) - cube_root(previous/100)) * (step/max_cycles))^3 + -- local new = previous + (max_tolerance / max_cycles)-- + math.sqrt(previous * 4) + return (new < max_tolerance) and new or max_tolerance +end + -- max_tolerance / max_cycles is added to the current tolerance value -local function calc_tolerance(previous) +local function calc_tolerance(previous, step) local previous = previous or tex.tolerance local max_cycles = linebreaker.max_cycles local max_tolerance = linebreaker.max_tolerance @@ -340,7 +391,9 @@ end -- try to linebreak current paragraph with increasing tolerance and -- emergencystretch -function linebreaker.best_solution(par, parameters) +function linebreaker.best_solution(par, parameters, step) + -- step is used in the tolerance calculation + local step = (step or 0) + 1 -- save current node list, because call to the linebreaker modifies it -- and we wouldn't be able to run it multiple times local head = node.copy_list(par) @@ -373,9 +426,14 @@ function linebreaker.best_solution(par, parameters) params.badness = badness if badness > 0 then -- calc new value of tolerance - local tolerance = calc_tolerance(params.tolerance) -- or 10000 + local tolerance + if linebreaker.use_cubic then + tolerance = calc_tolerance_cubic(params.tolerance, step) -- or 10000 + else + tolerance = calc_tolerance(params.tolerance, step) -- or 10000 + end -- save tolerance to newparams so this value will be used in next run - newparams.tolerance = tolerance + newparams.tolerance = math.floor(tolerance) newparams.emergencystretch = (params.emergencystretch or 0) + linebreaker.max_emergencystretch / linebreaker.max_cycles table.insert(parameters, newparams) -- run linebreaker again |