mirror of
https://git.fifo-f.eu/tex-projects/books/The-Invisible-Man-LaTeX.git
synced 2025-04-19 08:28:07 +02:00
initial commit
This commit is contained in:
parent
6eef0f0aca
commit
1665adb13a
41 changed files with 6429 additions and 0 deletions
116
widow-assist.lua
Normal file
116
widow-assist.lua
Normal file
|
@ -0,0 +1,116 @@
|
|||
-- Use method aliases for better performance
|
||||
local nodecopy = node.copy
|
||||
local nodecopylist = node.copy_list
|
||||
local nodetail = node.tail
|
||||
local nodeinsertbefore = node.insert_before
|
||||
local nodeinsertafter = node.insert_after
|
||||
local nodetraverseid = node.traverse_id
|
||||
|
||||
-- Get node ids from their names
|
||||
local HLIST = node.id("hlist")
|
||||
local WHAT = node.id("whatsit")
|
||||
local COL = node.subtype("pdf_colorstack")
|
||||
|
||||
-- Make nodes for beginning and end of colored regions
|
||||
local color_p1 = node.new(WHAT,COL)
|
||||
local color_p1s = node.new(WHAT,COL)
|
||||
local color_m1 = node.new(WHAT,COL)
|
||||
local color_pm1 = node.new(WHAT,COL)
|
||||
local color_pm1s = node.new(WHAT,COL)
|
||||
local color_pop = node.new(WHAT,COL)
|
||||
color_p1.stack = 0
|
||||
color_p1.command = 1
|
||||
color_p1.data = "0 0 1 rg" -- PDF code for RGB blue
|
||||
color_p1s.stack = 0
|
||||
color_p1s.command = 1
|
||||
color_p1s.data = "0 0.7 0.7 rg" -- PDF code for RGB dark cyan
|
||||
color_m1.stack = 0
|
||||
color_m1.command = 1
|
||||
color_m1.data = "1 0 0 rg" -- PDF code for RGB red
|
||||
color_pm1.stack = 0
|
||||
color_pm1.command = 1
|
||||
color_pm1.data = "1 0 1 rg" -- PDF code for RGB magenta
|
||||
color_pm1s.stack = 0
|
||||
color_pm1s.command = 1
|
||||
color_pm1s.data = "1 .5 .5 rg" -- PDF code for RGB pink
|
||||
color_pop.stack = 0
|
||||
color_pop.command = 2
|
||||
|
||||
-- Color to use for last line in the next post-linebreak filter call (nil = no color)
|
||||
local LastLineColor = nil
|
||||
|
||||
-- Function to color the last line in the given list
|
||||
local color_last_line = function (n)
|
||||
-- Get the last hlist in the given list
|
||||
local lastLine
|
||||
for line in nodetraverseid(HLIST, n) do
|
||||
lastLine = line
|
||||
end
|
||||
|
||||
-- Surround it with color start/stop
|
||||
lastLine.head = nodeinsertbefore(lastLine.head, lastLine.head, nodecopy(LastLineColor))
|
||||
nodeinsertafter(lastLine.head, nodetail(lastLine.head), nodecopy(color_pop))
|
||||
end
|
||||
|
||||
-- Callback to check if changing the looseness by +-1 would affect the line count
|
||||
local pre_linebreak_test_looseness = function (head, groupeCode)
|
||||
-- Disable underfull and overfull boxes reporting
|
||||
luatexbase.add_to_callback("hpack_quality", function() end, "hpqfilter")
|
||||
luatexbase.add_to_callback("vpack_quality", function() end, "vpqfilter")
|
||||
|
||||
-- Build a copy of the paragraph normally
|
||||
local n, i = tex.linebreak(nodecopylist(head))
|
||||
|
||||
-- Build a copy of the paragraph with increased looseness and default emergency stretch
|
||||
local nP1s, iP1s = tex.linebreak(nodecopylist(head), {looseness=tex.looseness+1})
|
||||
|
||||
local nP1, iP1
|
||||
if iP1s.prevgraf > i.prevgraf then
|
||||
-- It worked with the default emergency stretch, let's try without
|
||||
nP1, iP1 = tex.linebreak(nodecopylist(head), {looseness=tex.looseness+1, emergencystretch=0})
|
||||
else
|
||||
-- Didn't work with emergency stretch, no point to try without
|
||||
nP1, iP1 = n, i
|
||||
end
|
||||
|
||||
-- Build a copy of the paragraph with decreased looseness
|
||||
local nM1, iM1 = tex.linebreak(nodecopylist(head), {looseness=tex.looseness-1})
|
||||
|
||||
-- Reenable underfull and overfull boxes reporting
|
||||
luatexbase.remove_from_callback("hpack_quality", "hpqfilter")
|
||||
luatexbase.remove_from_callback("vpack_quality", "vpqfilter")
|
||||
|
||||
-- Set color to use in the post-linebreak callback
|
||||
if iP1.prevgraf > i.prevgraf and iM1.prevgraf < i.prevgraf then
|
||||
-- Both +1 and -1 looseness would work
|
||||
LastLineColor = color_pm1
|
||||
elseif iP1s.prevgraf > i.prevgraf and iM1.prevgraf < i.prevgraf then
|
||||
-- Both +1 and -1 looseness would work, but +1 only with emergency stretch
|
||||
LastLineColor = color_pm1s
|
||||
elseif iP1.prevgraf > i.prevgraf then
|
||||
-- Only +1 looseness would work
|
||||
LastLineColor = color_p1
|
||||
elseif iP1s.prevgraf > i.prevgraf then
|
||||
-- Only +1 looseness would work and only thanks to the emergency stretch
|
||||
LastLineColor = color_p1s
|
||||
elseif iM1.prevgraf < i.prevgraf then
|
||||
-- Only -1 looseness would work
|
||||
LastLineColor = color_m1
|
||||
else
|
||||
LastLineColor = nil
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Callback to colorize the last line of the paragraph when ColorLastLine is true
|
||||
local post_linebreak_color_last_line = function (head, groupcode)
|
||||
if LastLineColor then
|
||||
color_last_line(head)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Register callbacks
|
||||
luatexbase.add_to_callback("pre_linebreak_filter", pre_linebreak_test_looseness, "pre_linebreak_test_looseness")
|
||||
luatexbase.add_to_callback("post_linebreak_filter", post_linebreak_color_last_line, "post_linebreak_color_last_line")
|
Loading…
Add table
Add a link
Reference in a new issue