Re: Keep-with-next handling

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

Re: Keep-with-next handling

Luca Furini-2
Jeremias Maerki wrote:

> Could work for most cases although it would probably be difficult again
> on tables and a little less so on lists. I had to do some special stuff
> on tables and have still not solved everything. For example:
> +---------------+----------------+
> | cell1 line1   | cell2 line1    |
> |               | cell2 line2    |
> +---------------+----------------+
> | cell3 line1   | cell4 line1    |
> +---------------+----------------+
> A keep-with-previous on the second row should create a "glue" (not a
> knuth glue) not only between cell2 line2 and cell4 line1 but also
> between cell2 line1 and cell3 line1. This means that in the combined
> element list you get multiple infinite penalties. Your alternative
> approach might really help here. But I keep coming to the conclusion
> that I might have to get the cell content element lists of the following
> row (group) before I can finish the combined element list for the
> current one (because you might have a keep-with-previous in there).

As the combined list is created for a single row group at a time, I think
that the presence of keeps could be signaled using a couple of boolean
     getCombinedKnuthElementsForRowGroup(..., bKeepWithPrevious, bKeepWithNext)

In order to compute this boolean values, it should be enough to look for
keep constraints in the first and last cell LM of each column in the row
group; for example, if the table has M columns
     bKeepWithPrevious = cell[1,1].mustKeepWithPrevious()
                         || cell[1,2].mustKeepWithPrevious()
                         || ...
                         || cell[1,M].mustKeepWithPrevious()
     bKeepWithNext = cell[N,1].mustKeepWithNext()
                     || cell[P,2].mustKeepWithNext()
                     || ...
                     || cell[Q,M].mustKeepWithNext()
where N,P and Q are the last row indexes in the first, second and last
column (which could be different if there are row spans).

During the creation of the combined list:
  - if there is a keep-with-previous, the first step must be get something
from each column (it must be the greater among the column steps);
  - if there is a keep-with-next, the last step must be "synchronized"
between all columns: is is allowed to place the last fragment of a column
only if it will create the last combined element.

So, if a row group has both keep-with-previous and keep-with-next and one
of the columns contains just a single line (or a single group of lines
that cannot be parted) the combined list will have just a single step and
no inner breaking points.

The synchronization of the last step could be achieved this way:

     // initializations

     bSynchronizeLastStep = bKeepWithNext
     for (each column) {
         // compute normally the width of the next sub-sequence
         if (bKeepWithNext
             && we have reached the end of the column sequence) {
             // signal this is the last step, for example
             width[i] = -width[i]
         } else {
             bLastStep = false

     if (bSynchronizeLastStep) {
         // take the "greater" last step
         step = - min{width[i]};
     } else {
         // the normal behaviour

This is not enough: if there are both a keep-with-previus constraint and a
keep-with-next constraint, the whole process could be performed several
times until the computed step is ok (because a column could have inner
breaking points while another has none):

     bStepOk = false;
     while (!bStepOK) {
         // step computation

         bStepOK = true;
         if ((this is the first step)
             && bKeepWithPrevious) {
             for (each column) {
                 bStepOk = bStepOk
                     && (the remaining width is < than the total width)

Sorry for the long message, but everything seems quite complicated when
applied to tables! :-)

I also must add that these are just thoughts: as I did not yet try and
implement them, they could prove to be completely wrong.