summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/anch-snc.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/anch-snc.lua')
-rw-r--r--tex/context/base/mkiv/anch-snc.lua271
1 files changed, 271 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/anch-snc.lua b/tex/context/base/mkiv/anch-snc.lua
new file mode 100644
index 000000000..8006f3bd6
--- /dev/null
+++ b/tex/context/base/mkiv/anch-snc.lua
@@ -0,0 +1,271 @@
+if not modules then modules = { } end modules ['anch-snc'] = {
+ version = 1.001,
+ comment = "companion to anch-snc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+function mp.xxOverlayRegion()
+ local r = tokens.getters.macro("m_overlay_region")
+ mp.quoted('"'.. r .. '"')
+-- mp.print('"'.. r .. '"')
+end
+
+-- use factors as in mlib-int.lua
+
+local tonumber, next, setmetatable = tonumber, next, setmetatable
+local concat, sort, remove, copy = table.concat, table.sort, table.remove, table.copy
+local match, find = string.match, string.find
+local lpegmatch = lpeg.match
+
+local setmetatableindex = table.setmetatableindex
+
+local factor = number.dimenfactors.bp
+local mpprint = mp.print
+local mpnumeric = mp.numeric
+local mppoints = mp.points
+local texgetdimen = tex.getdimen
+
+local p_number = lpeg.patterns.cardinal/tonumber
+local p_space = lpeg.patterns.whitespace^0
+local p_tag = lpeg.P("syncpos:") * p_number * lpeg.P(":") * p_number
+local p_option = p_number -- for now
+ * ((lpeg.P(",") * p_space * lpeg.P("reset") * lpeg.Cc(true)) + lpeg.Cc(false))
+
+local list = { }
+local colors = setmetatableindex("table")
+
+local kinds = {
+ above = 1,
+ continue = 2,
+ nothing = 3,
+ normal = 4,
+ below = 5,
+}
+
+local allentries = setmetatableindex(function(t,category)
+ setmetatable(t,nil)
+ for tag, pos in next, job.positions.collected do
+ local c, n = lpegmatch(p_tag,tag)
+ if c then
+ local tc = t[c]
+ if tc then
+ tc[n] = pos
+ else
+ t[c] = { [n] = pos }
+ end
+ end
+ end
+ for k, list in next, t do
+ sort(list,function(a,b)
+ local ap = a.p
+ local bp = b.p
+ if ap == bp then
+ return b.y < a.y
+ else
+ return ap < bp
+ end
+ end)
+ list.start = 1
+ end
+ setmetatableindex(t,"table")
+ return t[category]
+end)
+
+local lastdone = { }
+
+function mp.sync_collect(category,realpage,useregion)
+ local all = allentries[category]
+ local m = 0
+ local n = #all
+ list = { }
+ if useregion then
+ -- successive can be optimized when we sort by region
+ local start = 1
+ local done = false
+ local last, rtop, rbot
+ for i=start,n do
+ local pos = all[i]
+ local p = pos.p
+ local r = pos.r
+ if r == useregion then
+ if not done then
+ local region = job.positions.collected[r]
+ list.region = region
+ list.page = region
+ rtop = (region.y or 0) + (region.h or 0)
+ rbot = (region.y or 0) - (region.d or 0)
+ last = { kind = "nothing", top = rtop, bottom = 0, task = 0 }
+ m = m + 1 ; list[m] = last
+ done = true
+ end
+ local top = pos.y + pos.h
+ last.bottom = top
+ local task, reset = lpegmatch(p_option,pos.e)
+ last = { kind = "normal", top = top, bottom = 0, task = task }
+ m = m + 1 ; list[m] = last
+ end
+ end
+ if done then
+ last.bottom = rbot
+ end
+ else
+ local start = all.start or 1
+ local done = false
+ local last, rtop, rbot, ptop, pbot
+ for i=start,n do
+ local pos = all[i]
+ local p = pos.p
+ if p == realpage then
+ if not done then
+ local region = job.positions.collected[pos.r]
+ local page = job.positions.collected["page:"..realpage] or region
+ list.region = region
+ list.page = page
+ rtop = (region.y or 0) + (region.h or 0)
+ rbot = (region.y or 0) - (region.d or 0)
+ ptop = (page .y or 0) + (page .h or 0)
+ pbot = (page .y or 0) - (page .d or 0)
+ last = { kind = "above", top = ptop, bottom = rtop, task = 0 }
+ m = m + 1 ; list[m] = last
+ if i > 1 then
+ local task, reset = lpegmatch(p_option,all[i-1].e)
+ last = { kind = "continue", top = rtop, bottom = 0, task = task }
+ m = m + 1 ; list[m] = last
+ else
+ last = { kind = "nothing", top = rtop, bottom = 0, task = 0 }
+ m = m + 1 ; list[m] = last
+ end
+ done = true
+ end
+ local top = pos.y + pos.h
+ last.bottom = top
+ local task, reset = lpegmatch(p_option,pos.e)
+ if reset then
+ local l = list[2]
+ l.kind = "nothing"
+ l.task = 0
+ end
+ last = { kind = "normal", top = top, bottom = 0, task = task }
+ m = m + 1 ; list[m] = last
+ elseif p > realpage then
+ all.start = i -- tricky, only for page
+ break
+ end
+ end
+ if done then
+ last.bottom = rbot
+ last = { kind = "below", top = rbot, bottom = pbot, task = 0 }
+ m = m + 1 ; list[m] = last
+ lastdone[category] = {
+ { kind = "above", top = ptop, bottom = rtop, task = 0 },
+ { kind = "continue", top = rtop, bottom = rbot, task = list[#list-1].task }, -- lasttask
+ { kind = "below", top = rbot, bottom = pbot, task = 0 },
+ region = list.region,
+ page = list.page,
+ }
+ else
+ local l = lastdone[category]
+ if l then
+ list = copy(l) -- inefficient, mayb emetatable for region/page
+ m = 3
+ end
+ end
+ end
+ mpnumeric(m)
+end
+
+function mp.sync_extend()
+ local n = #list
+ if n > 0 then
+ for i=1,n do
+ local l = list[i]
+ local k = l.kind
+ if k == "nothing" then
+ local ll = list[i+1]
+ if ll and ll.kind == "normal" then
+ ll.top = l.top
+ remove(list,i)
+ n = #list
+ break
+ end
+ end
+ end
+ end
+ mpnumeric(n)
+end
+
+function mp.sync_prune()
+ local n = #list
+ if n > 0 then
+ if list[1].kind == "above" then
+ remove(list,1)
+ end
+ if list[1].kind == "nothing" then
+ remove(list,1)
+ end
+ if list[#list].kind == "below" then
+ remove(list,#list)
+ end
+ n = #list
+ end
+ mpnumeric(n)
+end
+
+function mp.sync_collapse()
+ local n = #list
+ if n > 0 then
+ local m = 0
+ local p = nil
+ for i=1,n do
+ local l = list[i]
+ local t = l.task
+ if p == t then
+ list[m].bottom = l.bottom
+ else
+ m = m + 1
+ list[m] = l
+ end
+ p = t
+ end
+ for i=n,m+1,-1 do
+ list[i] = nil
+ end
+ n = m
+ end
+ mpnumeric(n)
+end
+
+function mp.sync_set_color(category,n,v)
+ colors[category][n] = v
+end
+
+function mp.sync_get_color(category,n)
+ mpprint(colors[category][n])
+end
+
+-- function mp.sync_get_size () mpnumeric(#list) end
+-- function mp.sync_get_top (n) mppoints (list[n].top) end
+-- function mp.sync_get_bottom(n) mppoints (list[n].bottom) end
+-- function mp.sync_get_kind (n) mpnumeric(kinds[list[n].kind]) end
+-- function mp.sync_get_task (n) mpnumeric(list[n].task) end
+
+-- function mp.sync_get_x() mppoints(list.page.x or 0) end
+-- function mp.sync_get_y() mppoints(list.page.y or 0) end
+-- function mp.sync_get_w() mppoints(list.page.w or 0) end
+-- function mp.sync_get_h() mppoints(list.page.h or 0) end
+-- function mp.sync_get_d() mppoints(list.page.d or 0) end
+
+function mp.sync_get_size () mpnumeric(#list) end
+function mp.sync_get_top (n) mpnumeric(list[n].top * factor) end
+function mp.sync_get_bottom(n) mpnumeric(list[n].bottom * factor) end
+function mp.sync_get_kind (n) mpnumeric(kinds[list[n].kind]) end
+function mp.sync_get_task (n) mpnumeric(list[n].task) end
+
+function mp.sync_get_x() mpnumeric((list.page.x or 0)*factor) end
+function mp.sync_get_y() mpnumeric((list.page.y or 0)*factor) end
+function mp.sync_get_w() mpnumeric((list.page.w or 0)*factor) end
+function mp.sync_get_h() mpnumeric((list.page.h or 0)*factor) end
+function mp.sync_get_d() mpnumeric((list.page.d or 0)*factor) end