if not modules then modules = { } end modules ['typo-par'] = { version = 1.001, comment = "companion to typo-par.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } -- A playground for experiments. local utfbyte = utf.byte local utfchar = utf.char local trace_paragraphs = false trackers.register("typesetters.paragraphs", function(v) trace_paragraphs = v end) local trace_dropper = false trackers.register("typesetters.paragraphs.dropper",function(v) trace_dropper = v end) local report_paragraphs = logs.reporter("nodes","paragraphs") local report_dropper = logs.reporter("nodes","dropped") typesetters.paragraphs = typesetters.paragraphs or { } local paragraphs = typesetters.paragraphs local nodecodes = nodes.nodecodes local whatsitcodes = nodes.whatsitcodes local tasks = nodes.tasks local variables = interfaces.variables local texattribute = tex.attribute local unsetvalue = attributes.unsetvalue local has_attribute = node.has_attribute local set_attribute = node.set_attribute local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local kern_node = nodecodes.kern local whatsit_code = nodecodes.whatsit local localpar_code = whatsitcodes.localpar local a_paragraph = attributes.private("paragraphspecial") local a_color = attributes.private('color') local a_transparency = attributes.private('transparency') local a_colorspace = attributes.private('colormodel') local dropper = { enabled = false, -- font = 0, -- n = 0, -- distance = 0, -- hoffset = 0, -- voffset = 0, } local droppers = { } typesetters.paragraphs.droppers = droppers function droppers.set(specification) dropper = specification or { } end function droppers.freeze() if dropper.enabled then dropper.font = font.current() end end -- 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 dropper ends up atthe top of -- a page so this has a low priority local function process(namespace,attribute,head) local done = false if head.id == whatsit_code and head.subtype == localpar_code then -- begin of par local a = has_attribute(head,attribute) if a and a > 0 then if dropper.enabled then dropper.enabled = false -- dangerous for e.g. nested || in tufte local first = head.next if first and first.id == hlist_code then -- parbox .. needs to be set at 0 first = first.next end if first and first.id == glyph_code then -- if texattribute[a_paragraph] >= 0 then -- texattribute[a_paragraph] = unsetvalue -- end 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 first.font = dropper.font or first.font -- can be a helper local ma = dropper.ma or 0 local ca = dropper.ca local ta = dropper.ta if ca and ca > 0 then set_attribute(first,a_colorspace,ma == 0 and 1 or ma) set_attribute(first,a_color,ca) end if ta and ta > 0 then set_attribute(first,a_transparency,ta) end -- local width = first.width local height = first.height local depth = first.depth local distance = dropper.distance or 0 local voffset = dropper.voffset or 0 local hoffset = dropper.hoffset or 0 first.xoffset = - width - hoffset - distance first.yoffset = - height - voffset if true then -- needed till we can store parindent with localpar first.prev = nil first.next = nil local h = node.hpack(first) h.width = 0 h.height = 0 h.depth = 0 prev.next = h next.prev = h h.next = next h.prev = prev end if dropper.location == variables.margin then -- okay else local lines = tonumber(dropper.n) or 0 if lines == 0 then -- safeguard, not too precise lines = math.ceil((height+voffset) / tex.baselineskip.width) end tex.hangafter = - lines tex.hangindent = width + distance end done = true end end end end return head, done end local enabled = false function paragraphs.set(n) if n == variables.reset or not tonumber(n) or n == 0 then texattribute[a_paragraph] = unsetvalue else if not enabled then tasks.enableaction("processors","typesetters.paragraphs.handler") if trace_paragraphs then report_paragraphs("enabling paragraphs") end enabled = true end texattribute[a_paragraph] = n end end paragraphs.attribute = a_paragraph paragraphs.handler = nodes.installattributehandler { name = "paragraphs", namespace = paragraphs, processor = process, }