1if not modules then modules = { } end modules [ ' anch-pgr ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to anch-pgr.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
19local tonumber = tonumber
20local sort , concat = table . sort , table . concat
21local splitter = lpeg . splitat ( " : " )
22local lpegmatch = lpeg . match
23
24local jobpositions = job . positions
25local formatters = string . formatters
26local setmetatableindex = table . setmetatableindex
27
28local enableaction = nodes . tasks . enableaction
29
30local commands = commands
31local context = context
32
33local implement = interfaces . implement
34
35local report_graphics = logs . reporter ( " backgrounds " )
36local report_shapes = logs . reporter ( " backgrounds " , " shapes " )
37local report_free = logs . reporter ( " backgrounds " , " free " )
38
39local trace_shapes = false trackers . register ( " backgrounds.shapes " , function ( v ) trace_shapes = v end )
40local trace_ranges = false trackers . register ( " backgrounds.shapes.ranges " , function ( v ) trace_ranges = v end )
41local trace_free = false trackers . register ( " backgrounds.shapes.free " , function ( v ) trace_free = v end )
42
43local f_b_tag = formatters [ " b:%s " ]
44local f_e_tag = formatters [ " e:%s " ]
45local f_p_tag = formatters [ " p:%s " ]
46
47local f_tag_two = formatters [ " %s:%s " ]
48
49local f_point = formatters [ " %p " ]
50local f_pair = formatters [ " (%p,%p) " ]
51local f_path = formatters [ " %--t--cycle " ]
52local f_pair_i = formatters [ " (%r,%r) " ]
53
54graphics = graphics or { }
55local backgrounds = { }
56graphics . backgrounds = backgrounds
57
58
59
60local texsetattribute = tex . setattribute
61
62local a_textbackground = attributes . private ( " textbackground " )
63
64local nuts = nodes . nuts
65
66local new_latelua = nuts . pool . latelua
67local new_rule = nuts . pool . rule
68local new_kern = nuts . pool . kern
69local new_hlist = nuts . pool . hlist
70
71local getbox = nuts . getbox
72local getid = nuts . getid
73
74local setlink = nuts . setlink
75local getheight = nuts . getheight
76local getdepth = nuts . getdepth
77
78local nodecodes = nodes . nodecodes
79local localpar_code = nodecodes . localpar
80
81local start_of_par = nuts . start_of_par
82local insert_before = nuts . insert_before
83local insert_after = nuts . insert_after
84
85local processranges = nuts . processranges
86
87local unsetvalue = attributes . unsetvalue
88
89local jobpositions = job . positions
90local getpos = jobpositions . getpos
91local getfree = jobpositions . getfree
92
93local data = { }
94local realpage = 1
95local recycle = 1000
96local enabled = false
97
98
99
100
101local function check ( specification )
102 local a = specification . attribute
103 local index = specification . index
104 local depth = specification . depth
105 local d = specification . data
106 local where = specification . where
107 local ht = specification . ht
108 local dp = specification . dp
109
110 local w = d . shapes [ realpage ]
111 local x , y = getpos ( )
112 if trace_ranges then
113 report_shapes ( " attribute %i, index %i, depth %i, location %s, position (%p,%p) " ,
114 a , index , depth , where , x , y )
115 end
116 local n = # w
117 if d . index ~ = index then
118 n = n + 1
119 d . index = index
120 d . depth = depth
121
122 w [ n ] = { y , ht , dp , x , x }
123 else
124 local wn = w [ n ]
125 local wh = wn [ 2 ]
126 local wd = wn [ 3 ]
127 if depth < d . depth then
128 local wy = wn [ 1 ]
129 wn [ 1 ] = y
130 d . depth = depth
131 local dy = wy - y
132 wh = wh - dy
133 wd = wd - dy
134 end
135 if where = = " r " then
136 if x > wn [ 5 ] then
137 wn [ 5 ] = x
138 end
139 else
140 if x < wn [ 4 ] then
141 wn [ 4 ] = x
142 end
143 end
144 if ht > wh then
145 wn [ 2 ] = ht
146 end
147 if dp > wd then
148 wn [ 3 ] = dp
149 end
150 end
151
152end
153
154local index = 0
155
156local function flush ( head , f , l , a , parent , depth )
157 local d = data [ a ]
158 if d then
159 local ix = index
160 local ht = getheight ( parent )
161 local dp = getdepth ( parent )
162 local ln = new_latelua { action = check , attribute = a , index = ix , depth = depth , data = d , where = " l " , ht = ht , dp = dp }
163 local rn = new_latelua { action = check , attribute = a , index = ix , depth = depth , data = d , where = " r " , ht = ht , dp = dp }
164 if trace_ranges then
165 ln = new_hlist ( setlink ( new_rule ( 65536 , 65536 * 4 , 0 ) , new_kern ( -65536 ) , ln ) )
166 rn = new_hlist ( setlink ( new_rule ( 65536 , 0 , 65536 * 4 ) , new_kern ( -65536 ) , rn ) )
167 end
168 if getid ( f ) = = localpar_code and start_of_par ( f ) then
169 insert_after ( head , f , ln )
170 else
171 head , f = insert_before ( head , f , ln )
172 end
173 insert_after ( head , l , rn )
174 end
175 return head , true
176end
177
178local function registerbackground ( name )
179 local n = # data + 1
180 if n > recycle then
181
182
183
184 n = 1
185 end
186 local b = jobpositions . tobesaved [ " b: " . . name ]
187 if b then
188 local s = setmetatableindex ( " table " )
189 b . s = s
190 data [ n ] = {
191 bpos = b ,
192 name = name ,
193 n = n ,
194 shapes = s ,
195 count = 0 ,
196 sindex = 0 ,
197 }
198 texsetattribute ( a_textbackground , n )
199 if not enabled then
200 enableaction ( " contributers " , " nodes.handlers.textbackgrounds " )
201 enabled = true
202 end
203 else
204 texsetattribute ( a_textbackground , unsetvalue )
205 end
206end
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223nodes . handlers . textbackgrounds = function ( head , where , parent )
224
225 index = index + 1
226 return processranges ( a_textbackground , flush , head , parent )
227end
228
229interfaces . implement {
230 name = " registerbackground " ,
231 actions = registerbackground ,
232 arguments = " string " ,
233}
234
235
236
237
238
239
240local function topairs ( t , n )
241 local r = { }
242 for i = 1 , n do
243 local ti = t [ i ]
244 r [ i ] = f_pair_i ( ti [ 1 ] / 65556 , ti [ 2 ] / 65536 )
245 end
246 return concat ( r , " " )
247end
248
249local eps = 65536 / 4
250local pps = eps
251local nps = - pps
252
253local function unitvector ( x , y )
254 if x < pps and x > nps then
255 x = 0
256 elseif x < 0 then
257 x = -1
258 else
259 x = 1
260 end
261 if y < pps and y > nps then
262 y = 0
263 elseif y < 0 then
264 y = -1
265 else
266 y = 1
267 end
268 return x , y
269end
270
271local function finish ( t )
272 local tm = # t
273 if tm < 2 then
274 return
275 end
276 if trace_ranges then
277 report_shapes ( " initial list: %s " , topairs ( t , tm ) )
278 end
279
280 local n = 1
281 local tn = tm
282 local tf = t [ 1 ]
283 local tx = tf [ 1 ]
284 local ty = tf [ 2 ]
285 for i = 2 , # t do
286 local ti = t [ i ]
287 local ix = ti [ 1 ]
288 local iy = ti [ 2 ]
289 local dx = ix - tx
290 local dy = iy - ty
291 if dx > eps or dx < - eps or dy > eps or dy < - eps then
292 n = n + 1
293 t [ n ] = ti
294 tx = ix
295 ty = iy
296 end
297 end
298 if trace_shapes then
299 report_shapes ( " removing similar points: %s " , topairs ( t , n ) )
300 end
301 if n > 2 then
302
303 repeat
304 tn = n
305 n = 0
306 local tm = t [ tn ]
307 local tmx = tm [ 1 ]
308 local tmy = tm [ 2 ]
309 local tp = t [ 1 ]
310 local tpx = tp [ 1 ]
311 local tpy = tp [ 2 ]
312 for i = 1 , tn do
313 local ti = tp
314 local tix = tpx
315 local tiy = tpy
316 if i = = tn then
317 tp = t [ 1 ]
318 else
319 tp = t [ i + 1 ]
320 end
321 tpx = tp [ 1 ]
322 tpy = tp [ 2 ]
323
324 local vx1 , vx2 = unitvector ( tix - tmx , tpx - tix )
325 if vx1 ~ = vx2 then
326 n = n + 1
327 t [ n ] = ti
328 else
329 local vy1 , vy2 = unitvector ( tiy - tmy , tpy - tiy )
330 if vy1 ~ = vy2 then
331 n = n + 1
332 t [ n ] = ti
333 end
334 end
335
336 tmx = tix
337 tmy = tiy
338 end
339 until n = = tn or n < = 2
340 if trace_shapes then
341 report_shapes ( " removing redundant points: %s " , topairs ( t , n ) )
342 end
343
344 if n > 2 then
345 repeat
346 tn = n
347 n = 0
348 local tm = t [ tn ]
349 local tmx = tm [ 1 ]
350 local tmy = tm [ 2 ]
351 local tp = t [ 1 ]
352 local tpx = tp [ 1 ]
353 local tpy = tp [ 2 ]
354 for i = 1 , tn do
355 local ti = tp
356 local tix = tpx
357 local tiy = tpy
358 if i = = tn then
359 tp = t [ 1 ]
360 else
361 tp = t [ i + 1 ]
362 end
363 tpx = tp [ 1 ]
364 tpy = tp [ 2 ]
365
366 local vx1 , vx2 = unitvector ( tix - tmx , tpx - tix )
367 if vx1 ~ = - vx2 then
368 n = n + 1
369 t [ n ] = ti
370 else
371 local vy1 , vy2 = unitvector ( tiy - tmy , tpy - tiy )
372 if vy1 ~ = - vy2 then
373 n = n + 1
374 t [ n ] = ti
375 end
376 end
377
378 tmx = tix
379 tmy = tiy
380 end
381 until n = = tn or n < = 2
382 if trace_shapes then
383 report_shapes ( " removing spikes: %s " , topairs ( t , n ) )
384 end
385 end
386 end
387
388 if tm > n then
389 for i = tm , n + 1 , -1 do
390 t [ i ] = nil
391 end
392 end
393 if n > 1 then
394 local tf = t [ 1 ]
395 local tl = t [ n ]
396 local dx = tf [ 1 ] - tl [ 1 ]
397 local dy = tf [ 2 ] - tl [ 2 ]
398 if dx > eps or dx < - eps or dy > eps or dy < - eps then
399
400 else
401
402 t [ n ] = nil
403 n = n -1
404 end
405 if trace_shapes then
406 report_shapes ( " removing cyclic endpoints: %s " , topairs ( t , n ) )
407 end
408 end
409 return t
410end
411
412local eps = 65536
413
414
415
416
417local function shape ( kind , b , p , realpage , xmin , xmax , ymin , ymax , fh , ld )
418 local s = b . s
419 if not s then
420 if trace_shapes then
421 report_shapes ( " calculating %s area, no shape " , kind )
422 end
423 return
424 end
425 s = s [ realpage ]
426 if not s then
427 if trace_shapes then
428 report_shapes ( " calculating %s area, no shape for page %s " , kind , realpage )
429 end
430 return
431 end
432 local ns = # s
433 if ns = = 0 then
434 if trace_shapes then
435 report_shapes ( " calculating %s area, empty shape for page %s " , kind , realpage )
436 end
437 return
438 end
439
440 if trace_shapes then
441 report_shapes ( " calculating %s area, using shape for page %s " , kind , realpage )
442 end
443
444
445 local ph = p and p . h or 0
446 local pd = p and p . d or 0
447
448 xmax = xmax + eps
449 xmin = xmin - eps
450 ymax = ymax + eps
451 ymin = ymin - eps
452 local ls = { }
453 local rs = { }
454 local pl = nil
455 local pr = nil
456 local n = 0
457 local xl = nil
458 local xr = nil
459 local mh = ph
460 local md = pd
461 for i = 1 , ns do
462 local si = s [ i ]
463 local y = si [ 1 ]
464 local ll = si [ 4 ]
465 if ll then
466 xl = ll
467 local rr = si [ 5 ]
468 if rr then
469 xr = rr
470 end
471 end
472 if trace_ranges then
473 report_shapes ( " original : [%02i] xl=%p xr=%p y=%p " , i , xl , xr , y )
474 end
475 if xl ~ = xr then
476 local xm = xl + ( xr - xl ) / 2
477 if xm > = xmin and xm < = xmax and y > = ymin and y < = ymax then
478 local ht = si [ 2 ]
479 if ht then
480 ph = ht
481 local dp = si [ 3 ]
482 if dp then
483 pd = dp
484 end
485 end
486 local h = y + ( ph < mh and mh or ph )
487 local d = y - ( pd < md and md or pd )
488 if pl then
489 n = n + 1
490 ls [ n ] = { pl , h }
491 rs [ n ] = { pr , h }
492 if trace_ranges then
493 report_shapes ( " paragraph : [%02i] xl=%p xr=%p y=%p " , i , pl , pr , h )
494 end
495 end
496 n = n + 1
497 ls [ n ] = { xl , h }
498 rs [ n ] = { xr , h }
499 if trace_ranges then
500 report_shapes ( " height : [%02i] xl=%p xr=%p y=%p " , i , xl , xr , h )
501 end
502 n = n + 1
503 ls [ n ] = { xl , d }
504 rs [ n ] = { xr , d }
505 if trace_ranges then
506 report_shapes ( " depth : [%02i] xl=%p xr=%p y=%p " , i , xl , xr , d )
507 end
508 end
509 pl , pr = xl , xr
510 else
511 if trace_ranges then
512 report_shapes ( " ignored : [%02i] xl=%p xr=%p y=%p " , i , xl , xr , y )
513 end
514 end
515 end
516
517 if true and n > 0 then
518
519
520 if fh then
521 local lsf = ls [ 1 ]
522 local rsf = rs [ 1 ]
523 if lsf [ 2 ] < fh then
524 lsf [ 2 ] = fh
525 end
526 if rsf [ 2 ] < fh then
527 rsf [ 2 ] = fh
528 end
529 end
530 if fd then
531 local lsl = ls [ n ]
532 local rsl = rs [ n ]
533 if lsl [ 2 ] > fd then
534 lsl [ 2 ] = fd
535 end
536 if rsl [ 2 ] > fd then
537 rsl [ 2 ] = fd
538 end
539 end
540 end
541
542 for i = n , 1 , -1 do
543 n = n + 1 rs [ n ] = ls [ i ]
544 end
545 return rs
546end
547
548local function singlepart ( b , e , p , realpage , r , left , right )
549 local bx = b . x
550 local by = b . y
551 local ex = e . x
552 local ey = e . y
553 local rx = r . x
554 local ry = r . y
555 local bh = by + b . h
556 local bd = by - b . d
557 local eh = ey + e . h
558 local ed = ey - e . d
559 local rh = ry + r . h
560 local rd = ry - r . d
561 local rw = rx + r . w
562 if left then
563 rx = rx + left
564 rw = rw - right
565 end
566 if ex = = rx then
567
568
569
570 ex = rw
571 end
572 local area
573 if by = = ey then
574 if trace_shapes then
575 report_shapes ( " calculating single area, partial line " )
576 end
577 area = {
578 { bx , bh } ,
579 { ex , eh } ,
580 { ex , ed } ,
581 { bx , bd } ,
582 }
583 elseif b . k = = 2 then
584 area = {
585 { rx , bh } ,
586 { rw , bh } ,
587 { rw , ed } ,
588 { rx , ed } ,
589 }
590 else
591 area = shape ( " single " , b , p , realpage , rx , rw , rd , rh , bh , ed )
592 end
593 if not area then
594 area = {
595 { bx , bh } ,
596 { rw , bh } ,
597 { rw , eh } ,
598 { ex , eh } ,
599 { ex , ed } ,
600 { rx , ed } ,
601 { rx , bd } ,
602 { bx , bd } ,
603 }
604 end
605 return {
606 location = " single " ,
607 region = r ,
608 area = finish ( area ) ,
609 }
610end
611
612local function firstpart ( b , e , p , realpage , r , left , right )
613 local bx = b . x
614 local by = b . y
615 local rx = r . x
616 local ry = r . y
617 local bh = by + b . h
618 local bd = by - b . d
619 local rh = ry + r . h
620 local rd = ry - r . d
621 local rw = rx + r . w
622 if left then
623 rx = rx + left
624 rw = rw - right
625 end
626 local area = shape ( " first " , b , p , realpage , rx , rw , rd , rh , bh , false )
627 if not area then
628 if b . k = = 2 then
629 area = {
630 { rx , bh } ,
631 { rw , bh } ,
632 { rw , rd } ,
633 { rx , rd } ,
634 }
635 else
636 area = {
637 { bx , bh } ,
638 { rw , bh } ,
639 { rw , rd } ,
640 { rx , rd } ,
641 { rx , bd } ,
642 { bx , bd } ,
643 }
644 end
645 end
646 return {
647 location = " first " ,
648 region = r ,
649 area = finish ( area ) ,
650 }
651end
652
653local function middlepart ( b , e , p , realpage , r , left , right )
654 local rx = r . x
655 local ry = r . y
656 local rh = ry + r . h
657 local rd = ry - r . d
658 local rw = rx + r . w
659 if left then
660 rx = rx + left
661 rw = rw - right
662 end
663 local area = shape ( " middle " , b , p , realpage , rx , rw , rd , rh , false , false )
664 if not area then
665 area = {
666 { rw , rh } ,
667 { rw , rd } ,
668 { rx , rd } ,
669 { rx , rh } ,
670 }
671 end
672 return {
673 location = " middle " ,
674 region = r ,
675 area = finish ( area ) ,
676 }
677end
678
679local function lastpart ( b , e , p , realpage , r , left , right )
680 local ex = e . x
681 local ey = e . y
682 local rx = r . x
683 local ry = r . y
684 local eh = ey + e . h
685 local ed = ey - e . d
686 local rh = ry + r . h
687 local rd = ry - r . d
688 local rw = rx + r . w
689 if left then
690 rx = rx + left
691 rw = rw - right
692 end
693 local area = shape ( " last " , b , p , realpage , rx , rw , rd , rh , false , ed )
694 if not area then
695 if b . k = = 2 then
696 area = {
697 { rw , rh } ,
698 { rw , ed } ,
699 { rx , ed } ,
700 { rx , rh } ,
701 }
702 else
703 area = {
704 { rw , rh } ,
705 { rw , eh } ,
706 { ex , eh } ,
707 { ex , ed } ,
708 { rx , ed } ,
709 { rx , rh } ,
710 }
711 end
712 end
713 return {
714 location = " last " ,
715 region = r ,
716 area = finish ( area ) ,
717 }
718end
719
720local function calculatemultipar ( tag )
721 local collected = jobpositions . collected
722 local b = collected [ f_b_tag ( tag ) ]
723 local e = collected [ f_e_tag ( tag ) ]
724 if not b or not e then
725 report_shapes ( " invalid tag %a " , tag )
726 return { }
727 end
728 local br = b . r
729 local er = e . r
730 if not br or not er then
731 report_shapes ( " invalid region for %a " , tag )
732 return { }
733 end
734 local btag , bindex = lpegmatch ( splitter , br )
735 local etag , eindex = lpegmatch ( splitter , er )
736 if not bindex or not eindex or btag ~ = etag then
737 report_shapes ( " invalid indices for %a " , tag )
738 return { }
739 end
740 local bindex = tonumber ( bindex )
741 local eindex = tonumber ( eindex )
742
743
744
745
746
747 local left = 0
748 local right = 0
749 local bc = b . c
750 local rc = bc and collected [ bc ]
751 if rc then
752 local tb = collected [ rc . r ]
753 if tb then
754 left = - ( tb . x - rc . x )
755 right = ( tb . w - rc . w - left )
756 end
757 end
758
759
760 local bn = b . n
761 local p = bn and collected [ f_p_tag ( bn ) ]
762 if p then
763 left = left + ( p . ls or 0 )
764 right = right + ( p . rs or 0 )
765 end
766
767 local bp = b . p
768 if trace_shapes then
769 report_shapes ( " tag %a, left %p, right %p, par %s, page %s, column %s " ,
770 tag , left , right , bn or " - " , bp or " - " , bc or " - " )
771 end
772
773 if bindex = = eindex then
774 return {
775 list = { [ bp ] = { singlepart ( b , e , p , bp , collected [ br ] , left , right ) } } ,
776 bpos = b ,
777 epos = e ,
778 }
779 else
780 local list = {
781 [ bp ] = { firstpart ( b , e , p , bp , collected [ br ] , left , right ) } ,
782 }
783 for i = bindex + 1 , eindex -1 do
784 br = f_tag_two ( btag , i )
785 local r = collected [ br ]
786 if not r then
787 report_graphics ( " invalid middle for %a " , br )
788 else
789 local rp = r . p
790 local pp = list [ rp ]
791 local mp = middlepart ( b , e , p , rp , r , left , right )
792 if pp then
793 pp [ # pp + 1 ] = mp
794 else
795 list [ rp ] = { mp }
796 end
797 end
798 end
799 local ep = e . p
800 local pp = list [ ep ]
801 local lp = lastpart ( b , e , p , ep , collected [ er ] , left , right )
802 if pp then
803 pp [ # pp + 1 ] = lp
804 else
805 list [ ep ] = { lp }
806 end
807 return {
808 list = list ,
809 bpos = b ,
810 epos = e ,
811 }
812 end
813end
814
815local pbg = { }
816
817local multilocs = {
818 single = 1 ,
819 first = 1 ,
820 middle = 2 ,
821 last = 3 ,
822}
823
824
825
826local f_template_a = formatters [ [[
827path multiregs[], multipars[], multibox ;
828string multikind[] ;
829numeric multilocs[], nofmultipars ;
830nofmultipars := %s ;
831multibox := unitsquare xyscaled (%p,%p) ;
832numeric par_strut_height, par_strut_depth, par_line_height ;
833par_strut_height := %p ;
834par_strut_depth := %p ;
835par_line_height := %p ;
836 ]] ]
837
838local f_template_b = formatters [ [[
839multilocs[%s] := %s ;
840multikind[%s] := "%s" ;
841multipars[%s] := (%--t--cycle) shifted - (%p,%p) ;
842 ]] ]
843
844
845
846local f_template_c = formatters [ [[
847setbounds currentpicture to multibox ;
848 ]] ]
849
850local function freemultipar ( pagedata , frees )
851
852
853
854
855 if not frees then
856 return
857 end
858 local nfree = # frees
859 if nfree = = 0 then
860 return
861 end
862 for i = 1 , # pagedata do
863 local data = pagedata [ i ]
864 local area = data . area
865
866 if area then
867
868 local region = data . region
869 local y = 0
870
871 local areas = { }
872 data . areas = areas
873
874 local f_1 = { }
875 local n_1 = 0
876 local f_2 = { }
877 local n_2 = 0
878 for i = 1 , # frees do
879 local f = frees [ i ]
880 local k = f . k
881 if k = = 1 then
882 n_1 = n_1 + 1
883 f_1 [ n_1 ] = f
884 elseif k = = 2 or k = = 3 then
885 n_2 = n_2 + 1
886 f_2 [ n_2 ] = f
887 end
888 end
889
890 local lineheight = tex . dimen . lineheight
891
892
893
894 local function check_one ( free1 , free2 )
895 local temp = { }
896 local some = false
897 local top = ( free2 and ( y + free2 . y + free2 . h + ( free2 . to or 0 ) ) ) or false
898 local bot = ( free1 and ( y + free1 . y - free1 . d - ( free1 . bo or 0 ) ) ) or false
899 for i = 1 , # area do
900 local a = area [ i ]
901 local x = a [ 1 ]
902 local y = a [ 2 ]
903 if free2 and y < = top then
904 y = top
905 end
906 if free1 and y > = bot then
907 y = bot
908 end
909 if not some then
910 some = y
911 elseif some = = true then
912
913 elseif y ~ = some then
914 some = true
915 end
916 temp [ i ] = { x , y }
917 end
918 if some = = true then
919 areas [ # areas + 1 ] = temp
920 end
921 end
922
923 if n_1 > 0 then
924 check_one ( false , f_1 [ 1 ] )
925 for i = 2 , n_1 do
926 check_one ( f_1 [ i -1 ] , f_1 [ i ] )
927 end
928 check_one ( f_1 [ n_1 ] , false )
929 end
930
931
932
933 if # areas = = 0 then
934 areas [ 1 ] = area
935 end
936
937
938
939 local function check_two ( area , frees )
940 local ul = area [ 1 ]
941 local ur = area [ 2 ]
942 local lr = area [ 3 ]
943 local ll = area [ 4 ]
944 local ulx = ul [ 1 ]
945 local uly = ul [ 2 ]
946 local urx = ur [ 1 ]
947 local ury = ur [ 2 ]
948 local lrx = lr [ 1 ]
949 local lry = lr [ 2 ]
950 local llx = ll [ 1 ]
951 local lly = ll [ 2 ]
952
953 local temp = { }
954 local n = 0
955 local done = false
956
957 for i = 1 , # frees do
958 local free = frees [ i ]
959 local fx = free . x
960 local fy = free . y
961 local ymax = y + fy + free . h + ( free . to or 0 )
962 local ymin = y + fy - free . d - ( free . bo or 0 )
963 local xmin = fx - ( free . lo or 0 )
964 local xmax = fx + free . w + ( free . ro or 0 )
965 if free . k = = 3 then
966 if uly < = ymax and uly > = ymin and lly < = ymin then
967 if trace_free then
968 report_free ( " case 1, top, right " )
969 end
970 n = n + 1 temp [ n ] = { xmin , ury }
971 n = n + 1 temp [ n ] = { xmin , ymin }
972 n = n + 1 temp [ n ] = { lrx , ymin }
973 n = n + 1 temp [ n ] = { lrx , lry }
974 done = true
975 elseif uly > = ymax and lly < = ymin then
976 if trace_free then
977 report_free ( " case 2, outside, right " )
978 end
979 if uly - ymax < lineheight then
980 n = n + 1 temp [ n ] = { xmin , ury }
981 else
982 n = n + 1 temp [ n ] = { urx , ury }
983 n = n + 1 temp [ n ] = { urx , ymax }
984 end
985 n = n + 1 temp [ n ] = { xmin , ymax }
986 n = n + 1 temp [ n ] = { xmin , ymin }
987 n = n + 1 temp [ n ] = { lrx , ymin }
988 n = n + 1 temp [ n ] = { lrx , lry }
989 done = true
990 elseif lly < = ymax and lly > = ymin and uly > = ymax then
991 if trace_free then
992 report_free ( " case 3, bottom, right " )
993 end
994 if uly - ymax < lineheight then
995 n = n + 1 temp [ n ] = { xmin , ury }
996 else
997 n = n + 1 temp [ n ] = { urx , ury }
998 n = n + 1 temp [ n ] = { urx , ymax }
999 end
1000 n = n + 1 temp [ n ] = { xmin , ymax }
1001 n = n + 1 temp [ n ] = { xmin , lry }
1002 done = true
1003 elseif uly < = ymax and lly > = ymin then
1004 if trace_free then
1005 report_free ( " case 4, inside, right " )
1006 end
1007 n = n + 1 temp [ n ] = { xmin , uly }
1008 n = n + 1 temp [ n ] = { xmin , lly }
1009 done = true
1010 else
1011
1012 if trace_free then
1013 report_free ( " case 0, nothing " )
1014 end
1015 end
1016 end
1017 end
1018
1019 if not done then
1020 if trace_free then
1021 report_free ( " no right shape " )
1022 end
1023 n = n + 1 temp [ n ] = { urx , ury }
1024 n = n + 1 temp [ n ] = { lrx , lry }
1025 n = n + 1 temp [ n ] = { llx , lly }
1026 else
1027 done = false
1028 end
1029
1030 for i = # frees , 1 , -1 do
1031 local free = frees [ i ]
1032 local fx = free . x
1033 local fy = free . y
1034 local ymax = y + fy + free . h + ( free . to or 0 )
1035 local ymin = y + fy - free . d - ( free . bo or 0 )
1036 local xmin = fx - ( free . lo or 0 )
1037 local xmax = fx + free . w + ( free . ro or 0 )
1038 if free . k = = 2 then
1039 if uly < = ymax and uly > = ymin and lly < = ymin then
1040 if trace_free then
1041 report_free ( " case 1, top, left " )
1042 end
1043 n = n + 1 temp [ n ] = { ulx , ymin }
1044 n = n + 1 temp [ n ] = { xmax , ymin }
1045 n = n + 1 temp [ n ] = { xmax , uly }
1046 done = true
1047 elseif uly > = ymax and lly < = ymin then
1048 if trace_free then
1049 report_free ( " case 2, outside, left " )
1050 end
1051 n = n + 1 temp [ n ] = { llx , lly }
1052 n = n + 1 temp [ n ] = { llx , ymin }
1053 n = n + 1 temp [ n ] = { xmax , ymin }
1054 n = n + 1 temp [ n ] = { xmax , ymax }
1055 if uly - ymax < lineheight then
1056 n = n + 1 temp [ n ] = { xmax , uly }
1057 else
1058 n = n + 1 temp [ n ] = { llx , ymax }
1059 n = n + 1 temp [ n ] = { llx , uly }
1060 end
1061 done = true
1062 elseif lly < = ymax and lly > = ymin and uly > = ymax then
1063 if trace_free then
1064 report_free ( " case 3, bottom, left " )
1065 end
1066 n = n + 1 temp [ n ] = { xmax , lly }
1067 n = n + 1 temp [ n ] = { xmax , ymax }
1068 if uly - ymax < lineheight then
1069 n = n + 1 temp [ n ] = { xmax , uly }
1070 else
1071 n = n + 1 temp [ n ] = { llx , ymax }
1072 n = n + 1 temp [ n ] = { llx , uly }
1073 end
1074 done = true
1075 elseif uly < = ymax and lly > = ymin then
1076 if trace_free then
1077 report_free ( " case 4, inside, left " )
1078 end
1079 n = n + 1 temp [ n ] = { xmax , lly }
1080 n = n + 1 temp [ n ] = { xmax , uly }
1081 done = true
1082 else
1083
1084 end
1085 end
1086 end
1087
1088 if not done then
1089 if trace_free then
1090 report_free ( " no left shape " )
1091 end
1092 n = n + 1 temp [ n ] = { llx , lly }
1093 end
1094 n = n + 1 temp [ n ] = { ulx , uly }
1095
1096 return temp
1097 end
1098
1099 if n_2 > 0 then
1100 for i = 1 , # areas do
1101 local area = areas [ i ]
1102 if # area = = 4 then
1103 areas [ i ] = check_two ( area , f_2 )
1104 else
1105
1106 end
1107 end
1108 end
1109
1110 for i = 1 , # areas do
1111 finish ( areas [ i ] )
1112 end
1113
1114 end
1115
1116 end
1117end
1118
1119local function fetchmultipar ( n , anchor , page )
1120 local a = jobpositions . collected [ anchor ]
1121 if not a then
1122 report_graphics ( " missing anchor %a " , anchor )
1123 else
1124 local data = pbg [ n ]
1125 if not data then
1126 data = calculatemultipar ( n )
1127 pbg [ n ] = data
1128
1129 end
1130 local list = data and data . list
1131 if list then
1132 local pagedata = list [ page ]
1133 if pagedata then
1134 local k = data . bpos . k
1135 if k ~ = 3 then
1136
1137 freemultipar ( pagedata , getfree ( page ) )
1138 end
1139 local nofmultipars = # pagedata
1140 if trace_shapes then
1141 report_graphics ( " fetching %a at page %s using anchor %a containing %s multipars " ,
1142 n , page , anchor , nofmultipars )
1143 end
1144 local x = a . x
1145 local y = a . y
1146 local w = a . w
1147 local h = a . h
1148 local d = a . d
1149 local bpos = data . bpos
1150 local bh = bpos . h
1151 local bd = bpos . d
1152 local result = { false }
1153 local n = 0
1154 for i = 1 , nofmultipars do
1155 local data = pagedata [ i ]
1156 local location = data . location
1157 local region = data . region
1158 local areas = data . areas
1159 if not areas then
1160 areas = { data . area }
1161 end
1162 for i = 1 , # areas do
1163 local area = areas [ i ]
1164 for i = 1 , # area do
1165 local a = area [ i ]
1166 area [ i ] = f_pair ( a [ 1 ] , a [ 2 ] )
1167 end
1168 n = n + 1
1169 result [ n + 1 ] = f_template_b ( n , multilocs [ location ] , n , location , n , area , x , y )
1170 end
1171 end
1172 data [ page ] = nil
1173 result [ 1 ] = f_template_a ( n , w , h + d , bh , bd , bh + bd )
1174 result [ n + 2 ] = f_template_c ( )
1175 return concat ( result , " \n " )
1176 end
1177 end
1178 end
1179 return f_template_a ( 0 , 0 , 0 , 0 , 0 , 0 ) ;
1180end
1181
1182backgrounds . fetchmultipar = fetchmultipar
1183
1184backgrounds . point = f_point
1185backgrounds . pair = f_pair
1186backgrounds . path = f_path
1187
1188
1189
1190implement {
1191 name = " fetchmultipar " ,
1192 actions = { fetchmultipar , context } ,
1193 arguments = { " string " , " string " , " integer " }
1194}
1195
1196local f_template_a = formatters [ [[
1197path posboxes[], posregions[] ;
1198numeric pospages[] ;
1199numeric nofposboxes ;
1200nofposboxes := %s ;
1201%t ;
1202 ]] ]
1203
1204local f_template_b = formatters [ [[
1205pospages[%s] := %s ;
1206posboxes[%s] := (%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle ;
1207posregions[%s] := (%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle ;
1208 ]] ]
1209
1210implement {
1211 name = " fetchposboxes " ,
1212 arguments = { " string " , " string " , " integer " } ,
1213 actions = function ( tags , anchor , page )
1214 local collected = jobpositions . collected
1215 if type ( tags ) = = " string " then
1216 tags = utilities . parsers . settings_to_array ( tags )
1217 end
1218 local list = { }
1219 local nofboxes = 0
1220 for i = 1 , # tags do
1221 local tag = tags [ i ]
1222 local c = collected [ tag ]
1223 if c then
1224 local r = c . r
1225 if r then
1226 r = collected [ r ]
1227 if r then
1228 local rx = r . x
1229 local ry = r . y
1230 local rw = r . w
1231 local rh = r . h
1232 local rd = r . d
1233 local cx = c . x - rx
1234 local cy = c . y
1235 local cw = cx + c . w
1236 local ch = cy + c . h
1237 local cd = cy - c . d
1238 nofboxes = nofboxes + 1
1239 list [ nofboxes ] = f_template_b (
1240 nofboxes , c . p ,
1241 nofboxes , cx , ch , cw , ch , cw , cd , cx , cd ,
1242 nofboxes , 0 , rh , rw , rh , rw , rd , 0 , rd
1243 )
1244 end
1245 end
1246 else
1247
1248 end
1249 end
1250 context ( f_template_a ( nofboxes , list ) )
1251 end
1252}
1253
1254local doifelse = commands . doifelse
1255
1256implement {
1257 name = " doifelserangeonpage " ,
1258 arguments = { " string " , " string " , " integer " } ,
1259 actions = function ( first , last , page )
1260 local c = jobpositions . collected
1261 local f = c [ first ]
1262 if f then
1263 f = f . p
1264 if f and f ~ = true and page > = f then
1265 local l = c [ last ]
1266 if l then
1267 l = l . p
1268 doifelse ( l and l ~ = true and page < = l )
1269 return
1270 end
1271 end
1272 end
1273 doifelse ( false )
1274 end
1275}
1276 |