details-textbackgrounds.tex /size: 21 Kb    last modification: 2023-12-21 09:43
1% language=us
2
3\environment details-environment
4
5\startcomponent details-textbackgrounds
6
7\start \setuphead [chapter] [after=] \startchapter[title={Backgrounds behind text}]
8
9\startbuffer[setup-a]
10\definetextbackground
11  [intro]
12  [backgroundcolor=infogray,
13   backgroundoffset=.25cm,
14   frame=off,
15   location=paragraph,
16   color=red]
17\stopbuffer
18
19\startbuffer[setup-b]
20\definetextbackground
21  [subintro]
22  [backgroundcolor=textgray,
23   backgroundoffset=0pt,
24   frame=off,
25   location=text,
26   color=blue]
27\stopbuffer
28
29\startbuffer[demo-a]
30\starttextbackground[intro]
31A rather common way to draw attention to a passage, is to add a
32background. In this chapter we will therefore discuss how to enhance your
33document with \starttextbackground [subintro] those colorful areas that either
34or not follow the shape of your paragraph. \stoptextbackground\ Be
35warned: this chapter has so many backgrounds that you might start to
36dislike them.
37\stoptextbackground
38\stopbuffer
39
40\getbuffer[setup-a,setup-b,demo-a]
41
42\blank
43
44In the previous paragraph we demonstrated two important features of the
45background handler: you can nest backgrounds and backgrounds can be tight or
46wide. Features like this will often be used in combination with others, like
47special section headers. The raw coding of the previous paragraph is therefore
48not representative.
49
50\typebuffer[demo-a]
51
52The outer background commands is defined as follows:
53
54\typebuffer[setup-a]
55
56Here, the \type {paragraph} option ensures that the background covers the width
57of the body text. The inner background is defined in a similar way, but this time
58we choose \type {text} location.
59
60\typebuffer[setup-b]
61
62In this document we use protruding characters (hanging punctuation) so we've
63chosen a rather large offset, one that also matches the rest of the page design.
64
65Those who are familiar with the way \TEX\ works will probably see what problems
66can occur with backgrounds like this. What happens for instance when we cross
67page boundaries, and how will more complicated paragraph shapes be handled?
68
69The current implementation tries to handle page breaks and paragraph shapes as
70good as possible. This works well in normal one||column mode as well as in
71columns.
72
73\startbuffer[setup-c]
74\definetextbackground [A] [backgroundcolor=infogray]
75\definetextbackground [B] [backgroundcolor=textgray]
76
77\setuptextbackground
78  [backgroundoffset=0pt,
79   offset=0pt,
80   frame=off,
81   location=text]
82\stopbuffer
83
84\getbuffer[setup-c]
85
86\startbuffer[demo-b]
87\placefigure[left]{}{\externalfigure[detcow][width=2cm]}
88
89\starttextbackground [A]
90  In this example, the paragraph shape is determined by the graphic placed
91  left of the text.
92    \starttextbackground [B]
93      This feature is implemented using the \type {\hangindent} and \type
94      {\hangafter} primitives, which means that we need to keep track of
95      their state. In addition, we need to handle the indentation directives
96      \type {\leftskip}, \type {\rightskip} and \type {\parindent}.
97    \stoptextbackground\
98  Because backgrounds end up in a different background overlay, nesting
99  them is no problem, and it is even possible to move them to the front
100  and back, as we will demonstrate later on. While the mechanism discussed
101  here will always be improved when we find border cases, the fundaments
102  it is built upon are quite stable.
103\stoptextbackground
104\stopbuffer
105
106{\setupalign[nothanging]\getbuffer[demo-b]\par}
107
108\typebuffer[demo-b]
109
110The backgrounds were defined as:
111
112\typebuffer[setup-c]
113
114\startbuffer[setup-d]
115\setuptextbackground [B] [backgroundcolor=darkgray,level=+2]
116\stopbuffer
117
118{\setupalign[nothanging]\getbuffer[setup-d,demo-b]\par}
119
120This time we moved the inner background a few levels up. By default they reside
121at \type {level=-1}. This way, by using a non transparent color, we can hide
122information.
123
124\typebuffer[setup-d]
125
126Unless you mess around too much with boxes, backgrounds work as expected in most
127situations. According to the Merriam||Webster on the authors laptop:
128
129\startbuffer
130\starttabulate[|l|p|l|]
131\NC background \NC \starttextbackground [A] the part of a
132    painting representing what lies behind objects is the
133    \starttextbackground [B] foreground \stoptextbackground
134    \stoptextbackground \NC one \NC \NR
135\TB [halfline]
136\NC foreground \NC \starttextbackground [A] the part of a
137    scene or representation that is nearest to and in front
138    of the \starttextbackground [B] spectator
139    \stoptextbackground \stoptextbackground \NC two \NC \NR
140\TB [halfline]
141\NC spectator \NC  \starttextbackground [A] one who looks
142    on or watches \stoptextbackground \NC three \NC \NR
143\stoptabulate
144\stopbuffer
145
146\getbuffer
147
148This is coded similar to normal running text. A table like this is in a way still
149part of the text flow. As floating body (see \in {table} [tab:back]) it can
150virtually end up everywhere. We add a frame to make clear where the boundaries are.
151
152\start
153
154    \setupfloat
155      [table]
156      [frame=on,framecolor=red,rulethickness=1pt]
157
158    \placetable
159      [here] [tab:back]
160      {} {\hsize.75\textwidth\getbuffer}
161
162    \definefloat
163        [mytable]
164        [table]
165
166    \setupfloat
167        [mytable]
168        [leftmargindistance=-\innermargintotal]
169
170    \placemytable
171        [left,high,low]
172        [tab:back-m]
173        {}
174        {\hsize.5\textwidth\getbuffer}
175
176    Keeping track of the state of a paragraph in a table in combination with
177    background is not entirely trivial. The current implementation evolved from
178    less clever ones and, unless you start doing complicated box manipulations
179    with the float content, works quite well. One reason why we made backgrounds
180    work in tables (and especially floating tables) is that is was needed for
181    typesetting books for primary and secundary education. In there, we want to
182    be able to hide the answers that students are supposed to fill in.
183
184    \flushsidefloats
185
186\stop
187
188In \in {figure} [fig:columns:1] you can see an advanced example of backgrounds
189running over columns. If you look carefully, you will notice that the background
190depends on the kind of background at hand:
191
192\startitemize[n,packed]
193\item the text starts and flows on
194\item the text flows on (or stands alone)
195\item the text flows on and ends
196\stopitemize
197
198This information is available when you want to draw your own backgrounds. Here
199the graphic was defined as follows:
200
201\startplacefigure [reference=fig:columns:1]
202    \startcombination[4*1]
203          {\externalfigure[back-4.pdf][page=1,width=\distributedhsize\textwidth\emwidth4]}{Page 1}
204          {\externalfigure[back-4.pdf][page=2,width=\distributedhsize\textwidth\emwidth4]}{Page 2}
205          {\externalfigure[back-4.pdf][page=3,width=\distributedhsize\textwidth\emwidth4]}{Page 3}
206          {\externalfigure[back-4.pdf][page=4,width=\distributedhsize\textwidth\emwidth4]}{Page 4}
207    \stopcombination
208\stopplacefigure
209
210\starttyping
211\startuseMPgraphic{mpos:par:color}
212  for i=1 upto nofmultipars :
213    fill multipars[i] withcolor
214      if     multikind[i]="single" : "darkgray" ;
215      elseif multikind[i]="first"  : "red" ;
216      elseif multikind[i]="middle" : "green" ;
217      elseif multikind[i]="last"   : "blue" ;
218      else                         : "black" ;
219      fi ;
220  endfor ;
221\stopuseMPgraphic
222\stoptyping
223
224This graphic is hooked into the background setup by setting the \type {mp}
225variable.
226
227\starttyping
228\definetextbackground
229  [shade]
230  [location=paragraph,
231   mp=mpos:par:color,
232   before=\blank,
233   after=\blank]
234\stoptyping
235
236A variant is the following. This time we use a shade:
237
238\starttyping
239\startuseMPgraphic{mpos:par:columnset:shade}
240  numeric h ;
241  for i=1 upto nofmultipars :
242    h := bbheight(p) ;
243    if multikind[i] = "single" :
244      fill multipars[i] topenlarged -.5h
245        withshademethod "linear"
246        withshadedirection shadedup
247        withcolor boxfillcolor shadedinto .8white ;
248      fill multipars[i] bottomenlarged -.5h
249        withshademethod "linear"
250        withshadedirection shadedup
251        withcolor .8white shadedinto boxfillcolor ;
252    elseif multikind[i] = "first" :
253      fill multipars[i]
254        withshademethod "linear"
255        withshadedirection shadedup
256        withcolor boxfillcolor shadedinto .8white ;
257    elseif multikind[i] = "middle" :
258      fill multipars[i] topenlarged -.5h
259        withshademethod "linear"
260        withshadedirection shadedup
261        withcolor boxfillcolor shadedinto .8white ;
262      fill multipars[i] bottomenlarged -.5h
263        withshademethod "linear"
264        withshadedirection shadedup
265        withcolor .8white shadedinto boxfillcolor ;
266    elseif multikind[i] = "last" :
267      fill multipars[i]
268        withshademethod "linear"
269        withshadedirection shadedup
270        withcolor .8white shadedinto boxfillcolor ;
271    fi ;
272  endfor ;
273\stopuseMPgraphic
274\stoptyping
275
276When we hook it into the background we get \in {figure} [fig:columns:2] as result:
277
278\starttyping
279\definetextbackground
280  [shade]
281  [location=paragraph,
282   backgroundcolor=shadecolor,
283   mp=mpos:par:columnset:shade,
284   before=\blank,
285   after=\blank]
286\stoptyping
287
288\startplacefigure [reference=fig:columns:2]
289    \startcombination[4*1]
290          {\externalfigure[back-5.pdf][page=1,width=\distributedhsize\textwidth\emwidth4]}{Page 1}
291          {\externalfigure[back-5.pdf][page=2,width=\distributedhsize\textwidth\emwidth4]}{Page 2}
292          {\externalfigure[back-5.pdf][page=3,width=\distributedhsize\textwidth\emwidth4]}{Page 3}
293          {\externalfigure[back-5.pdf][page=4,width=\distributedhsize\textwidth\emwidth4]}{Page 4}
294    \stopcombination
295\stopplacefigure
296
297The complexity of the backgrounds mechanism is partly due to the fact that we
298want to use arbitrary \METAPOST\ code to render the background. For instance, we
299want to have a proper shape so that not only the filled shape but also the drawn
300shape comes out right. You can compare this to a glyph in a font: when rendered
301filled the outline can be anything as it will not be drawn but when we use the
302outline we can run into overlaps and such. Where glyphs can use the odd|-|even
303filling methods, background can only use that for simple cases.
304
305When a background is rectangular it's all quite easy but as soon as some holes
306occur we need to do more work. Holes can be the result of a image placed next to
307the running text, or an image flushed at a page break or in the middle of a
308background. Paragraph shapes are another example. Backgrounds can cross page
309boundaries too. Yet another property is nesting and in such cases the shape is
310a bit more complex as we cross lines partially.
311
312In \MKII\ the background mechanism already was quite useable but it had some
313limitations. Calculating the background was mostly delegated to \METAPOST\ which
314is reasonable. In \MKIV\ some work is delegated to \LUA\ instead but that doesn't
315mean that the code is cleaner or easier to understand. So, to summarize, there
316are several cases that we need to take into account, like:
317
318\startitemize
319    \startitem
320        A background can run behind a paragraph in which case the start is
321        leftmost and end rightmost. In this case inserts (like floats) have to be
322        dealt with after the shape has been calculated.
323    \stopitem
324    \startitem
325        A background can be in|-|line (the \type {text} location variant) in
326        which case we need to follow the paragraph shape, if set. In that case we
327        have a mix of calculating the background shape and afterwards
328        compensating for inserts.
329    \stopitem
330    \startitem
331        A third case is tabulation and tables where we have dedicated regions to
332        deal with. When these float we need to make sure that the backgrounds are
333        adapted to the where they end up.
334    \stopitem
335    \startitem
336        Yet another case is in columns, where we hape multiple regions to deal
337        with.
338    \stopitem
339    \startitem
340        As mentioned, floats need special treatment and they can be part of the
341        page flow but also end up left or right of the text (either or not
342        shifted) but also in the margins, edges, back- or cutspace. Their
343        placement influences the way backgrounds are calculated so additional
344        information needs to travel with them.
345    \stopitem
346
347\stopitemize
348
349We distinguish between a paragraph background, which runs between the left and right skip
350areas and a text background which follows a shape. In \in {figure} [fig:columns:3] we see a
351test case with several such shapes.
352
353\startplacefigure [reference=fig:columns:3]
354    \startcombination[4*3]
355          {\externalfigure[back-2.pdf][page=1, width=\distributedhsize\textwidth\emwidth4]}{Page  1}
356          {\externalfigure[back-2.pdf][page=2, width=\distributedhsize\textwidth\emwidth4]}{Page  2}
357          {\externalfigure[back-2.pdf][page=3, width=\distributedhsize\textwidth\emwidth4]}{Page  3}
358          {\externalfigure[back-2.pdf][page=4, width=\distributedhsize\textwidth\emwidth4]}{Page  4}
359          {\externalfigure[back-2.pdf][page=5, width=\distributedhsize\textwidth\emwidth4]}{Page  5}
360          {\externalfigure[back-2.pdf][page=6, width=\distributedhsize\textwidth\emwidth4]}{Page  6}
361          {\externalfigure[back-2.pdf][page=7, width=\distributedhsize\textwidth\emwidth4]}{Page  7}
362          {\externalfigure[back-2.pdf][page=8, width=\distributedhsize\textwidth\emwidth4]}{Page  8}
363          {\externalfigure[back-2.pdf][page=9, width=\distributedhsize\textwidth\emwidth4]}{Page  9}
364          {\externalfigure[back-2.pdf][page=10,width=\distributedhsize\textwidth\emwidth4]}{Page 10}
365          {\externalfigure[back-2.pdf][page=11,width=\distributedhsize\textwidth\emwidth4]}{Page 11}
366          {\externalfigure[back-2.pdf][page=12,width=\distributedhsize\textwidth\emwidth4]}{Page 12}
367    \stopcombination
368\stopplacefigure
369
370In the case of side floats the following cases occur. Of course multiple such
371cases can follow each order so in practice we have to deal with an accumulation.
372
373\startlinecorrection[blank]
374\startMPcode
375    linejoin := linecap := butt ;
376
377    numeric u  ; u  := 1mm ;
378    numeric lw ; lw := u/2 ;
379
380    pickup pencircle scaled 2lw ;
381
382    def example (expr n) (text t) (text l) =
383        path b ; b := boundingbox image (
384            for i=t : draw ( 0u,i*2u) -- (20u,i*2u) ; endfor ;
385            for i=l : draw ( 0u,i*2u) -- (20u,i*2u) ; endfor ;
386        ) ;
387        picture p ; p := image (
388            for i=t : draw ( 0u,i*2u) -- (20u,i*2u) ; endfor ;
389            for i=l : draw (11u,i*2u) -- (20u,i*2u) ; endfor ;
390        ) ;
391        setbounds p to b ;
392        path q ; q := unitsquare xysized(10u,10u) shifted (0,4u) ;
393        draw image (
394            fill boundingbox p leftenlarged -lw rightenlarged -lw withcolor "blue" ;
395            draw p withcolor .5white ;
396            fill q withcolor "red"  ;
397            draw textext("\bf " & decimal n) shifted (center q) withcolor white ;
398        ) shifted ((n-1)*30u,0) ;
399    enddef ;
400
401    example (1) (1)   (2,3,4)       ;
402    example (2) (1,8) (2,3,4,5,6,7) ;
403    example (3) (8)   (5,6,7)       ;
404    example (4) ()    (3,4,5,6)     ;
405
406    currentpicture := currentpicture ysized(3*LineHeight- StrutDepth) ;
407
408\stopMPcode
409\stoplinecorrection
410
411As often in \TEX\ coming up with a solution is not a the problem but interference
412is. You can cook up a solution for one case that fails in another. Backgrounds
413fall into this category, as do side floats. In the next pages we will demonstrate
414a few cases. In practice you can probably always come up with something that
415works out well, but in an automated workflow (like unattended \XML\ to \PDF\
416conversion) you can best play safe. We show some examples on the next pages.
417
418\blank
419
420\definetextbackground
421  [demobg]
422  [backgroundcolor=blue,
423   color=white,
424   frame=off,
425   location=paragraph]
426
427\setupfloatcaption
428  [color=black]
429
430\definesimulatewords
431  [demo]
432  [n=50,
433   m=\simulatewordsparameter{n},
434   min=1,
435   max=5,
436   color=text,
437   line=yes,
438   random=100]
439
440\startbuffer
441\placefigure
442  [left]
443  {case 1}
444  {\blackrule[width=12cm,height=1cm,color=red]}
445\simulatewords[demo][n=10]
446\starttextbackground[demobg]
447    \simulatewords[demo][n=30]
448\stoptextbackground
449\flushsidefloats
450
451\blank
452
453\starttextbackground[demobg]
454    \simulatewords[demo][n=40]
455    \placefigure
456      [left]
457      {case 2}
458      {\blackrule[width=12cm,height=1cm,color=red]}
459    \simulatewords[demo][n=40]
460\stoptextbackground
461\flushsidefloats
462
463\blank
464
465\placefigure
466  [left]
467  {case 3}
468  {\blackrule[width=4cm,height=15mm,color=red]}
469\starttextbackground[demobg]
470    \simulatewords[demo][n=40]
471\stoptextbackground
472\simulatewords[demo][n=40]
473\flushsidefloats
474
475\blank
476
477\simulatewords[demo][n=35]
478\placefigure
479  [left]
480  {case 4}
481  {\blackrule[width=4cm,height=1cm,color=red]}
482\simulatewords[demo][n=20]
483\starttextbackground[demobg]
484    \simulatewords[demo][n=25]
485\stoptextbackground
486\simulatewords[demo][n=40]
487\flushsidefloats
488
489\blank
490
491\stopbuffer
492
493\start \setupwhitespace[none] \getbuffer \stop \blank
494
495The previous examples were typeset with:
496
497\typebuffer
498
499Regular (page flow) floats are a different story. Here we have the problem that a
500float might be postpones because there is no room on the current page and they
501are moved forward (which is why they're called float). Again we show some
502examples.
503
504% \page
505
506\startbuffer[sample]
507One problem introduced by the internet is that one can view music online. Well,
508it's actually not really a problem as it is fun to do, but it does interfere with
509development of code: one can enter distraction mode quite easily.
510\stopbuffer
511
512\startbuffer
513\starttextbackground[demobg]
514    \par \getbuffer[sample] \par
515    \placefigure{}{\blackrule[width=4cm,height=1cm,color=red]}
516    \par \getbuffer[sample] \par
517    \placefigure{}{\blackrule[width=4cm,height=3cm,color=red]}
518    \par \getbuffer[sample] \par
519    \placefigure{}{\blackrule[width=4cm,height=2cm,color=red]}
520    \par \getbuffer[sample] \par
521\stoptextbackground
522\stopbuffer
523
524\blank \getbuffer \blank
525
526The input is:
527
528\typebuffer
529
530A combination of both background avoiding mechanisms is shown on the next page
531(we flush a few more grapohics so that we cross a page boundary):
532
533% \page
534
535\startbuffer
536\starttextbackground[demobg]
537    \placefigure{}{\blackrule[width=4cm,height=2cm,color=red]}
538    \par \input ward \par
539    \placefigure[left]{}{\blackrule[width=4cm,height=2cm,color=red]}
540    \par \input ward \par
541    \placefigure{}{\blackrule[width=4cm,height=2cm,color=red]}
542    \placefigure{}{\blackrule[width=4cm,height=2cm,color=red]}
543    \placefigure{}{\blackrule[width=4cm,height=2cm,color=red]}
544    \placefigure{}{\blackrule[width=4cm,height=2cm,color=red]}
545    \placefigure{}{\blackrule[width=4cm,height=2cm,color=red]}
546    \placefigure{}{\blackrule[width=4cm,height=2cm,color=red]}
547    \par \input ward \par
548    \placefigure{}{\blackrule[width=4cm,height=2cm,color=red]}
549    \par \input ward \par
550\stoptextbackground
551\stopbuffer
552
553\blank \getbuffer \blank
554
555This is the result from:
556
557\typebuffer
558
559You can control the interaction between backgrounds and floars with the \type
560{freeregion} parameter.
561
562\startbuffer
563\starttextbackground[demobg]
564    \simulatewords[demo][n=40]
565    \startplacefigure
566      [location=left,
567       title={free}]
568        \blackrule[width=12cm,height=1cm,color=red]
569    \stopplacefigure
570    \simulatewords[demo][n=40]
571    \startplacefigure
572      [location=left,
573       title={non|-|free},
574       freeregion=no,
575       color=textcolor]
576        \blackrule[width=12cm,height=1cm,color=red]
577    \stopplacefigure
578    \simulatewords[demo][n=40]
579    \startplacefigure
580      [location=here,
581       title={free}]
582        \blackrule[width=12cm,height=1cm,color=red]
583    \stopplacefigure
584    \simulatewords[demo][n=40]
585    \startplacefigure
586      [location=here,
587       title={non|-|free},
588       freeregion=no,
589       color=textcolor]
590        \blackrule[width=12cm,height=1cm,color=red]
591    \stopplacefigure
592    \simulatewords[demo][n=40]
593\stoptextbackground
594\stopbuffer
595
596\typebuffer
597
598The next pages show the result, first with some tracing enabled sop that you
599can see what gets freed. This visual effect is enabled with:
600
601\starttyping
602\enabletrackers[floats.freeregion]
603\stoptyping
604
605We now move to the next page.
606
607\page
608    \getbuffer
609\page
610    \enabletrackers[floats.freeregion]
611    \getbuffer
612    \disabletrackers[floats.freeregion]
613\page
614
615We have some control over side float placement and of course that will interfere
616with backgrounds. Say that we have this:
617
618\startbuffer
619\definefloat
620  [demofigureleft]
621  [figure]
622  [default=left,
623  margin=1cm,
624   leftmargindistance=2cm,
625   rightmargindistance=2cm]
626
627\definefloat
628  [demofigureright]
629  [demofigureleft]
630  [default=right]
631\stopbuffer
632
633\typebuffer \getbuffer
634
635Combined with the following we get the result on the next pages.
636
637\startbuffer
638\starttextbackground[demobg]
639    \startplacefloat[figure][location=left]
640        \blackrule[width=12cm,height=1cm,color=red]
641    \stopplacefigure
642    \simulatewords[demo][n=40]
643    \blank
644    \startplacefloat[figure][location=right]
645        \blackrule[width=12cm,height=1cm,color=red]
646    \stopplacefigure
647    \simulatewords[demo][n=40]
648    \blank
649    \startplacefloat[demofigureleft]
650        \blackrule[width=10cm,height=1cm,color=red]
651    \stopplacefigure
652    \simulatewords[demo][n=40]
653    \blank
654    \startplacefloat[demofigureright]
655        \blackrule[width=10cm,height=1cm,color=red]
656    \stopplacefigure
657    \simulatewords[demo][n=40]
658    \startplacefloat[figure] % [freeregion=no]
659        \blackrule[width=12cm,height=1cm,color=red]
660    \stopplacefigure
661    \simulatewords[demo][n=40]
662\stoptextbackground
663\stopbuffer
664
665\typebuffer
666
667\page
668
669\start
670    \enabletrackers[floats.freeregion]
671    \setupwhitespace[none]
672    \getbuffer
673    \disabletrackers[floats.freeregion]
674\stop
675
676\page
677
678\start
679    \setupwhitespace[none]
680    \getbuffer
681\stop
682
683\page
684
685\stop \stopchapter
686
687\stopcomponent
688