From 974640d66e61e81cb197ad96fdff7b08343e4c5a Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sat, 6 Mar 2021 21:58:15 +0000 Subject: context git-svn-id: svn://tug.org/texlive/trunk@58167 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/tex/context/base/mkxl/driv-shp.lmt | 1358 ++++++++++++++++++++ 1 file changed, 1358 insertions(+) create mode 100644 Master/texmf-dist/tex/context/base/mkxl/driv-shp.lmt (limited to 'Master/texmf-dist/tex/context/base/mkxl/driv-shp.lmt') diff --git a/Master/texmf-dist/tex/context/base/mkxl/driv-shp.lmt b/Master/texmf-dist/tex/context/base/mkxl/driv-shp.lmt new file mode 100644 index 00000000000..d3a47bf0d2e --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkxl/driv-shp.lmt @@ -0,0 +1,1358 @@ +if not modules then modules = { } end modules ['driv-shp'] = { + version = 1.001, + optimize = true, + comment = "companion to driv-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, next = type, next + +local setmetatableindex = table.setmetatableindex +local formatters = string.formatters +local concat = table.concat +local keys = table.keys +local sortedhash = table.sortedhash +local splitstring = string.split +local find = string.find +local stripstring = string.strip +local idiv = number.idiv +local sequenced = table.sequenced +local round = math.round +local extract = bit32.extract +local nuts = nodes.nuts + +local tonut = nodes.tonut +local tonode = nodes.tonode + +local getdirection = nuts.getdirection +local getlist = nuts.getlist +local getoffsets = nuts.getoffsets +local getorientation = nuts.getorientation +local getfield = nuts.getfield +local getwhd = nuts.getwhd +local getkern = nuts.getkern +local getheight = nuts.getheight +local getdepth = nuts.getdepth +----- getwidth = nuts.getwidth +local getnext = nuts.getnext +local getsubtype = nuts.getsubtype +local getid = nuts.getid +local getleader = nuts.getleader +----- getglue = nuts.getglue +local getshift = nuts.getshift +local getdata = nuts.getdata +----- getexpansion = nuts.getexpansion +local getreplace = nuts.getreplace +local setreplace = nuts.setreplace +local getfont = nuts.getfont +local getkerndimension = nuts.getkerndimension + +local setdirection = nuts.setdirection +local setfield = nuts.setfield +local setlink = nuts.setlink + +local isglyph = nuts.isglyph +local findtail = nuts.tail +local nextdir = nuts.traversers.dir +local nextnode = nuts.traversers.node + +----- rangedimensions = node.direct.rangedimensions -- nuts ? +local effectiveglue = nuts.effective_glue +local start_of_par = nuts.start_of_par +local dirdimensions = nuts.dirdimensions + +local texget = tex.get + +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers +local characters = fonthashes.characters +local parameters = fonthashes.parameters + +local nodecodes = nodes.nodecodes +local whatsitcodes = nodes.whatsitcodes +local gluecodes = nodes.gluecodes +local dircodes = nodes.dircodes +local dirvalues = nodes.dirvalues +local subtypes = nodes.subtypes + +local lefttoright_code = dirvalues.lefttoright +local righttoleft_code = dirvalues.righttoleft + +local glyph_code = nodecodes.glyph +local kern_code = nodecodes.kern +local glue_code = nodecodes.glue +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local dir_code = nodecodes.dir +local disc_code = nodecodes.disc +local math_code = nodecodes.math +local rule_code = nodecodes.rule +local whatsit_code = nodecodes.whatsit +----- penalty_code = nodecodes.penalty +----- boundary_code = nodecodes.boundary + +local leaders_code = gluecodes.leaders +local cleaders_code = gluecodes.cleaders +local xleaders_code = gluecodes.xleaders +local gleaders_code = gluecodes.gleaders + +local spaceskip_code = gluecodes.spaceskip + +local getpagedimensions = layouts.getpagedimensions + +local drivers = drivers +local instances = drivers.instances + +local report = logs.reporter("drivers") + +--------------------------------------------------------------------------------------- + +local lastfont = nil +local fontcharacters = nil + +local magicconstants = tex.magicconstants +local trueinch = magicconstants.trueinch +local maxdimen = magicconstants.maxdimen +local running = magicconstants.running + +local pos_h = 0 +local pos_v = 0 +local pos_r = lefttoright_code +local shippingmode = "none" + +local abs_max_v = 0 +local abs_max_h = 0 + +local shipbox_h = 0 +local shipbox_v = 0 +local page_size_h = 0 +local page_size_v = 0 +----- page_h_origin = 0 -- trueinch +----- page_v_origin = 0 -- trueinch + +local initialize +local finalize +local updatefontstate +local pushorientation +local poporientation +local flushcharacter +local flushfontchar +local flushrule +local flushliteral +local flushwhatsit + +-- make local + +function drivers.getpos () return round(pos_h), round(pos_v) end +function drivers.getrpos() return round(pos_h), round(pos_v), pos_r end +function drivers.gethpos() return round(pos_h) end +function drivers.getvpos() return round(pos_v) end + +-- characters + +local flush_character do + + local stack = setmetatableindex("table") + local level = 0 + local nesting = 0 + local main = 0 + + -- experiment (smaller page stream but might be fragile) + + local tospace = false directives.register("backends.spaces", function(v) tospace = v end) + + -- todo: cache streams + + local default = 16384 * number.dimenfactors.bp -- 65536 // 4 + + local vfinjectors = fonts.helpers.vfinjectors + + local function flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy) + + if nesting > 100 then + return + elseif nesting == 0 then + main = font + end + + nesting = nesting + 1 + + local saved_h = pos_h + local saved_v = pos_v + local saved_r = pos_r + pos_r = lefttoright_code + + local data = fontdata[font] + local fnt = font + local fonts = data.fonts + local siz = (data.parameters.factor or 1)/65536 + + local function flushchar(font,char,fnt,chr,f,e) + if fnt then + local nest = char ~= chr or font ~= fnt + if fnt == 0 then + fnt = main + end + return flush_character(current,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e) + else + return 0 + end + end + + -- we assume resolved fonts: id mandate but maybe also size + + -- we could map left, right, up, down -> offset + -- we could map char, font, slot to -> slot + + for i=1,#vfcommands do + local packet = vfcommands[i] + local command = packet[1] + if command == "char" then + local chr = packet[2] + local f = packet[3] + local e = packet[4] + pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) + elseif command == "slot" then + local index = packet[2] + local chr = packet[3] + local f = packet[4] + local e = packet[5] + if index == 0 then + pos_h = pos_h + flushchar(font,char,font,chr,f,e) + else + local okay = fonts and fonts[index] + if okay then + local fnt = okay.id + if fnt then + pos_h = pos_h + flushchar(font,char,fnt,chr,f,e) + end + else + -- safeguard, we assume the font itself (often index 1) + pos_h = pos_h + flushchar(font,char,font,chr,f,e) + end + end + elseif command == "use" then + local index = packet[2] + if index then + local fnt + if index == 0 then + fnt = font + else + local okay = fonts and fonts[index] + if okay then + fnt = okay.id + end + end + if fnt then + -- not efficient but ok for now as experiment + local d = characters[fnt] + if d then + for i=3,#packet do + local chr = packet[i] + local dat = d[chr] + if dat then + flushfontchar(fnt,chr,dat) + end + end + end + end + end + elseif command == "right" then + local h = packet[2] -- already scaled + if h ~= 0 then + if factor ~= 0 then + h = h + h * factor / 1000 -- expansion + end + pos_h = pos_h + h * sx + end + elseif command == "left" then + local h = packet[2] -- already scaled + if h ~= 0 then + if factor ~= 0 then + h = h + h * factor / 1000 -- expansion + end + pos_h = pos_h - h * sx + end + elseif command == "down" then + local v = packet[2] -- already scaled + if v and v ~= 0 then + pos_v = pos_v - v * sy + end + elseif command == "up" then + local v = packet[2] -- already scaled + if v and v ~= 0 then + pos_v = pos_v + v * sy + end + elseif command == "offset" then + local ph = pos_h + local pv = pos_v + local h = packet[2] or 0 + local v = packet[3] or 0 + local c = packet[4] + if h ~= 0 then + if factor ~= 0 then + h = h + h * factor / 1000 -- expansion + end + pos_h = pos_h + h * sx + end + if v and v ~= 0 then + pos_v = pos_v + v * sy + end + if c then + flushchar(font,char,fnt,c) + pos_h = ph + pos_v = pv + end + elseif command == "compose" then + local ph = pos_h + local pv = pos_v + local h = packet[2] or 0 + local v = packet[3] or 0 + local c = packet[4] + if h ~= 0 then + if factor ~= 0 then + h = h + h * factor / 1000 -- expansion + end + pos_h = pos_h + h * sx + end + if v and v ~= 0 then + pos_v = pos_v + v * sy + end + if c then + flushchar(font,char,fnt,c) + pos_h = ph + pos_v = pv + end + elseif command == "push" then + level = level + 1 + local s = stack[level] + s[1] = pos_h + s[2] = pos_v + elseif command == "pop" then + if level > 0 then + local s = stack[level] + pos_h = s[1] + pos_v = s[2] + level = level - 1 + end + elseif command == "rule" then + local size_v = packet[2] + local size_h = packet[3] + if size_h > 0 and size_v > 0 then + if factor ~= 0 then + size_h = size_h + size_h * factor / 1000 + end + if size_h > 0 then + size_h = size_h * sx + size_v = size_v * sy + flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v) + pos_h = pos_h + size_h + end + end + elseif command == "frame" then + -- d:width d:height d:depth d:rulethickness b:outline b:advance b:baseline s:color + local width = packet[2] + if width > 0 then + local height = packet[3] or 0 + local depth = packet[4] or 0 + local total = height + depth + if total > 0 then + if factor ~= 0 then + width = width + width * factor / 1000 + end + if width > 0 then + local line = packet[5] or default + local outline = not packet[6] + local advance = not packet[7] + local baseline = outline and packet[8] + local color = packet[9] -- no longer needed probably + if color then + vfinjectors.startcolor(pos_h,pos_v,color) -- takes packet or string + end + width = width * sx + height = height * sy + depth = depth * sy + flushspecialrule(pos_h,pos_v,pos_r,width,height,depth,line,outline,baseline) + if color then + vfinjectors.stopcolor() + end + if advance then + pos_h = pos_h + width + end + end + end + end + elseif command == "font" then + local index = packet[2] + local okay = fonts and fonts[index] + if okay then + fnt = okay.id or fnt -- or maybe just return + end + elseif command == "lua" then + local code = packet[2] + local kind = type(code) + if kind ~= "function" then + code = loadstring(code) + kind = type(code) + end + if kind == "function" then + code(font,char,pos_h,pos_v,sx,sy) + end + elseif command == "node" then -- obsolete + local h = packet[2] + hlist_out(h,getlist(h)) + else + local injector = vfinjectors[command] + if injector then + injector(pos_h,pos_v,packet) + end + end + -- image : not needed, maybe some day + -- pdfmode : not used + -- special : makes no sense + -- nop : the official ignore + -- scale : not supported + end + + pos_h = saved_h + pos_v = saved_v + pos_r = saved_r + + nesting = nesting - 1 + end + + local onetimemessage -- could be defined later (todo: make plug for this) + + local getxyscales = nuts.getxyscales + + flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,f,e) + + if font ~= lastfont then + lastfont = font + fontcharacters = characters[font] + updatefontstate(font) + end + + local data = fontcharacters[char] + if not data then + if char > 0 then + if not onetimemessage then + onetimemessage = fonts.loggers.onetimemessage + end + onetimemessage(font,char,"missing") + end + return 0, 0, 0 + end + if vfcommands then + vfcommands = data.commands + end + local width, height, depth, naturalwidth, sx, sy + if current then + naturalwidth, height, depth, factor = getwhd(current,true) -- also get corrected width + sx, sy = getxyscales(current) -- maybe: getwhdfs + if factor == 0 then + width = naturalwidth + else + -- width = (1.0 + factor/1000000.0) * naturalwidth + width = naturalwidth + naturalwidth * factor/1000000.0 + -- width = naturalwidth + naturalwidth * 0.000001 * factor + end + else + width = data.width or 0 + height = data.height or 0 + depth = data.depth or 0 + naturalwidth = width + if not factor then + factor = 0 + end + sx = 1 + sy = 1 + end + if pos_r == righttoleft_code then + pos_h = pos_h - width -- here ? + end + if vfcommands then + flush_vf_packet(current,pos_h,pos_v,pos_r,font,char,data,factor,vfcommands,sx,sy) -- also f ? + else + -- kind of messy that we do orientation here and offsets elsewhere .. this might change + local orientation = data.orientation + if orientation and (orientation == 1 or orientation == 3) then + local x = data.xoffset + local y = data.yoffset + if x then + pos_h = pos_h + x + end + if y then + pos_v = pos_v + y + end + pushorientation(orientation,pos_h,pos_v) + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width) + poporientation(orientation,pos_h,pos_v) + else + flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,f,e,factor,sx,sy) -- ,naturalwidth,width) + end + end + return width, height, depth + end + +end + +-- end of characters + +local function reset_state() + pos_h = 0 + pos_v = 0 + pos_r = lefttoright_code + shipbox_h = 0 + shipbox_v = 0 + shippingmode = "none" + page_size_h = 0 + page_size_v = 0 + -- page_h_origin = 0 -- trueinch + -- page_v_origin = 0 -- trueinch +end + +-- local function dirstackentry(t,k) +-- local v = { +-- cur_h = 0, +-- cur_v = 0, +-- ref_h = 0, +-- ref_v = 0, +-- } +-- t[k] = v +-- return v +-- end +-- +-- local dirstack = setmetatableindex(dirstackentry) +-- +-- local function reset_dir_stack() +-- dirstack = setmetatableindex(dirstackentry) +-- end + +local dirstack = { } + +local function reset_dir_stack() + dirstack = { } +end + +local hlist_out, vlist_out do + + local function applyanchor(orientation,x,y,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) + local ot = extract(orientation, 0,4) + local ay = extract(orientation, 4,4) + local ax = extract(orientation, 8,4) + local of = extract(orientation,12,4) + if ot == 4 then + ot, ay = 0, 1 + elseif ot == 5 then + ot, ay = 0, 2 + end + if ot == 0 or ot == 2 then + if ax == 1 then x = x - width + elseif ax == 2 then x = x + width + elseif ax == 3 then x = x - width/2 + elseif ax == 4 then x = x + width/2 + end + if ot == 2 then + doffset, hoffset = hoffset, doffset + end + if ay == 1 then y = y - doffset + elseif ay == 2 then y = y + hoffset + elseif ay == 3 then y = y + (doffset + hoffset)/2 - doffset + end + elseif ot == 1 or ot == 3 then + if ay == 1 then y = y - height + elseif ay == 2 then y = y + height + elseif ay == 3 then y = y - height/2 + end + if ot == 1 then + doffset, hoffset = hoffset, doffset + end + if ax == 1 then x = x - width + elseif ax == 2 then x = x + width + elseif ax == 3 then x = x - width/2 + elseif ax == 4 then x = x + width/2 + elseif ax == 5 then x = x - hoffset + elseif ax == 6 then x = x + doffset + end + end + return ot, x + xoffset, y - yoffset + end + + -- to be checked: begin- or enddir kan nil zijn, weird + + -- local function calculate_width_to_enddir(this_box,begindir) -- can be a helper + -- local dir_nest = 1 + -- local enddir = begindir + -- for current, subtype in nextdir, getnext(begindir) do + -- if subtype == normaldir_code then -- todo + -- dir_nest = dir_nest + 1 + -- else + -- dir_nest = dir_nest - 1 + -- end + -- if dir_nest == 0 then -- does the type matter + -- enddir = current + -- local width = rangedimensions(this_box,begindir,enddir) + -- return enddir, width + -- end + -- end + -- if enddir == begindir then + -- local width = rangedimensions(this_box,begindir) -- ,enddir) + -- return enddir, width + -- end + -- return enddir, 0 + -- end + + -- check frequencies of nodes + + hlist_out = function(this_box,current) + local ref_h = pos_h + local ref_v = pos_v + local ref_r = pos_r + pos_r = getdirection(this_box) + local boxwidth, + boxheight, + boxdepth = getwhd(this_box) + + local cur_h = 0 + local cur_v = 0 + + -- if not current then + -- current = getlist(this_box) + -- end + + -- we can encounter par, boundary and penalty nodes but a special + -- iterator over content nodes won't save much + for current, id, subtype in nextnode, current do + if id == glyph_code then + local char, font = isglyph(current) + local x_offset, y_offset, left, right, raise = getoffsets(current) + if x_offset ~= 0 or y_offset ~= 0 then + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + x_offset) + else + pos_h = ref_h + (cur_h + x_offset) + end + pos_v = ref_v - (cur_v - y_offset) + -- synced + end + pos_v = pos_v + raise + pos_h = pos_h - left + local wd = flush_character(current,font,char,false,true,pos_h,pos_v,pos_r) + cur_h = cur_h + wd - right + elseif id == glue_code then + local gluewidth = effectiveglue(current,this_box) + if gluewidth ~= 0 then + if subtype >= leaders_code then + local leader = getleader(current) + if leader then + local width, height, depth = getwhd(leader) + if getid(leader) == rule_code then + if gluewidth > 0 then + if height == running then + height = boxheight + end + if depth == running then + depth = boxdepth + end + local total = height + depth + if total > 0 then + if pos_r == righttoleft_code then + pos_h = pos_h - gluewidth + end + pos_v = pos_v - depth + flushrule(leader,pos_h,pos_v,pos_r,gluewidth,total,getsubtype(leader)) + end + cur_h = cur_h + gluewidth + end + elseif width > 0 and gluewidth > 0 then + local boxdir = getdirection(leader) or lefttoright_code + gluewidth = gluewidth + 10 + local edge = cur_h + gluewidth + local lx = 0 + if subtype == gleaders_code then + local save_h = cur_h + if pos_r == righttoleft_code then + cur_h = ref_h - shipbox_h - cur_h + cur_h = width * (cur_h / width) + cur_h = ref_h - shipbox_h - cur_h + else + cur_h = cur_h + ref_h - shipbox_h + cur_h = width * (cur_h / width) + cur_h = cur_h - ref_h - shipbox_h + end + if cur_h < save_h then + cur_h = cur_h + width + end + elseif subtype == leaders_code then + local save_h = cur_h + cur_h = width * (cur_h / width) + if cur_h < save_h then + cur_h = cur_h + width + end + else + lq = gluewidth / width + lr = gluewidth % width + if subtype == cleaders_code then + cur_h = cur_h + lr / 2 + else + lx = lr / (lq + 1) + cur_h = cur_h + (lr - (lq - 1) * lx) / 2 + end + end + local shift = getshift(leader) + pushleaderlevel() + while cur_h + width <= edge do + local basepoint_h = 0 + -- local basepoint_v = shift + if boxdir ~= pos_r then + basepoint_h = boxwidth + end + -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h,shift) + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h) + else + pos_h = ref_h + (cur_h + basepoint_h) + end + pos_v = ref_v - shift + -- synced + if getid(leader) == vlist_code then + vlist_out(leader,getlist(leader)) + else + hlist_out(leader,getlist(leader)) + end + cur_h = cur_h + width + lx + end + popleaderlevel() + cur_h = edge - 10 + else + cur_h = cur_h + gluewidth + end + else + cur_h = cur_h + gluewidth + end + else + if tospace and subtype == spaceskip_code then + -- todo: flush_space + flush_character(false,getfont(current),32,false,true,pos_h,pos_v,pos_r) -- we need tp pass current for scale? + end + cur_h = cur_h + gluewidth + end + end + elseif id == hlist_code or id == vlist_code then + local width, height, depth = getwhd(current) + local list = getlist(current) + if list then + local boxdir = getdirection(current) or lefttoright_code + local shift, orientation = getshift(current) + if not orientation then + local basepoint_h = boxdir ~= pos_r and width or 0 + -- local basepoint_v = shift + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h) + else + pos_h = ref_h + (cur_h + basepoint_h) + end + pos_v = ref_v - shift + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + elseif orientation == 0x1000 then + local orientation, xoffset, yoffset = getorientation(current) + local basepoint_h = boxdir ~= pos_r and width or 0 + -- local basepoint_v = shift + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h + xoffset) + else + pos_h = ref_h + (cur_h + basepoint_h + xoffset) + end + pos_v = ref_v - (shift - yoffset) + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + else + local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current) + local orientation, basepoint_h, basepoint_v = applyanchor(orientation,0,shift,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) + if orientation == 1 then + basepoint_h = basepoint_h + doffset + if boxdir == pos_r then + basepoint_v = basepoint_v - height + end + elseif orientation == 2 then + if boxdir == pos_r then + basepoint_h = basepoint_h + width + end + elseif orientation == 3 then + basepoint_h = basepoint_h + hoffset + if boxdir ~= pos_r then + basepoint_v = basepoint_v - height + end + end + if pos_r == righttoleft_code then + pos_h = ref_h - (cur_h + basepoint_h) + else + pos_h = ref_h + (cur_h + basepoint_h) + end + pos_v = ref_v - (cur_v + basepoint_v) + -- synced + pushorientation(orientation,pos_h,pos_v,pos_r) + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + poporientation(orientation,pos_h,pos_v,pos_r) + end + end + cur_h = cur_h + width + elseif id == kern_code then + -- we can use getkerndimension(current) but then we get rounded values so for + -- now we calculate ourselves + local kern, factor = getkern(current,true) + if kern ~= 0 then + if factor ~= 0 then + cur_h = cur_h + (1.0 + factor/1000000.0) * kern + else + cur_h = cur_h + kern + end + end + elseif id == rule_code then + local width, height, depth = getwhd(current) + if width > 0 then + if height == running then + height = boxheight + end + if depth == running then + depth = boxdepth + end + local total = height + depth + if total > 0 then + local xoffset, yoffset, left, right = getoffsets(current) -- top bottom + if left ~= 0 then + pos_v = pos_v + left + total = total - left + end + if right ~= 0 then + depth = depth - right + total = total - right + end + if pos_r == righttoleft_code then + pos_h = pos_h - width + xoffset = - xoffset + end + pos_v = pos_v - depth + flushrule(current,pos_h + xoffset,pos_v + yoffset,pos_r,width,total,subtype) + end + end + cur_h = cur_h + width + elseif id == math_code then + -- local kern = getkern(current) + -- if kern ~= 0 then + -- cur_h = cur_h + kern + -- else + cur_h = cur_h + effectiveglue(current,this_box) + -- end + elseif id == dir_code then + -- We normally have proper begin-end pairs. A begin without end is (silently) handled + -- and an end without a begin will be (silently) skipped we only need to move forward + -- so we then have a faster calculation. + local dir, cancel = getdirection(current) + if cancel then + local ds = dirstack[current] + if ds then + ref_h = ds.ref_h + ref_v = ds.ref_v + cur_h = ds.cur_h + cur_v = ds.cur_v + else + -- pardir + end + pos_r = dir + else + local width, enddir = dirdimensions(this_box,current) + local new_h = cur_h + width + if dir ~= pos_r then + cur_h = new_h + end + if enddir ~= current then + dirstack[enddir] = { + cur_h = new_h, + cur_v = cur_v, + ref_h = ref_h, + ref_v = ref_v, + } + setdirection(enddir,pos_r) + end + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + -- synced + ref_h = pos_h + ref_v = pos_v + cur_h = 0 + cur_v = 0 + pos_r = dir + goto synced + end + elseif id == whatsit_code then + flushwhatsit[subtype](current,pos_h,pos_v) + elseif id == disc_code then + local replace, tail = getreplace(current) + -- actually, we no longer have these select discs in the packaged list ... it's about + -- time to clean up the disc code a bit further + if replace then -- and subtype ~= select_disc_code then + setlink(tail,getnext(current)) + setlink(current,replace) + setreplace(current) + end + -- elseif id == par_code and start_of_par(current) then + -- local pardir = getdirection(current) or lefttoright_code + -- if pardir == righttoleft_code then + -- end + -- end + else + -- penalty, boundary ... no dimensions + goto synced + end + -- There is no gain in skipping over this when we have zero progression + -- and such. + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + ::synced:: + end + pos_h = ref_h + pos_v = ref_v + pos_r = ref_r + end + + vlist_out = function(this_box,current) + local ref_h = pos_h + local ref_v = pos_v + local ref_r = pos_r + pos_r = getdirection(this_box) + + local boxwidth, + boxheight, + boxdepth = getwhd(this_box) + + local cur_h = 0 + local cur_v = - boxheight + local top_edge = cur_v + + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + -- synced + + -- if not current then + -- current = getlist(this_box) + -- end + + -- while current do + -- local id = getid(current) + for current, id, subtype in nextnode, current do + if id == glue_code then + local glueheight = effectiveglue(current,this_box) + if glueheight ~= 0 then + if subtype >= leaders_code then + local leader = getleader(current) + if leader then + local width, height, depth = getwhd(leader) + local total = height + depth + if getid(leader) == rule_code then + depth = 0 -- hm + total = glueheight -- forgotten ... needs testing + if total > 0 then + if width == running then + width = boxwidth + end + if width > 0 then + if pos_r == righttoleft_code then + cur_h = cur_h - width + end + flushrule(leader,pos_h,pos_v - total,pos_r,width,total,getsubtype(leader)) + end + cur_v = cur_v + total + end + elseif total > 0 and glueheight > 0 then + glueheight = glueheight + 10 + local edge = cur_v + glueheight + local ly = 0 + if subtype == gleaders_code then + save_v = cur_v + cur_v = ref_v - shipbox_v - cur_v + cur_v = total * (cur_v / total) + cur_v = ref_v - shipbox_v - cur_v + if cur_v < save_v then + cur_v = cur_v + total + end + elseif subtype == leaders_code then -- aleader + save_v = cur_v + cur_v = top_edge + total * ((cur_v - top_edge) / total) + if cur_v < save_v then + cur_v = cur_v + total + end + else + lq = glueheight / total + lr = glueheight % total + if subtype == cleaders_code then + cur_v = cur_v + lr / 2 + else + ly = lr / (lq + 1) + cur_v = cur_v + (lr - (lq - 1) * ly) / 2 + end + end + local shift = getshift(leader) + pushleaderlevel() + while cur_v + total <= edge do -- todo: <= edge - total + -- synch_pos_with_cur(ref_h, ref_v, getshift(leader), cur_v + height) + if pos_r == righttoleft_code then + pos_h = ref_h - shift + else + pos_h = ref_h + shift + end + pos_v = ref_v - (cur_v + height) + -- synced + if getid(leader) == vlist_code then + vlist_out(leader,getlist(leader)) + else + hlist_out(leader,getlist(leader)) + end + cur_v = cur_v + total + ly + end + popleaderlevel() + cur_v = edge - 10 + else + cur_v = cur_v + glueheight + end + end + else + cur_v = cur_v + glueheight + end + end + elseif id == hlist_code or id == vlist_code then + local width, height, depth = getwhd(current) + local list = getlist(current) + if list then + local boxdir = getdirection(current) or lefttoright_code + local shift, orientation = getshift(current) + if not orientation then + -- local basepoint_h = shift + -- local basepoint_v = height + if boxdir ~= pos_r then + shift = shift + width + end + if pos_r == righttoleft_code then + pos_h = ref_h - shift + else + pos_h = ref_h + shift + end + pos_v = ref_v - (cur_v + height) + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + elseif orientation == 0x1000 then + local orientation, xoffset, yoffset = getorientation(current) + -- local basepoint_h = shift + -- local basepoint_v = height + if boxdir ~= pos_r then + shift = shift + width + end + if pos_r == righttoleft_code then + pos_h = ref_h - (shift + xoffset) + else + pos_h = ref_h + (shift + xoffset) + end + pos_v = ref_v - (cur_v + height - yoffset) + -- synced + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + else + local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current) + local orientation, basepoint_h, basepoint_v = applyanchor(orientation,shift,height,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset) + if orientation == 1 then + basepoint_h = basepoint_h + width - height + basepoint_v = basepoint_v - height + elseif orientation == 2 then + basepoint_h = basepoint_h + width + basepoint_v = basepoint_v + depth - height + elseif orientation == 3 then -- weird + basepoint_h = basepoint_h + height + end + if pos_r == righttoleft_code then + pos_h = ref_h - basepoint_h + else + pos_h = ref_h + basepoint_h + end + pos_v = ref_v - (cur_v + basepoint_v) + -- synced + pushorientation(orientation,pos_h,pos_v,pos_r) + if id == vlist_code then + vlist_out(current,list) + else + hlist_out(current,list) + end + poporientation(orientation,pos_h,pos_v,pos_r) + end + end + cur_v = cur_v + height + depth + elseif id == kern_code then + cur_v = cur_v + getkern(current) + elseif id == rule_code then + local width, height, depth = getwhd(current) + local total = height + depth + if total > 0 then + if width == running then + width = boxwidth + end + if width > 0 then + local xoffset, yoffset, left, right = getoffsets(current) + if left ~= 0 then + width = width - left + xoffset = left + end + if right ~= 0 then + width = width - right + end + if pos_r == righttoleft_code then + xoffset = - xoffset - width + end + flushrule(current,pos_h + xoffset,pos_v - total - yoffset,pos_r,width,total,subtype) + end + end + cur_v = cur_v + total + elseif id == whatsit_code then + flushwhatsit[subtype](current,pos_h,pos_v) + else + -- penalty + goto synced + end + if pos_r == righttoleft_code then + pos_h = ref_h - cur_h + else + pos_h = ref_h + cur_h + end + pos_v = ref_v - cur_v + ::synced:: + end + pos_h = ref_h + pos_v = ref_v + pos_r = ref_r + end + +end + +function drivers.converters.lmtx(driver,box,smode,objnum,specification) + + if not driver then + report("error in converter, no driver") + return + end + + if box then + box = tonut(box) + else + report("error in converter, no box") + return + end + + local actions = driver.actions + local flushers = driver.flushers + + initialize = actions.initialize + finalize = actions.finalize + + updatefontstate = flushers.updatefontstate + + pushorientation = flushers.pushorientation + poporientation = flushers.poporientation + + pushleaderlevel = flushers.pushleaderlevel + popleaderlevel = flushers.popleaderlevel + + flushcharacter = flushers.character + flushfontchar = flushers.fontchar + flushrule = flushers.rule + flushsimplerule = flushers.simplerule + flushspecialrule = flushers.specialrule + flushliteral = flushers.literal + flushwhatsit = flushers.whatsit + + reset_dir_stack() + reset_state() + + shippingmode = smode + + local details = nil -- must be outside labels + + local width, height, depth = getwhd(box) + + local total = height + depth + + ----- v_offset_par = 0 + ----- h_offset_par = 0 + + local max_v = total -- + v_offset_par + local max_h = width -- + h_offset_par + + if height > maxdimen or depth > maxdimen or width > maxdimen then + goto DONE + end + + if max_v > maxdimen then + goto DONE + elseif max_v > abs_max_v then + abs_max_v = max_v + end + + if max_h > maxdimen then + goto DONE + elseif max_h > abs_max_h then + abs_max_h = max_h + end + + if shippingmode == "page" then + + -- We have zero offsets in ConTeXt. + + local pagewidth, pageheight = getpagedimensions() + + pos_r = lefttoright_code + + if pagewidth > 0 then + page_size_h = pagewidth + else + page_size_h = width + end + + if page_size_h == 0 then + page_size_h = width + end + + if pageheight > 0 then + page_size_v = pageheight + else + page_size_v = total + end + + if page_size_v == 0 then + page_size_v = total + end + + local refpoint_h = 0 + local refpoint_v = page_size_v + + pos_h = refpoint_h + pos_v = refpoint_v - height + + else + + page_size_h = width + page_size_v = total + pos_r = getdirection(box) + pos_v = depth + pos_h = pos_r == righttoleft_code and width or 0 + + end + + shipbox_ref_h = pos_h + shipbox_ref_v = pos_v + + details = { + shippingmode = smode, -- target + boundingbox = { 0, 0, page_size_h, page_size_v }, + objectnumber = smode ~= "page" and objnum or nil, + pagenumber = smode == "page" and objnum or nil, + specification = specification, + } + + initialize(driver,details) + + lastfont = nil -- this forces a sync each page / object + + if getid(box) == vlist_code then + vlist_out(box,getlist(box)) + else + hlist_out(box,getlist(box)) + end + + ::DONE:: + + finalize(driver,details) + + shippingmode = "none" +end + +-- This will move to back-out.lua eventually. + +do + + ----- sortedhash = table.sortedhash + + ----- tonut = nodes.tonut + local properties = nodes.properties.data + local flush = texio.write + local flushline = texio.write_nl + + local periods = utilities.strings.newrepeater(".") + + local function showdetails(n,l) + local p = properties[tonut(n)] + if p then + for k, v in sortedhash(p) do + local t = type(v) + if t == "string" then + if find(v,"[\n\r]") then + v = "\n" .. stripstring(v) .. "\n" + end + elseif t == "number" or t == "boolean" then + v = tostring(v) + elseif t == "table" then + v = sequenced(v) + else + v = "<" .. tostring(v) .. ">" + end + flushline(periods[l+1] .. " " .. k .. " = " .. v) + end + end + end + + local whatsittracers = { + latelua = showdetails, + literal = showdetails, + } + + callback.register("show_whatsit",function(n,l) + local s = nodes.whatsitcodes[n.subtype] + flush(" [" .. s .. "]") + local w = whatsittracers[s] + if w then + w(n,l) + end + end) + +end -- cgit v1.2.3