summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/typo-fln.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/typo-fln.lua')
-rw-r--r--tex/context/base/mkiv/typo-fln.lua156
1 files changed, 121 insertions, 35 deletions
diff --git a/tex/context/base/mkiv/typo-fln.lua b/tex/context/base/mkiv/typo-fln.lua
index 1e1a2c44a..cef77cea1 100644
--- a/tex/context/base/mkiv/typo-fln.lua
+++ b/tex/context/base/mkiv/typo-fln.lua
@@ -21,7 +21,10 @@ typesetters.firstlines = typesetters.firstlines or { }
local firstlines = typesetters.firstlines
local nodes = nodes
+
local tasks = nodes.tasks
+local enableaction = tasks.enableaction
+local disableaction = tasks.disableaction
local context = context
local implement = interfaces.implement
@@ -31,6 +34,9 @@ local tonut = nuts.tonut
local tonode = nuts.tonode
local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getboth = nuts.getboth
+local setboth = nuts.setboth
local getid = nuts.getid
local getfield = nuts.getfield
local setfield = nuts.setfield
@@ -39,6 +45,10 @@ local setlist = nuts.setlist
local getattr = nuts.getattr
local setattr = nuts.setattr
local getbox = nuts.getbox
+local getdisc = nuts.getdisc
+local setdisc = nuts.setdisc
+local setlink = nuts.setlink
+local setfont = nuts.setfont
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
@@ -46,13 +56,12 @@ local disc_code = nodecodes.disc
local kern_code = nodecodes.kern
local traverse_id = nuts.traverse_id
-local free_node_list = nuts.flush_list
-local free_node = nuts.flush_node
+local flush_node_list = nuts.flush_list
+local flush_node = nuts.flush_node
local copy_node_list = nuts.copy_list
local insert_node_after = nuts.insert_after
-local insert_node_before = nuts.insert_before
-local hpack_node_list = nuts.hpack
local remove_node = nuts.remove
+local list_dimensions = nuts.dimensions
local nodepool = nuts.pool
local newpenalty = nodepool.penalty
@@ -65,7 +74,7 @@ firstlines.actions = actions
local a_firstline = attributes.private('firstline')
local a_color = attributes.private('color')
local a_transparency = attributes.private('transparency')
-local a_colorspace = attributes.private('colormodel')
+local a_colormodel = attributes.private('colormodel')
local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
@@ -82,7 +91,7 @@ local settings = nil
function firstlines.set(specification)
settings = specification or { }
- tasks.enableaction("processors","typesetters.firstlines.handler")
+ enableaction("processors","typesetters.firstlines.handler")
if trace_firstlines then
report_firstlines("enabling firstlines")
end
@@ -120,12 +129,31 @@ actions[v_line] = function(head,setting)
local n = 0
local temp = copy_node_list(head)
local linebreaks = { }
- for g in traverse_id(glyph_code,temp) do
- if dynamic > 0 then
- setattr(g,0,dynamic)
+
+ local function set(head)
+ for g in traverse_id(glyph_code,head) do
+ if dynamic > 0 then
+ setattr(g,0,dynamic)
+ end
+ setfont(g,font)
+ end
+ end
+
+ set(temp)
+
+ for g in traverse_id(disc_code,temp) do
+ local pre, post, replace = getdisc(g)
+ if pre then
+ set(pre)
+ end
+ if post then
+ set(post)
+ end
+ if replace then
+ set(replace)
end
- setfield(g,"font",font)
end
+
local start = temp
local list = temp
local prev = temp
@@ -137,25 +165,37 @@ actions[v_line] = function(head,setting)
if i <= - hangafter then
hsize = hsize - hangindent
end
+
+ local function try(extra)
+ local width = list_dimensions(list,start)
+ if extra then
+ width = width + list_dimensions(extra)
+ end
+ if width > hsize then
+ list = prev
+ return true
+ else
+ linebreaks[i] = n
+ prev = start
+ nofchars = n
+ end
+ end
+
while start do
local id = getid(start)
if id == glyph_code then
n = n + 1
elseif id == disc_code then
-- this could be an option
+ n = n + 1
+ if try(getfield(start,"pre")) then
+ break
+ end
elseif id == kern_code then -- todo: fontkern
-- this could be an option
elseif n > 0 then
- local pack = hpack_node_list(copy_node_list(list,start))
- if getfield(pack,"width") > hsize then
- free_node_list(pack)
- list = prev
+ if try() then
break
- else
- linebreaks[i] = n
- prev = start
- free_node_list(pack)
- nofchars = n
end
end
start = getnext(start)
@@ -166,23 +206,69 @@ actions[v_line] = function(head,setting)
end
local start = head
local n = 0
+
+ local function update(start)
+ if dynamic > 0 then
+ setattr(start,0,dynamic)
+ end
+ setfont(start,font)
+ if ca and ca > 0 then
+ setattr(start,a_colormodel,ma == 0 and 1 or ma)
+ setattr(start,a_color,ca)
+ end
+ if ta and ta > 0 then
+ setattr(start,a_transparency,ta)
+ end
+ end
+
for i=1,noflines do
local linebreak = linebreaks[i]
while start and n < nofchars do
local id = getid(start)
- if id == glyph_code then -- or id == disc_code then
- if dynamic > 0 then
- setattr(start,0,dynamic)
- end
- setfield(start,"font",font)
- if ca and ca > 0 then
- setattr(start,a_colorspace,ma == 0 and 1 or ma)
- setattr(start,a_color,ca)
- end
- if ta and ta > 0 then
- setattr(start,a_transparency,ta)
- end
+ if id == glyph_code then
n = n + 1
+ update(start)
+ elseif id == disc_code then
+ n = n + 1
+ local disc = start
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true)
+ if linebreak == n then
+ local p, n = getboth(start)
+ if pre then
+ for current in traverse_id(glyph_code,pre) do
+ update(current)
+ end
+ setlink(pretail,n)
+ setlink(p,pre)
+ start = pretail
+ pre = nil
+ else
+ setlink(p,n)
+ start = p
+ end
+ if post then
+ local p, n = getboth(start)
+ setlink(posttail,n)
+ setlink(start,post)
+ post = nil
+ end
+ else
+ local p, n = getboth(start)
+ if replace then
+ for current in traverse_id(glyph_code,replace) do
+ update(current)
+ end
+ setlink(replacetail,n)
+ setlink(p,replace)
+ start = replacetail
+ replace = nil
+ else
+ setlink(p,n)
+ start = p
+ end
+ end
+ setdisc(disc,pre,post,replace)
+ flush_node(disc)
end
if linebreak == n then
if trace_firstlines then
@@ -196,7 +282,7 @@ actions[v_line] = function(head,setting)
start = getnext(start)
end
end
- free_node_list(temp)
+ flush_node_list(temp)
return head, true
end
@@ -220,7 +306,7 @@ actions[v_word] = function(head,setting)
ok = true
end
if ca and ca > 0 then
- setattr(start,a_colorspace,ma == 0 and 1 or ma)
+ setattr(start,a_colormodel,ma == 0 and 1 or ma)
setattr(start,a_color,ca)
end
if ta and ta > 0 then
@@ -229,7 +315,7 @@ actions[v_word] = function(head,setting)
if dynamic > 0 then
setattr(start,0,dynamic)
end
- setfield(start,"font",font)
+ setfont(start,font)
elseif id == disc_code then
-- continue
elseif id == kern_code then -- todo: fontkern
@@ -263,7 +349,7 @@ function firstlines.handler(head)
end
if attr then
-- here as we can process nested boxes first so we need to keep state
- tasks.disableaction("processors","typesetters.firstlines.handler")
+ disableaction("processors","typesetters.firstlines.handler")
-- texsetattribute(attribute,unsetvalue)
local alternative = settings.alternative or v_default
local action = actions[alternative] or actions[v_default]