diff options
Diffstat (limited to 'tex/context/base/typo-drp.lua')
-rw-r--r-- | tex/context/base/typo-drp.lua | 375 |
1 files changed, 68 insertions, 307 deletions
diff --git a/tex/context/base/typo-drp.lua b/tex/context/base/typo-drp.lua index 3a87d94b3..903140dae 100644 --- a/tex/context/base/typo-drp.lua +++ b/tex/context/base/typo-drp.lua @@ -11,7 +11,9 @@ if not modules then modules = { } end modules ['typo-drp'] = { local tonumber, type, next = tonumber, type, next local ceil = math.ceil -local settings_to_hash = utilities.parsers.settings_to_hash + +local utfbyte = utf.byte +local utfchar = utf.char local trace_initials = false trackers.register("typesetters.initials", function(v) trace_initials = v end) local report_initials = logs.reporter("nodes","initials") @@ -22,42 +24,19 @@ typesetters.initials = initials or { } local nodes = nodes local tasks = nodes.tasks -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getchar = nuts.getchar -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getfield = nuts.getfield -local getattr = nuts.getattr - -local setfield = nuts.setfield -local setattr = nuts.setattr - -local hpack_nodes = nuts.hpack - +local hpack_nodes = nodes.hpack local nodecodes = nodes.nodecodes local whatsitcodes = nodes.whatsitcodes -local nodepool = nuts.pool +local nodepool = nodes.pool local new_kern = nodepool.kern -local insert_before = nuts.insert_before -local insert_after = nuts.insert_after -local remove_node = nuts.remove -local traverse_id = nuts.traverse_id -local traverse = nuts.traverse -local free_node = nuts.free +local insert_before = nodes.insert_before +local insert_after = nodes.insert_after local variables = interfaces.variables local v_default = variables.default local v_margin = variables.margin -local v_auto = variables.auto -local v_first = variables.first -local v_last = variables.last local texget = tex.get local texsetattribute = tex.setattribute @@ -65,8 +44,7 @@ local unsetvalue = attributes.unsetvalue local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist -local glue_code = nodecodes.glue -local kern_code = nodecodes.kern +local kern_node = nodecodes.kern local whatsit_code = nodecodes.whatsit local localpar_code = whatsitcodes.localpar @@ -78,8 +56,6 @@ local a_color = attributes.private('color') local a_transparency = attributes.private('transparency') local a_colorspace = attributes.private('colormodel') -local category = characters.category - local settings = nil function initials.set(specification) @@ -108,288 +84,74 @@ commands.setinitial = initials.set -- todo: prevent linebreak .. but normally a initial ends up at the top of -- a page so this has a low priority --- actions[v_default] = function(head,setting) --- local done = false --- if getid(head) == whatsit_code and getsubtype(head) == localpar_code then --- -- begin of par --- local first = getnext(head) --- -- parbox .. needs to be set at 0 --- if first and getid(first) == hlist_code then --- first = getnext(first) --- end --- -- we need to skip over kerns and glues (signals) --- while first and getid(first) ~= glyph_code do --- first = getnext(first) --- end --- if first and getid(first) == glyph_code then --- local char = getchar(first) --- local prev = getprev(first) --- local next = getnext(first) --- -- if getid(prev) == hlist_code then --- -- -- set the width to 0 --- -- end --- if next and getid(next) == kern_code then --- setfield(next,"kern",0) --- end --- if setting.font then --- setfield(first,"font",setting.font) --- end --- if setting.dynamic > 0 then --- setattr(first,0,setting.dynamic) --- end --- -- can be a helper --- local ma = setting.ma or 0 --- local ca = setting.ca --- local ta = setting.ta --- if ca and ca > 0 then --- setattr(first,a_colorspace,ma == 0 and 1 or ma) --- setattr(first,a_color,ca) --- end --- if ta and ta > 0 then --- setattr(first,a_transparency,ta) --- end --- -- --- local width = getfield(first,"width") --- local height = getfield(first,"height") --- local depth = getfield(first,"depth") --- local distance = setting.distance or 0 --- local voffset = setting.voffset or 0 --- local hoffset = setting.hoffset or 0 --- local parindent = tex.parindent --- local baseline = texget("baselineskip").width --- local lines = tonumber(setting.n) or 0 --- -- --- setfield(first,"xoffset",- width - hoffset - distance - parindent) --- setfield(first,"yoffset",- voffset) -- no longer - height here --- -- We pack so that successive handling cannot touch the dropped cap. Packaging --- -- in a hlist is also needed because we cannot locally adapt e.g. parindent (not --- -- yet stored in with localpar). --- setfield(first,"prev",nil) --- setfield(first,"next",nil) --- local h = hpack_nodes(first) --- setfield(h,"width",0) --- setfield(h,"height",0) --- setfield(h,"depth",0) --- setfield(prev,"next",h) --- setfield(next,"prev",h) --- setfield(h,"next",next) --- setfield(h,"prev",prev) --- first = h --- -- end of packaging --- if setting.location == v_margin then --- -- okay --- else --- if lines == 0 then -- safeguard, not too precise --- lines = ceil((height+voffset) / baseline) --- end --- -- We cannot set parshape yet ... when we can I'll add a slope --- -- option (positive and negative, in emwidth). --- local hangafter = - lines --- local hangindent = width + distance + parindent --- if trace_initials then --- report_initials("setting hangafter to %i and hangindent to %p",hangafter,hangindent) --- end --- tex.hangafter = hangafter --- tex.hangindent = hangindent --- if parindent ~= 0 then --- insert_after(first,first,new_kern(-parindent)) --- end --- end --- done = true --- end --- end --- return head, done --- end - actions[v_default] = function(head,setting) local done = false - if getid(head) == whatsit_code and getsubtype(head) == localpar_code then + if head.id == whatsit_code and head.subtype == localpar_code then -- begin of par - local first = getnext(head) - local indent = false + local first = head.next -- parbox .. needs to be set at 0 - if first and getid(first) == hlist_code then - first = getnext(first) - indent = true + if first and first.id == hlist_code then + first = first.next end -- we need to skip over kerns and glues (signals) - while first and getid(first) ~= glyph_code do - first = getnext(first) + while first and first.id ~= glyph_code do + first = first.next end - if first and getid(first) == glyph_code then - local ma = setting.ma or 0 - local ca = setting.ca - local ta = setting.ta - local last = first + if first and first.id == glyph_code then + local char = first.char + local prev = first.prev + local next = first.next + -- if prev.id == hlist_code then + -- -- set the width to 0 + -- end + if next and next.id == kern_node then + next.kern = 0 + end + if setting.font then + first.font = setting.font + end + if setting.dynamic > 0 then + first[0] = setting.dynamic + end + -- can be a helper + local ma = setting.ma or 0 + local ca = setting.ca + local ta = setting.ta + if ca and ca > 0 then + first[a_colorspace] = ma == 0 and 1 or ma + first[a_color] = ca + end + if ta and ta > 0 then + first[a_transparency] = ta + end + -- + local width = first.width + local height = first.height + local depth = first.depth local distance = setting.distance or 0 local voffset = setting.voffset or 0 local hoffset = setting.hoffset or 0 local parindent = tex.parindent local baseline = texget("baselineskip").width local lines = tonumber(setting.n) or 0 - local dynamic = setting.dynamic - local font = setting.font - local method = settings_to_hash(setting.method) - local length = tonumber(setting.m) or 1 - -- - -- 1 char | n chars | skip first quote | ignore punct | keep punct -- - if getattr(first,a_initial) then - for current in traverse(getnext(first)) do - if getattr(current,a_initial) then - last = current - else - break - end - end - elseif method[v_auto] then - local char = getchar(first) - local kind = category(char) - if kind == "po" or kind == "pi" then - if method[v_first] then - -- remove quote etc before initial - local next = getnext(first) - if not next then - -- don't start with a quote or so - return head, false - end - last = nil - for current in traverse_id(glyph_code,next) do - head, first = remove_node(head,first,true) - first = current - last = first - break - end - if not last then - -- no following glyph or so - return head, false - end - else - -- keep quote etc with initial - local next = getnext(first) - if not next then - -- don't start with a quote or so - return head, false - end - for current in traverse_id(glyph_code,next) do - last = current - break - end - if last == first then - return head, false - end - end - elseif kind == "pf" then - -- error: final quote - else - -- okay - end - -- maybe also: get all A. B. etc - local next = getnext(first) - if next then - for current in traverse_id(glyph_code,next) do - local char = getchar(current) - local kind = category(char) - if kind == "po" then - if method[v_last] then - -- remove period etc after initial - remove_node(head,current,true) - else - -- keep period etc with initial - last = current - end - end - break - end - end - else - for current in traverse_id(glyph_code,first) do - last = current - if length <= 1 then - break - else - length = length - 1 - end - end - end - local current = first - while true do - local id = getid(current) - if id == kern_code then - setfield(current,"kern",0) - elseif id == glyph_code then - local next = getnext(current) - if font then - setfield(current,"font",font) - end - if dynamic > 0 then - setattr(current,0,dynamic) - end - -- can be a helper - if ca and ca > 0 then - setattr(current,a_colorspace,ma == 0 and 1 or ma) - setattr(current,a_color,ca) - end - if ta and ta > 0 then - setattr(current,a_transparency,ta) - end - -- - end - if current == last then - break - else - current = getnext(current) - end - end + first.xoffset = - width - hoffset - distance - parindent + first.yoffset = - voffset -- no longer - height here -- We pack so that successive handling cannot touch the dropped cap. Packaging -- in a hlist is also needed because we cannot locally adapt e.g. parindent (not -- yet stored in with localpar). - local prev = getprev(first) - local next = getnext(last) - -- - setfield(first,"prev",nil) - setfield(last,"next",nil) - local dropper = hpack_nodes(first) - local width = getfield(dropper,"width") - local height = getfield(dropper,"height") - local depth = getfield(dropper,"depth") - setfield(dropper,"width",0) - setfield(dropper,"height",0) - setfield(dropper,"depth",0) - -- - setfield(prev,"next",dropper) - if next then - setfield(next,"prev",dropper) - end - setfield(dropper,"next",next) - setfield(dropper,"prev",prev) - -- - if next then - local current = next - while current do - local id = getid(current) - if id == glue_code or id == kern_code then - local next = getnext(current) - -- remove_node(current,current,true) -- created an invalid next link and dangling remains - remove_node(head,current,true) - current = next - else - break - end - end - end - -- - local hoffset = width + hoffset + distance + (indent and parindent or 0) - for current in traverse_id(glyph_code,first) do - setfield(current,"xoffset",- hoffset ) - setfield(current,"yoffset",- voffset) -- no longer - height here - if current == last then - break - end - end - -- - first = dropper - -- + first.prev = nil + first.next = nil + local h = hpack_nodes(first) + h.width = 0 + h.height = 0 + h.depth = 0 + prev.next = h + next.prev = h + h.next = next + h.prev = prev + + -- end of packaging if setting.location == v_margin then -- okay else @@ -399,15 +161,15 @@ actions[v_default] = function(head,setting) -- We cannot set parshape yet ... when we can I'll add a slope -- option (positive and negative, in emwidth). local hangafter = - lines - local hangindent = width + distance + local hangindent = width + distance + parindent if trace_initials then report_initials("setting hangafter to %i and hangindent to %p",hangafter,hangindent) end tex.hangafter = hangafter tex.hangindent = hangindent - end - if indent then - insert_after(first,first,new_kern(-parindent)) + if parindent ~= 0 then + insert_after(first,first,new_kern(-parindent)) + end end done = true end @@ -416,17 +178,16 @@ actions[v_default] = function(head,setting) end function initials.handler(head) - head = tonut(head) local start = head local attr = nil while start do - attr = getattr(start,a_initial) + attr = start[a_initial] if attr then break - elseif getid(start) == glyph then + elseif start.id == glyph then break else - start = getnext(start) + start = start.next end end if attr then @@ -440,8 +201,8 @@ function initials.handler(head) report_initials("processing initials, alternative %a",alternative) end local head, done = action(head,settings) - return tonode(head), done + return head, done end end - return tonode(head), false + return head, false end |