1if not modules then modules = { } end modules ['anch-snc'] = {
2 version = 1.001,
3 comment = "companion to anch-snc.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local tonumber, next, setmetatable, rawget = tonumber, next, setmetatable, rawget
10local concat, sort, remove, copy = table.concat, table.sort, table.remove, table.copy
11local match, find = string.match, string.find
12local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
13local setmetatableindex = table.setmetatableindex
14local P, Cc = lpeg.P, lpeg.Cc
15
16graphics = graphics or { }
17local synchronizers = { }
18graphics.synchronizers = synchronizers
19
20local jobpositions = job.positions
21
22local p_number = lpegpatterns.cardinal/tonumber
23local p_space = lpegpatterns.whitespace^0
24local p_option = p_number * ((P(",") * p_space * P("reset") * Cc(true)) + Cc(false))
25
26local list = { }
27local kinds = {
28 above = 1,
29 continue = 2,
30 nothing = 3,
31 normal = 4,
32 below = 5,
33}
34
35local lastdone = { }
36
37function synchronizers.collect(category,realpage,region)
38 local all = jobpositions.getsync(category)
39 local m = 0
40 local n = #all
41 list = { }
42 if region and region ~= "" then
43
44 local start = 1
45 local done = false
46 local last, rtop, rbot
47 for i=start,n do
48 local pos = all[i]
49 local p = pos.p
50 local r = pos.r
51 if r == region then
52 if not done then
53 local region = jobpositions.collected[r]
54 list.region = region
55 list.page = region
56 rtop = (region.y or 0) + (region.h or 0)
57 rbot = (region.y or 0) - (region.d or 0)
58 last = { kind = "nothing", top = rtop, bottom = 0, task = 0 }
59 m = m + 1 ; list[m] = last
60 done = true
61 end
62 local top = pos.y + pos.h
63 last.bottom = top
64 local task, reset = lpegmatch(p_option,pos.e)
65 last = { kind = "normal", top = top, bottom = 0, task = task }
66 m = m + 1 ; list[m] = last
67 end
68 end
69 if done then
70 last.bottom = rbot
71 end
72 else
73 local start = all.start or 1
74 local done = false
75 local last, rtop, rbot, ptop, pbot
76 for i=start,n do
77 local pos = all[i]
78 local p = pos.p
79 if p == realpage then
80 if not done then
81 local region = jobpositions.collected[pos.r]
82 local page = jobpositions.collected["page:"..realpage] or region
83 list.region = region
84 list.page = page
85 rtop = (region.y or 0) + (region.h or 0)
86 rbot = (region.y or 0) - (region.d or 0)
87 ptop = (page .y or 0) + (page .h or 0)
88 pbot = (page .y or 0) - (page .d or 0)
89 last = { kind = "above", top = ptop, bottom = rtop, task = 0 }
90 m = m + 1 ; list[m] = last
91 if i > 1 then
92 local task, reset = lpegmatch(p_option,all[i-1].e)
93 last = { kind = "continue", top = rtop, bottom = 0, task = task }
94 m = m + 1 ; list[m] = last
95 else
96 last = { kind = "nothing", top = rtop, bottom = 0, task = 0 }
97 m = m + 1 ; list[m] = last
98 end
99 done = true
100 end
101 local top = pos.y + pos.h
102 last.bottom = top
103 local task, reset = lpegmatch(p_option,pos.e)
104 if reset then
105 local l = list[2]
106 l.kind = "nothing"
107 l.task = 0
108 end
109 last = { kind = "normal", top = top, bottom = 0, task = task }
110 m = m + 1 ; list[m] = last
111 elseif p > realpage then
112 all.start = i
113 break
114 end
115 end
116 if done then
117 last.bottom = rbot
118 last = { kind = "below", top = rbot, bottom = pbot, task = 0 }
119 m = m + 1 ; list[m] = last
120 lastdone[category] = {
121 { kind = "above", top = ptop, bottom = rtop, task = 0 },
122 { kind = "continue", top = rtop, bottom = rbot, task = list[#list-1].task },
123 { kind = "below", top = rbot, bottom = pbot, task = 0 },
124 region = list.region,
125 page = list.page,
126 }
127 else
128 local l = lastdone[category]
129 if l then
130 list = copy(l)
131 m = 3
132 end
133 end
134 end
135 return m
136end
137
138function synchronizers.extend()
139 local n = #list
140 if n > 0 then
141 for i=1,n do
142 local l = list[i]
143 local k = l.kind
144 if k == "nothing" then
145 local ll = list[i+1]
146 if ll and ll.kind == "normal" then
147 ll.top = l.top
148 remove(list,i)
149 n = #list
150 break
151 end
152 end
153 end
154 end
155 return n
156end
157
158function synchronizers.prune()
159 local n = #list
160 if n > 0 then
161 if list[1].kind == "above" then
162 remove(list,1)
163 end
164 if list[1].kind == "nothing" then
165 remove(list,1)
166 end
167 if list[#list].kind == "below" then
168 remove(list,#list)
169 end
170 n = #list
171 end
172 return n
173end
174
175function synchronizers.collapse()
176 local n = #list
177 if n > 0 then
178 local m = 0
179 local p = nil
180 for i=1,n do
181 local l = list[i]
182 local t = l.task
183 if p == t then
184 list[m].bottom = l.bottom
185 else
186 m = m + 1
187 list[m] = l
188 end
189 p = t
190 end
191 for i=n,m+1,-1 do
192 list[i] = nil
193 end
194 n = m
195 end
196 return n
197end
198
199
200
201function synchronizers.getsize () return #list end
202function synchronizers.gettop (n) return list[n].top end
203function synchronizers.getbottom(n) return list[n].bottom end
204function synchronizers.getkind (n) return kinds[list[n].kind] end
205function synchronizers.gettask (n) return list[n].task end
206
207function synchronizers.getx() return list.page.x or 0 end
208function synchronizers.gety() return list.page.y or 0 end
209function synchronizers.getw() return list.page.w or 0 end
210function synchronizers.geth() return list.page.h or 0 end
211function synchronizers.getd() return list.page.d or 0 end
212
213
214
215
216
217
218 |