From 59e7679528d75e5d523acddf69dabdce42d53734 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Wed, 14 Aug 2019 12:32:10 +0200 Subject: 2019-08-14 11:34:00 --- tex/context/base/mkiv/typo-drp.lua | 420 +++++++++++++++++-------------------- 1 file changed, 196 insertions(+), 224 deletions(-) (limited to 'tex/context/base/mkiv/typo-drp.lua') diff --git a/tex/context/base/mkiv/typo-drp.lua b/tex/context/base/mkiv/typo-drp.lua index 6ac59d00c..2f51e5dc0 100644 --- a/tex/context/base/mkiv/typo-drp.lua +++ b/tex/context/base/mkiv/typo-drp.lua @@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['typo-drp'] = { license = "see context related readme files" } --- This ons is sensitive for order (e.g. when combined with first line +-- This one is sensitive for order (e.g. when combined with first line -- processing. -- todo: use isglyph @@ -28,6 +28,7 @@ local enableaction = tasks.enableaction local disableaction = tasks.disableaction local nuts = nodes.nuts +local tonut = nodes.tonut local getnext = nuts.getnext local getprev = nuts.getprev @@ -36,6 +37,9 @@ local getid = nuts.getid local getattr = nuts.getattr local getwhd = nuts.getwhd +local getprop = nuts.getprop +local setprop = nuts.setprop + local setattr = nuts.setattr local setlink = nuts.setlink local setprev = nuts.setprev @@ -46,6 +50,7 @@ local setwhd = nuts.setwhd local setkern = nuts.setkern local setoffsets = nuts.setoffsets local setglyphdata = nuts.setglyphdata +local setattr = nuts.setattr local hpack_nodes = nuts.hpack @@ -70,7 +75,6 @@ local v_last = variables.last local texget = tex.get local texset = tex.set -local texsetattribute = tex.setattribute local unsetvalue = attributes.unsetvalue local glyph_code = nodecodes.glyph @@ -89,16 +93,16 @@ local a_colormodel = attributes.private('colormodel') local category = characters.category -local settings = nil - -function initials.set(specification) - settings = specification or { } - settings.enabled = true +local function set(par,specification) enableaction("processors","typesetters.initials.handler") if trace_initials then report_initials("enabling initials") end - texsetattribute(a_initial,1) + setprop(par,a_initial,specification) +end + +function initials.set(specification) + nuts.setparproperty(set,specification) end interfaces.implement { @@ -123,256 +127,224 @@ interfaces.implement { } } --- dropped caps experiment (will be done properly when luatex --- stores the state in the local par node) .. btw, search still --- works with dropped caps, as does an export - --- we need a 'par' attribute and in fact for dropped caps we don't need --- need an attribute ... dropit will become s state counter (or end up --- in the localpar user data - --- for the moment, each paragraph gets a number as id (attribute) ..problem --- with nesting .. or anyhow, needed for tagging anyway - -- 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 id = getid(head) - if id == localpar_code then -- and getsubtype(head) == 0 - -- begin of par - local first = getnext(head) - local indent = false - -- parbox .. needs to be set at 0 - if first and getid(first) == hlist_code then - first = getnext(first) - indent = true - 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 ma = setting.ma or 0 - local ca = setting.ca - local ta = setting.ta - local last = first - local distance = setting.distance or 0 - local voffset = setting.voffset or 0 - local hoffset = setting.hoffset or 0 - local parindent = texget("parindent") - local baseline = texget("baselineskip",false) - 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 nextnode, 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 - end - last = nil - for current in nextglyph, 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 - 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 - end - for current in nextglyph, next do - last = current - break - end - if last == first then - return head - end - end - elseif kind == "pf" then - -- error: final quote + -- begin of par + local first = getnext(head) + local indent = false + -- parbox .. needs to be set at 0 + if first and getid(first) == hlist_code then + first = getnext(first) + indent = true + 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 ma = setting.ma or 0 + local ca = setting.ca + local ta = setting.ta + local last = first + local distance = setting.distance or 0 + local voffset = setting.voffset or 0 + local hoffset = setting.hoffset or 0 + local parindent = texget("parindent") + local baseline = texget("baselineskip",false) + 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 nextnode, getnext(first) do + if getattr(current,a_initial) then + last = current else - -- okay + break end - -- maybe also: get all A. B. etc - local next = getnext(first) - if next then - for current, char in nextglyph, next do - 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 + 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 end - end - else - for current in nextglyph, first do - last = current - if length <= 1 then + last = nil + for current in nextglyph, next do + head, first = remove_node(head,first,true) + first = current + last = first break - else - length = length - 1 end - end - end - local current = first - while true do - local id = getid(current) - if id == kern_code then - setkern(current,0) - elseif id == glyph_code then - local next = getnext(current) - if font then - setfont(current,font) + if not last then + -- no following glyph or so + return head end - if dynamic > 0 then - setglyphdata(current,dynamic) + else + -- keep quote etc with initial + local next = getnext(first) + if not next then + -- don't start with a quote or so + return head end --- apply font - --- local g = nuts.copy(current) --- g.subtype = 0 --- nodes.handlers.characters(g) --- nodes.handlers.protectglyphs(g) --- setchar(current,g.char) --- nuts.flush_node(g) - - -- can be a helper - if ca and ca > 0 then - setattr(current,a_colormodel,ma == 0 and 1 or ma) - setattr(current,a_color,ca) + for current in nextglyph, next do + last = current + break end - if ta and ta > 0 then - setattr(current,a_transparency,ta) + if last == first then + return head end - -- - end - if current == last then - break - else - current = getnext(current) end + elseif kind == "pf" then + -- error: final quote + else + -- okay end - -- 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) - -- - setprev(first) - setnext(last) - local dropper = hpack_nodes(first) - local width, height, depth = getwhd(dropper) - setwhd(dropper,0,0,0) - -- - setlink(prev,dropper) - setlink(dropper,next) - -- + -- maybe also: get all A. B. etc + local next = getnext(first) 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 + for current, char in nextglyph, next do + 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 - -- - local hoffset = width + hoffset + distance + (indent and parindent or 0) + else for current in nextglyph, first do - setoffsets(current,-hoffset,-voffset) -- no longer - height here - if current == last then + last = current + if length <= 1 then break + else + length = length - 1 end end - -- - first = dropper - -- - if setting.location == v_margin then - -- okay - else - if lines == 0 then -- safeguard, not too precise - lines = ceil((height+voffset) / baseline) + end + local current = first + while true do + local id = getid(current) + if id == kern_code then + setkern(current,0) + elseif id == glyph_code then + local next = getnext(current) + if font then + setfont(current,font) 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 - if trace_initials then - report_initials("setting hangafter to %i and hangindent to %p",hangafter,hangindent) + if dynamic > 0 then + setglyphdata(current,dynamic) end - texset("hangafter",hangafter) - texset("hangindent",hangindent) + -- can be a helper + if ca and ca > 0 then + setattr(current,a_colormodel,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 indent then - insert_after(first,first,new_kern(-parindent)) + if current == last then + break + else + current = getnext(current) end end + -- 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) + -- + setprev(first) + setnext(last) + local dropper = hpack_nodes(first) + local width, height, depth = getwhd(dropper) + setwhd(dropper,0,0,0) + -- + setlink(prev,dropper) + setlink(dropper,next) + -- + 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 nextglyph, first do + setoffsets(current,-hoffset,-voffset) -- no longer - height here + if current == last then + break + end + end + -- + first = dropper + -- + 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 + if trace_initials then + report_initials("setting hangafter to %i and hangindent to %p",hangafter,hangindent) + end + texset("hangafter",hangafter) + texset("hangindent",hangindent) + end + if indent then + insert_after(first,first,new_kern(-parindent)) + end end return head end +-- we can count ... when all done, we can disable ... + function initials.handler(head) - local start = head - local attr = nil - while start do - attr = getattr(start,a_initial) - if attr then - break - elseif getid(start) == glyph then - break - else - start = getnext(start) - end - end - if attr then - -- here as we can process nested boxes first so we need to keep state - disableaction("processors","typesetters.initials.handler") - -- texsetattribute(attribute,unsetvalue) - local alternative = settings.alternative or v_default - local action = actions[alternative] or actions[v_default] - if action then - if trace_initials then - report_initials("processing initials, alternative %a",alternative) + if getid(head) == localpar_code then + local settings = getprop(head,a_initial) + if settings then + disableaction("processors","typesetters.initials.handler") + local alternative = settings.alternative or v_default + local action = actions[alternative] or actions[v_default] + if action then + if trace_initials then + report_initials("processing initials, alternative %a",alternative) + end + return action(head,settings) end - return action(head,settings) end end return head -- cgit v1.2.3