1if not modules then modules = { } end modules ['typo-lin'] = {
2 version = 1.001,
3 comment = "companion to typo-lin.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
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53local type = type
54
55local trace_anchors = false trackers.register("paragraphs.anchors", function(v) trace_anchors = v end)
56
57local report = logs.reporter("anchors")
58
59local nuts = nodes.nuts
60local nodecodes = nodes.nodecodes
61local gluecodes = nodes.gluecodes
62local listcodes = nodes.listcodes
63
64local hlist_code = nodecodes.hlist
65local glue_code = nodecodes.glue
66local kern_code = nodecodes.kern
67local linelist_code = listcodes.line
68
69local leftskip_code = gluecodes.leftskip
70local rightskip_code = gluecodes.rightskip
71local parfillskip_code = gluecodes.parfillskip
72
73local tonut = nodes.tonut
74local tonode = nodes.tonode
75
76local nexthlist = nuts.traversers.hlist
77local insertbefore = nuts.insertbefore
78local insertafter = nuts.insertafter
79local find_tail = nuts.tail
80local rehpack = nuts.rehpack
81
82
83local getsubtype = nuts.getsubtype
84local getlist = nuts.getlist
85local setlist = nuts.setlist
86local getid = nuts.getid
87local getnext = nuts.getnext
88local getprev = nuts.getprev
89local getboth = nuts.getboth
90local setlink = nuts.setlink
91local setkern = nuts.setkern
92local getkern = nuts.getkern
93local getdirection = nuts.getdirection
94local getshift = nuts.getshift
95local setshift = nuts.setshift
96local getwidth = nuts.getwidth
97local setwidth = nuts.setwidth
98
99local setprop = nuts.setprop
100local getprop = nuts.rawprop
101
102local effectiveglue = nuts.effectiveglue
103
104local nodepool = nuts.pool
105local new_kern = nodepool.kern
106local new_leftskip = nodepool.leftskip
107local new_rightskip = nodepool.rightskip
108local new_hlist = nodepool.hlist
109local new_rule = nodepool.rule
110local new_glue = nodepool.glue
111
112local righttoleft_code = nodes.dirvalues.righttoleft
113
114local texgetcount = tex.getcount
115local texgetglue = tex.getglue
116local setmetatableindex = table.setmetatableindex
117local formatters = string.formatters
118
119local jobpositions = job.positions
120local getposition = jobpositions.get
121local getreserved = jobpositions.getreserved
122
123local paragraphs = { }
124typesetters.paragraphs = paragraphs
125
126local addskips = false
127local noflines = 0
128
129
130
131
132
133
134local function finalize(prop,key)
135 local line = prop.line
136 local hsize = prop.hsize
137 local width = prop.width
138 local shift = getshift(line)
139 local reverse = getdirection(line) == righttoleft_code or false
140 local pack = new_hlist()
141 local head = getlist(line)
142 local delta = 0
143 if reverse then
144 delta = - shift + (hsize - width)
145 else
146 delta = shift
147 end
148 local kern1 = new_kern(delta)
149 local kern2 = new_kern(-delta)
150 head = insertbefore(head,head,kern1)
151 head = insertbefore(head,head,pack)
152 head = insertbefore(head,head,kern2)
153 setlist(line,head)
154 local where = {
155 pack = pack,
156 head = nil,
157 tail = nil,
158 }
159 prop.where = where
160 prop.reverse = reverse
161 prop.shift = shift
162 setmetatableindex(prop,nil)
163 return prop[key]
164end
165
166local function normalize(line,islocal)
167 local oldhead = getlist(line)
168 local head = oldhead
169 local leftskip = nil
170 local rightskip = nil
171 local width = getwidth(line)
172 local hsize = islocal and width or tex.hsize
173 local lskip = 0
174 local rskip = 0
175 local pskip = 0
176 local current = head
177 local id = getid(current)
178 if id == glue_code then
179 local subtype = getsubtype(head)
180 if subtype == leftskip_code then
181 leftskip = head
182 lskip = getwidth(head) or 0
183 end
184 current = getnext(head)
185 id = getid(current)
186 end
187
188
189
190
191 local tail = find_tail(head)
192 local current = tail
193 local id = getid(current)
194 if id == glue_code then
195 if getsubtype(current) == rightskip_code then
196 rightskip = tail
197 rskip = getwidth(current) or 0
198 current = getprev(tail)
199 id = getid(current)
200 end
201 if id == glue_code then
202 if getsubtype(current) == parfillskip_code then
203 pskip = effectiveglue(current,line)
204 end
205 end
206 end
207 if addskips then
208 if rightskip and not leftskip then
209 leftskip = new_leftskip(lskip)
210 head = insertbefore(head,head,leftskip)
211 end
212 if leftskip and not rightskip then
213 rightskip = new_rightskip(0)
214 head, tail = insertafter(head,tail,rightskip)
215 end
216 end
217 if head ~= oldhead then
218 setlist(line,head)
219 end
220 noflines = noflines + 1
221 local prop = {
222 width = width,
223 hsize = hsize,
224 leftskip = lskip,
225 rightskip = rskip,
226 parfillskip = pskip,
227 line = line,
228 number = noflines,
229 }
230 setprop(line,"line",prop)
231 setmetatableindex(prop,finalize)
232 return prop
233end
234
235function paragraphs.checkline(n)
236 return getprop(n,"line") or normalize(n,true)
237end
238
239
240
241function paragraphs.normalize(head,islocal)
242 if texgetcount("pagebodymode") > 0 then
243
244 return head, false
245 end
246
247 local mode = texgetcount("parfillleftmode")
248 if mode > 0 then
249 local l_width, l_stretch, l_shrink = texgetglue("parfillleftskip")
250 if l_width ~= 0 or l_stretch ~= 0 or l_shrink ~= 0 then
251 local last = nil
252 local done = mode == 2
253 for line, subtype in nexthlist, head do
254 if subtype == linelist_code and not getprop(line,"line") then
255 if done then
256 last = line
257 else
258 done = true
259 end
260 end
261 end
262 if last then
263 local head = getlist(last)
264 local current = head
265 if current then
266 if getid(current) == glue_code and getsubtype(current,leftskip_code) then
267 current = getnext(current)
268 end
269 if current then
270 head, current = insertbefore(head,current,new_glue(l_width,l_stretch,l_shrink))
271 if head == current then
272 setlist(last,head)
273 end
274
275 rehpack(last)
276 end
277 end
278 end
279 end
280 end
281
282 for line, subtype in nexthlist, head do
283 if subtype == linelist_code and not getprop(line,"line") then
284 normalize(line)
285 end
286 end
287 return head, true
288end
289
290
291
292
293
294
295
296
297local function addtoline(n,list,option)
298 local line = getprop(n,"line")
299 if not line then
300 line = normalize(n,true)
301 end
302 if line then
303 if trace_anchors and not line.traced then
304 line.traced = true
305 local rule = new_rule(2*65536,2*65536,1*65536)
306 local list = insertbefore(rule,rule,new_kern(-1*65536))
307 addtoline(n,list)
308 local rule = new_rule(2*65536,6*65536,-3*65536)
309 local list = insertbefore(rule,rule,new_kern(-1*65536))
310 addtoline(n,list,"internal")
311 else
312 line.traced = true
313 end
314 local list = tonut(list)
315 local where = line.where
316 local head = where.head
317 local tail = where.tail
318 local blob = new_hlist(list)
319 local delta = 0
320 if option == "internal" then
321 if line.reverse then
322 delta = line.shift - line.leftskip - (line.hsize - line.width)
323 else
324 delta = line.shift + line.leftskip
325 end
326 end
327
328
329
330 local kern = new_kern(delta)
331 if tail then
332 head, tail = insertafter(head,tail,kern)
333 else
334 head, tail = kern, kern
335 setlist(where.pack,head)
336 end
337 head, tail = insertafter(head,tail,blob)
338 local kern = new_kern(-delta)
339 head, tail = insertafter(head,tail,kern)
340
341 where.head = head
342 where.tail = tail
343 return line, blob
344 else
345
346 end
347end
348
349local function addanchortoline(n,anchor)
350 local line = type(n) ~= "table" and getprop(n,"line") or n
351 if not line then
352 line = normalize(n,true)
353 end
354 if line then
355 local anchor = tonut(anchor)
356 local where = line.where
357 if trace_anchors then
358 anchor = new_hlist(setlink(
359 anchor,
360 new_kern(-65536/4),
361 new_rule(65536/2,4*65536,4*65536),
362 new_kern(-65536/4-4*65536),
363 new_rule(8*65536,65536/4,65536/4)
364 ))
365 setwidth(anchor,0)
366 end
367 if where.tail then
368 local head = where.head
369 insertbefore(head,head,anchor)
370 else
371 where.tail = anchor
372 end
373 setlist(where.pack,anchor)
374 where.head = anchor
375 return line
376 end
377end
378
379paragraphs.addtoline = addtoline
380paragraphs.addanchortoline = addanchortoline
381
382function paragraphs.moveinline(n,blob,dx,dy)
383 if not blob then
384 return
385 end
386 if not dx then
387 dx = 0
388 end
389 if not dy then
390 dy = 0
391 end
392 if dx ~= 0 or dy ~= 0 then
393 local line = type(n) ~= "table" and getprop(n,"line") or n
394 if line then
395 if dx ~= 0 then
396 local prev, next = getboth(blob)
397 if prev and getid(prev) == kern_code then
398 setkern(prev,getkern(prev) + dx)
399 end
400 if next and getid(next) == kern_code then
401 setkern(next,getkern(next) - dx)
402 end
403 end
404 if dy ~= 0 then
405 if getid(blob) == hlist_code then
406 setshift(blob,getshift(blob) + dy)
407 end
408 end
409 else
410
411 end
412 end
413end
414
415local latelua = nodepool.latelua
416local setposition = jobpositions.setspec
417
418local function setanchor(h_anchor)
419 return latelua {
420 action = setposition,
421 name = "md:h",
422 index = h_anchor,
423 value = { x = true, c = true },
424 }
425end
426
427function paragraphs.calculatedelta(n,width,delta,atleft,islocal,followshape,area)
428 local line = type(n) ~= "table" and getprop(n,"line") or n
429 if not line then
430 line = normalize(n,true)
431 end
432 local hmove = 0
433 if line then
434 local reverse = line.reverse
435
436 if atleft then
437 if reverse then
438
439 else
440 delta = - delta - width
441 end
442 else
443 if reverse then
444 delta = - delta - width - line.hsize
445 else
446 delta = delta + line.hsize
447 end
448 end
449 if islocal then
450
451 if atleft then
452 if reverse then
453 delta = delta - line.leftskip
454 else
455 delta = delta + line.leftskip
456 end
457 else
458 if reverse then
459 delta = delta + line.rightskip
460 else
461 delta = delta - line.rightskip
462 end
463 end
464 if followshape then
465
466 if atleft then
467 if reverse then
468 delta = delta + line.shift - line.hsize + line.width
469 else
470 delta = delta + line.shift
471 end
472 else
473 if reverse then
474 delta = delta + line.shift + line.parfillskip
475 else
476 delta = delta + line.shift - line.hsize + line.width - line.parfillskip
477 end
478 end
479 end
480 end
481 if area then
482 local number = line.number
483 if not line.hanchor then
484 addanchortoline(line,setanchor(number))
485 line.hanchor = true
486 end
487 local blob = getposition("md:h",number)
488 if blob then
489 local reference = getreserved(area,blob.c)
490 if reference then
491 hmove = (reference.x or 0) - (blob.x or 0)
492 if atleft then
493 if reverse then
494 hmove = hmove + (reference.w or 0)
495 else
496
497 end
498 else
499 if reverse then
500 hmove = hmove + line.hsize
501 else
502 hmove = hmove + (reference.w or 0) - line.hsize
503 end
504 end
505 end
506 end
507 end
508 end
509 return delta, hmove
510end
511 |