diff options
Diffstat (limited to 'tex/context/base/typo-drp.lua')
-rw-r--r-- | tex/context/base/typo-drp.lua | 308 |
1 files changed, 261 insertions, 47 deletions
diff --git a/tex/context/base/typo-drp.lua b/tex/context/base/typo-drp.lua index b3f840ae1..57818d62f 100644 --- a/tex/context/base/typo-drp.lua +++ b/tex/context/base/typo-drp.lua @@ -11,9 +11,7 @@ if not modules then modules = { } end modules ['typo-drp'] = { local tonumber, type, next = tonumber, type, next local ceil = math.ceil - -local utfbyte = utf.byte -local utfchar = utf.char +local settings_to_hash = utilities.parsers.settings_to_hash local trace_initials = false trackers.register("typesetters.initials", function(v) trace_initials = v end) local report_initials = logs.reporter("nodes","initials") @@ -49,10 +47,17 @@ 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 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 @@ -60,7 +65,8 @@ local unsetvalue = attributes.unsetvalue local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist -local kern_node = nodecodes.kern +local glue_code = nodecodes.glue +local kern_code = nodecodes.kern local whatsit_code = nodecodes.whatsit local localpar_code = whatsitcodes.localpar @@ -72,6 +78,8 @@ 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) @@ -100,6 +108,99 @@ 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 @@ -114,60 +215,173 @@ actions[v_default] = function(head,setting) 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_node 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") + +-- show(head,8,"one") + + 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 = 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 -- - setfield(first,"xoffset",- width - hoffset - distance - parindent) - setfield(first,"yoffset",- voffset) -- no longer - height here + if 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 + 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 -- 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(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 + 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 + parindent + 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 + -- if setting.location == v_margin then -- okay else |